首页 > 解决方案 > 无法从 Azure AD 中的注册应用程序获取访问令牌

问题描述

我正在尝试在块管理器中从 Microsoft.Graph 实例化一个新的 GraphServiceClient 实例。

已经做了什么:

  1. 创建 ASP.NET Core 2.0 控制台应用程序
  2. 从 Nugget 添加 Micrososft.Graph
  3. 在 Azure AD 门户中注册应用以获取应用机密 ID(应用密码)和应用 ID(客户端 ID)
  4. 从 Azure AD 门户检索租户 ID(目录 ID)

基本上,这是我的 ASP.NET Core 2.0 项目(控制台应用程序)的全部代码:

using Microsoft.Graph;
using Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace SendADUserListEmail.Services
{
    // Response object from Azure AD
    public class AzureADResponse
    {
        public string token_type { get; set; }
        public int expires_in { get; set; }
        public string access_token { get; set; }
    }

    /// <summary>
    /// Micrososf Graph vs Azure AD Graph :
    /// https://blogs.msdn.microsoft.com/aadgraphteam/2016/07/08/microsoft-graph-or-azure-ad-graph/
    /// 
    /// Introduction to the Azure Active Directory Graph API :
    /// https://www.red-gate.com/simple-talk/cloud/security-and-compliance/azure-active-directory-part-5-graph-api/
    /// 
    /// ULTIMATE TUTORIAL ABOUT MICROSOFT GRAPH APIS
    /// https://bytescout.com/blog/microsoft-graph-apis.html
    /// 
    /// Startup !!! TO READ !!! :
    /// https://github.com/microsoftgraph/msgraph-sdk-dotnet
    /// 
    /// Creating the application Client ID and Client Secret from Microsoft Azure new portal
    /// - Register an application on Azure Portal : 
    /// - 1. Accèder au portail
    /// - 2. Inscription d'application
    /// - 3. Voir Paramètres > Propriétés
    /// https://www.netiq.com/communities/cool-solutions/creating-application-client-id-client-secret-microsoft-azure-new-portal/
    /// 
    /// Microsoft App Registration Portal (alternative method to register an app) :
    /// https://apps.dev.microsoft.com
    /// 
    /// Microsoft Graph explorer (graph request tester) :
    /// https://developer.microsoft.com/en-us/graph/graph-explorer
    /// </summary>
    class GraphApiHelper
    {
        // Client
        GraphServiceClient GraphServiceClient = null;

        // Tenant ID (directory ID)
        private const string tenantId = "/*MY_TENANT_ID_FROM_AZURE_AD_PORTAL*/";
        // App ID (client ID)
        private const string appId = "/*MY_APP_ID_FROM_AZURE_AD_PORTAL*/";
        // Secret ID (app password)
        private const string appSecret = "/*MY_APP_SECRET_FROM_AZURE_AD_PORTAL*/";

        public void Connexion()
        {
            string url = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
            string @params = $"client_id={appId}&" +
                "scope=User.Read&" +
                $"client_secret={appSecret}&" +
                "grant_type=client_credentials";

            try
            {
                string accessToken = "";
                string jsonStringResult = "";
                AzureADResponse response = new AzureADResponse();

                // Getting the access token from Azure AD
                using (WebClient webClient = new WebClient())
                {
                    webClient.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";

                    jsonStringResult = webClient.UploadString(url, @params);
                    response = JsonConvert.DeserializeObject<AzureADResponse>(jsonStringResult);

                    // Set the access token
                    accessToken = response.access_token;
                }

                // Initialize the Microsoft Graph client
                GraphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider((requestMessage) =>
                {
                    requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);

                    return Task.FromResult(0);
                }));
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message);
            }
        }

        public List<SystemUser> GetSystemUserList()
        {
            Connexion();

            return null;
        }
    }
}

尝试使用 System.Net.WebClient 执行发布请求时出现此错误:

string url = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
string @params = $"client_id={appId}&" +
            "scope=User.Read&" +
            $"client_secret={appSecret}&" +
            "grant_type=client_credentials";

jsonStringResult = webClient.UploadString(url, @params);

远程服务器返回错误:(400) 错误请求。

基于此来源:https ://docs.microsoft.com/en-us/graph/auth-v2-service 我想收到这样的东西:

{
  "token_type": "Bearer",
  "expires_in": 3599,
  "access_token": 
  "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBP..."
}

我需要的是初始化 GraphServiceClient 的访问令牌。

知道为什么 Microsoft Azure 在此请求上失败了吗?

标签: azurepostazure-active-directorymicrosoft-graph-apiaccess-token

解决方案


您应该遵循 juunas 的建议并使用像 ADAL 这样的库来为您做这件事。

如果您想自己调用以检索令牌,请首先通过测试来自 Postman 等工具的相同请求来验证问题来自您的代码,而不是来自您的应用程序注册。当您收到错误 400 时,它可能来自您的代码并且您的请求格式不正确。

我不习惯使用 WebClient 进行 http 调用,所以我不知道出了什么问题,但我会说它可能与您处理参数的方式有关。如果我是你,我会使用 HttpClient,你可以找到一些带有在 stackoverflow 中编码的表单 url 的查询示例(如何使用 HTTPclient 内容类型 = application/x-www-form-urlencoded 发布)。


推荐阅读