无法从 Azure AD 获取不记名令牌以用于 API 应用程序

Unable to get bearer token from Azure AD to use with API App

我有一个 MVC 应用程序需要访问 Azure 中受 Azure AD 身份验证保护的私有 API 应用程序。所以我需要获取 Azure AD 不记名令牌,将其转换为 Zumo-Auth 令牌并使用它来访问 API 应用程序。

我正在经历 this tutorial,一切正常,直到我需要从 authContext 请求令牌。这是代码片段:

var authContext = new AuthenticationContext(
    "https://login.microsoftonline.com/MyADDomain.onmicrosoft.com");

ClientCredential credential = new ClientCredential(
    "04472E33-2638-FAKE-GUID-F826AF4928DB", 
    "OMYAPIKEY1x3BLAHEMMEHEHEHEHEeYSOMETHINGRc=");

// Get the AAD token.
var appIdUri = 
    "https://MyAppGateway-814485545465FAKE4d5a4532cd.azurewebsites.net/login/aad";

//var appIdUri = "https://MyADDomain.onmicrosoft.com/MyAppName";
//var appIdUri = "https://MyADDomain.onmicrosoft.com/";
//var appIdUri = "https://graph.windows.net";

AuthenticationResult result = 
    authContext.AcquireToken(appIdUri, credential); // <-- can't get the token from AD

// downhill from here
var aadToken = new JObject();
aadToken["access_token"] = result.AccessToken;
var appServiceClient = new AppServiceClient(
    "https://MyAppGateway-814485545465FAKE4d5a4532cd.azurewebsites.net/");

// Send the AAD token to the gateway and get a Zumo token
var appServiceUser = await appServiceClient.LoginAsync("aad", aadToken);

带有authContext.AcquireToken(appIdUri, credential)的那一行是造成麻烦的那一行。

如果 appIdUri 我给出 https://MyAppGateway-814485545465FAKE4d5a4532cd.azurewebsites.net/login/aad,我得到异常:

400: AdalServiceException: AADSTS50001: Resource 'https://MyAppGateway-814485545465FAKE4d5a4532cd.azurewebsites.net/login/aad' is not registered for the account.

但是这一行在 AD 应用程序Reply Url 的列表中

当我尝试将 https://MyADDomain.onmicrosoft.com/MyAppNamehttps://MyADDomain.onmicrosoft.com/ 用作 appIdUri 时,我收到一条不同的异常消息:

400: AdalServiceException: AADSTS50105: Application '04472E33-2638-FAKE-GUID-F826AF4928DB' is not assigned to a role for the application 'https://MyADDomain.onmicrosoft.com/MyAppName'

400: AdalServiceException: AADSTS50105: Application '04472E33-2638-FAKE-GUID-F826AF4928DB' is not assigned to a role for the application 'https://MyADDomain.onmicrosoft.com/'

在这两种情况下,我都将 AD 应用程序中的 App ID URI 设置为“https://MyADDomain.onmicrosoft.com/MyAppName' or 'https://MyADDomain.onmicrosoft.com/”。 Reply URL 列表中的两个名称。

最终,经过足够多的尝试,我将 https://graph.windows.net 设置为 appIdUri 并取回了不记名令牌。但是令牌的有效期是过去的(过去大约 1 分钟)。所以我无法对此做任何进一步的事情。并在尝试使用令牌登录 API App 时获得 401-Unauthenticated

我错过了什么?

我已经按照您提到的教程继续学习了:Call an Azure API app from a web app client authenticated by Azure Active Directory

  1. 创建一个 Azure API Api returns 联系人数据
  2. 将 API 应用部署到 Azure 应用服务。
  3. 使用 Azure Active Directory 保护 API 应用。

然后我能够检索令牌,正如您从下面的演示中看到的,我的代码与您的代码没有什么不同,只是它使用了更高版本的 using Microsoft.IdentityModel.Clients.ActiveDirectoryAsync.

从 AAD 获取访问令牌

class Program
{
    static void Main(string[] args)
    {
        var authContext = new AuthenticationContext(Constants.AUTHORITY);
        var credential = 
            new ClientCredential(Constants.CLIENT_ID, Constants.CLIENT_SECRET);
        var result = (AuthenticationResult)authContext
            .AcquireTokenAsync(Constants.API_ID_URL, credential)
            .Result;
        var token = result.AccessToken;
        Console.WriteLine(token.ToString());
        Console.ReadLine();
    }
}

常量

AUTHORITY。第一部分是 https://login.microsoftonline.com。最后一部分是 允许的租户 。我们将允许的租户设置为 portal.azure.com,转到我们应用程序的网关,然后选择设置 > 身份 > Azure Active Directory > 允许的租户。我的房客是 bigfontoutlook.onmicrosoft.com.

CLIENT_ID。我们从添加到 Azure Active Directory 的应用程序中检索此客户端 ID。在 manage.windowsazure.com > Active Directory > Your Directory > APPLICATIONS > Your Application > CONFIGURE 找到它。检索到它后,我们必须将其添加到客户端 ID 字段中网关的 Azure Active Directory 设置中。

CLIENT_SECRET。我们 create/retrieve 这与我们检索客户端 ID 的位置相同。

API_ID_URL。我们通过选择设置 > 身份 > Azure Active Directory > 应用程序 URL.

在我们的 Web API 应用程序的网关 blade 中检索它

以下是适合我的。

class Constants
{
    public const string AUTHORITY =
     "https://login.microsoftonline.com/bigfontoutlook.onmicrosoft.com/";

    public const string CLIENT_ID = 
      "0d7dce06-c3e3-441f-89a7-f828e210ff6d";

    public const string CLIENT_SECRET =
      "AtRMr+Rijrgod4b9Q34i/UILldyJ2VO6n2jswkcVNDs=";

    public const string API_ID_URL = 
      "https://mvp201514929cfaaf694.azurewebsites.net/login/aad";
}

最终解码的 JWT

这是解码后的 JWT 访问令牌所包含的内容。

{
 typ: "JWT",
 alg: "RS256",
 x5t: "MnC_VZcATfM5pOYiJHMba9goEKY",
 kid: "MnC_VZcATfM5pOYiJHMba9goEKY"
}.
{
 aud: "https://mvp201514929cfc350148cfa5c9b24a7daaf694.azurewebsites.net/login/aad",
 iss: "https://sts.windows.net/0252f597-5d7e-4722-bafa-0b26f37dc14f/",
 iat: 1442346927,
 nbf: 1442346927,
 exp: 1442350827,
 ver: "1.0",
 tid: "0252f597-5d7e-4722-bafa-0b26f37dc14f",
 oid: "5a6f33eb-b622-4996-8a6a-600dce355389",
 sub: "5a6f33eb-b622-4996-8a6a-600dce355389",
 idp: "https://sts.windows.net/0252f597-5d7e-4722-bafa-0b26f37dc14f/",
 appid: "0d7dce06-c3e3-441f-89a7-f828e210ff6d",
 appidacr: "1"
}.

注意:这是一个一次性应用程序,位于一次性活动目录帐户中,带有一次性资源组,因此显示我的安全凭证是 non-issue。

图表只是为了确定:)