Ошибка 404 при использовании API графа из консольного приложения c # - PullRequest
0 голосов
/ 28 июня 2019

В настоящее время я пытаюсь аутентифицировать Graph API, используя мой C #.Я могу запросить этот API и успешно получить токен от Postman. Но когда я вызываю тот же API, я получаю ошибку 404.

Мой код такой, как показано ниже:

using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace GraphTest
{
    public class AuthenticationModel
    {
        public string grantType { get; set; } = "client_credentials";
        public string clientId { get; set; } = "my_ad_app_id";
        public string clientSecret { get; set; } = "client_secret";
        public string scope { get; set; } = "https://graph.microsoft.com/.default";
    } 
    public class Authentication
    {
        private static string tenantId = "tenant_id";
        private static readonly HttpClient Client = new HttpClient();
        public Authentication()
        {
           var authenticationModel = new AuthenticationModel();
           RunAsync().GetAwaiter().GetResult();
        }

        private static async Task RunAsync()
        {
            Client.BaseAddress = new Uri("https://login.microsoftonline.com/");
            Client.DefaultRequestHeaders.Accept.Clear();
            Client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("*/*"));
            Client.DefaultRequestHeaders.Add("Host", "login.microsoftonline.com");
            Client.DefaultRequestHeaders.Add("Cache-Control", "no-cache");

            try
            {
                var authenticationModel = new AuthenticationModel();
                var url = await GetTokenAsync(authenticationModel);
                Console.WriteLine($"Created at {url}");
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message);
            }
        }

        private static async Task<Uri> GetTokenAsync(AuthenticationModel authenticationModel)
        {
            var keyValues = authenticationModel.GetType().GetProperties()
                .ToList()
                .Select(p => $"{p.Name} = {p.GetValue(authenticationModel)}")
                .ToArray();
            var xUrlEncodedBody = string.Join('&', keyValues);
            var response = await Client.PostAsJsonAsync(
                $"{tenantId}/oauth2/v2.0/token", xUrlEncodedBody);
            response.EnsureSuccessStatusCode();

            return response;
        }
    }
}

Итак,Я получаю это в ответ: StatusCode:404, ReasonPhrase:Not Found Пожалуйста, помогите мне узнать, что, где я делаю это неправильно.

Примечание: API с теми же данными прекрасно работает с Почтальоном.Хотя я заменил некоторые значения здесь из соображений безопасности.

Ответы [ 2 ]

1 голос
/ 28 июня 2019

Вы не должны публиковать URL-адрес, закодированный в формате JSON (PostAsJsonAsync). Тело должно иметь тип содержимого application/x-www-form-urlencoded.

Но, резервируя секунду, вам не нужно реализовывать протокол самостоятельно, когда есть библиотеки, которые делают это за вас :). Мы предоставляем и поддерживаем Microsoft Authentication Library (MSAL) , которая облегчает эту задачу.

var app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
              .WithTenantId("{tenantID}")
              .WithClientSecret(config.ClientSecret)
              .Build();

string[] scopes = new string[] { "https://graph.microsoft.com/.default" };

AuthenticationResult result = null;

try
{
    result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
}
catch (MsalServiceException ex)
{
    Console.WriteLine($"Error getting token: {ex.Message}");
}

Console.WriteLine($"Token: {result.AccessToken}");
0 голосов
/ 28 июня 2019

Я запустил ваш код, и он неправильно генерирует строку запроса, как показано ниже, с пробелами.

xUrlEncodedBody => grantType = client_credentials&clientId = my_ad_app_id&clientSecret = client_secret&scope = https://graph.microsoft.com/.default

Между именем и значением параметра запроса есть пробел, см. Строку ниже.

.Select(p => $"{p.Name} = {p.GetValue(authenticationModel)}")

Уберите пробел и попробуйте снова

.Select(p => $"{p.Name}={p.GetValue(authenticationModel)}")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...