我使用' dal-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"
}
1 for Azure AD。
在Azure AD的SAML 2.0单点登录SAML协议中描述响应字段,它们描述受众响应值。注意底部的粗体文本:
观众这包含一个标识目标受众的URI。Azure AD将此元素的值设置为发起登录的AuthnRequest的Issuer元素的值。要评估受众值,请使用应用程序注册期间指定的应用程序ID URI的值。
与发行者值一样,受众值必须与Azure AD中代表云服务的服务主体名称之一完全匹配。但是,如果Issuer元素的值不是URI值,那么响应中的Audience值就是以
spn:
为前缀的Issuer值。
因此,无论好坏,Azure AD SAML 2.0的答案似乎是:
- 将发行人实体ID更改为URI
- 更改您的实现,从受众响应值的开头去掉
spn:
。
1 SAML 2.0 Core规范不是将<Issuer>
元素指定为URI
,而是将其指定为复杂类型NameIDType
,默认情况下没有格式要求的字符串。因此,Azure AD对非uri字符串不满意会让我们感到恼火。话虽如此,规范中中的每个示例发行人都是一个URI,所以也许我们恼人的自我辩护有其局限性。
2年后仍然面临同样的问题。正如@Adam Young在评论中对他自己的问题所发表的那样——将受众id替换为受众URL,这将解决问题。