AzureAD JWT 令牌受众声明前缀使 JWT 令牌无效

Posted

技术标签:

【中文标题】AzureAD JWT 令牌受众声明前缀使 JWT 令牌无效【英文标题】:AzureAD JWT Token Audience claim prefix makes JWT Token invalid 【发布时间】:2016-12-23 00:42:08 【问题描述】:

我正在使用“adal-node”npm 包向 AzureAD 进行身份验证。这一切都很好,我得到了一个令牌。

但是,在检查 JWT 令牌中的“aud”声明时,我看到受众 GUID 以“spn:”为前缀。当我尝试在已经存在的 Web API 上使用 JWT 令牌时,我认为这会给我带来问题。当我使用相同的 AzureAD 通过 WebApp 进行身份验证时,“aud”声明不以“spn:”为前缀,并且我可以在 WebAPI 上调用端点。

任何人都可以对此有所了解吗?这是在费了很多脑筋之后才能克服的最后一道障碍。

更新:

使用 npm 包“azure-ad-jwt”通过 AzureAD 验证 JWT 令牌后,我收到了我怀疑是问题的错误 - “JWT 受众无效”。它期望“aud”声明没有“spn:”前缀。这个 spn 前缀是从哪里来的?

这是我的 app.js

var adal = require('adal-node');

var activeDirectoryEndpointUrl = 'https://login.microsoftonline.com/';

var options = 
    domain: '<AzureAD GUID>',
    activeDirectoryResourceId: '<AzureAD App Client ID 1>',
    clientId: '<AzureAD App Client ID 2>'
;

var tokenCache = new adal.MemoryCache();
var authorityUrl = activeDirectoryEndpointUrl + options.domain;
var context = new adal.AuthenticationContext(authorityUrl, true, tokenCache);

context.acquireUserCode(options.activeDirectoryResourceId, options.clientId, 'en-us', function (err, userCodeResponse) 
    if (err) 
        console.error(err);
        return;
    

    console.log('Use a web browser to open the page ' + userCodeResponse.verificationUrl + ' and enter the code ' + userCodeResponse.userCode + ' to sign in.');

    context.acquireTokenWithDeviceCode(options.activeDirectoryResourceId, options.clientId, userCodeResponse, function (err, tokenResponse) 
        if (err) 
            console.error(err);
            return;
        

        console.log(tokenResponse);
    );
);

解码的 JWT 令牌:


    "typ":"JWT",
    "alg":"RS256",
    "x5t":"XXXXXXX",
    "kid":"XXXXXXX"


    "aud":"spn:XXXXXXX",    // <<< Offending claim
    "iss":"https://sts.windows.net/XXXXXXX/",
    "iat":1471355868,
    "nbf":1471355868,
    "exp":1471359768,
    "acr":"1",
    "amr":["pwd"],
    "appid":"XXXXXXX",
    "appidacr":"0",
    "e_exp":7200,
    "family_name":"XX",
    "given_name":"XX",
    "ipaddr":"XX.XX.XX.XX",
    "name":"XX XX",
    "oid":"XXXXXXX",
    "scp":"user_impersonation",
    "sub":"XXXXXXX",
    "tid":"XXXXXXX",
    "unique_name":"XXX@XXX.onmicrosoft.com",
    "upn":"XXX@XXX.onmicrosoft.com",
    "ver":"1.0"

【问题讨论】:

这个问题你解决了吗? 在向 Microsoft 提出支持请求后,他们确认问题出在 adal npm 包上。它使用的 AzureAD api 版本旧且需要更新。他们什么时候会更新 npm 包,我不确定。或者,他们建议对受众使用 URI,而不是 GUID。 请建议替换 npm (adal-node 似乎已被废弃 【参考方案1】:

2 年后仍然面临同样的问题。正如@Adam Young 在 cmets 中针对他自己的问题发布的那样 - 将受众 ID 替换为受众 URL,这将解决问题。

【讨论】:

【参考方案2】:

似乎按“设计”1 记录在 Azure AD 中。

在描述响应字段的 Azure AD 的 SAML 2.0 Single Sign-On SAML protocol 中,它们描述了 audience 响应值。注意底部的粗体文本:

观众

这包含一个标识目标受众的 URI。 Azure AD 将此元素的值设置为启动登录的 AuthnRequest 的 Issuer 元素的值。要评估 Audience 值,请使用在应用程序注册期间指定的 App ID URI 的值。

与 Issuer 值一样,Audience 值必须与代表 Azure AD 中的云服务的服务主体名称之一完全匹配。 但是,如果 Issuer 元素的值不是 URI 值,则响应中的 Audience 值是前缀为 spn: 的 Issuer 值

因此,无论好坏,Azure AD SAML 2.0 的答案似乎都是:

    将您的发行人实体 ID 更改为 URI 更改您的实现以从 audience 响应值的开头去除 spn:

1SAML 2.0 Core spec 指定&lt;Issuer&gt; 元素不是URI,而是复杂类型NameIDType,默认情况下没有格式要求的字符串。因此,我们会对 Azure AD 对非 URI 字符串不满意感到恼火。话虽如此,规范中的每个示例 Issuer都是一个 URI,所以也许我们恼火的自我辩护有其局限性。

【讨论】:

以上是关于AzureAD JWT 令牌受众声明前缀使 JWT 令牌无效的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用会话的情况下获取图形令牌?

Azure AD 令牌中的哪些 JWT 声明可以安全地用于用户映射?

JWT 令牌 - 受众、发行人和子域

在 c# 中为使用 AzureAd 登录的当前用户获取 Jwt 令牌

如何为 OAuth2 访问令牌指定受众?

当客户端需要令牌以访问多个受众时如何创建 JWT?