我正在尝试验证每次请求时从Azure AD获取的IdToken,但我一直收到错误消息,表示令牌上没有签名。当我验证访问令牌它工作,但我宁愿使用Id令牌,因为它包含用户声明。反正有没有让Azure发回带有签名的Id令牌?
public JwtSecurityToken ValidateJwtToken(string jwtToken)
{
string stsDiscoveryEndpoint = $"{_authority}/.well-known/openid-configuration";
ConfigurationManager<OpenIdConnectConfiguration> configManager =
new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;
TokenValidationParameters validationParameters = new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = false,
ValidateLifetime = false,
IssuerSigningKeys = config.SigningKeys
};
JwtSecurityTokenHandler tokendHandler = new JwtSecurityTokenHandler();
try
{
SecurityToken token;
tokendHandler.ValidateToken(jwtToken, validationParameters, out token);
return token as JwtSecurityToken;
}
catch (Exception ex)
{
loggingService.LogError("Could not validate azure ad token", nameof(AzureSecurityService), ex);
return null;
}
}
public async Task<string> GenerateToken(string code)
{
AuthenticationContext authenticationContext = new AuthenticationContext(_authority);
try
{
string baseUrl = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
AuthenticationResult result =
await authenticationContext.AcquireTokenByAuthorizationCodeAsync(code, new Uri(baseUrl), new ClientCredential(_clientId, _clientSecret));
return result.IdToken;
}
catch (AdalException adalex)
{
loggingService.LogError("Could not get authorization request url", nameof(AzureSecurityService), adalex);
return null;
}
catch (Exception ex)
{
loggingService.LogError("Could not get authorization request url", nameof(AzureSecurityService), ex);
return null;
}
}
public async Task<string> GetAuthUrl()
{
AuthenticationContext authenticationContext = new AuthenticationContext(_authority);
// Config for OAuth client credentials
try
{
string baseUrl = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
var authUri =
await authenticationContext.GetAuthorizationRequestUrlAsync("00000000-0000-0000-0000-000000000000", _clientId, new Uri(baseUrl), UserIdentifier.AnyUser, null);
return authUri.ToString();
}
catch (AdalException adalex)
{
loggingService.LogError("Could not get authorization request url", nameof(AzureSecurityService), adalex);
return null;
}
catch (Exception ex)
{
loggingService.LogError("Could not get authorization request url", nameof(AzureSecurityService), ex);
return null;
}
}
更新
所以无论出于什么原因,即使没有提供范围,我也会收到索赔。我现在所做的只是将查询参数添加到范围的auth url并请求openid和profile:
var authUri =
await authenticationContext.GetAuthorizationRequestUrlAsync("00000000-0000-0000-0000-000000000000", _clientId, new Uri(GetBaseUrl()), UserIdentifier.AnyUser, "scope=openid profile");
我的问题是,为什么默认范围不会返回带签名的id_token?
答案 0 :(得分:1)
您应该忘记在授权请求中输入所需的范围值,
来自OpenID Connect specification
<强>范围强>
必需的。 OpenID Connect请求必须包含openid范围值。 如果openid范围值不存在,则完全是行为 不确定的。可能存在其他范围值。使用的范围值 不被实现理解应该被忽略。看到 第5.4和11节,了解由此定义的其他范围值 说明书
因此,您必须在授权请求中指定 openid 。
Azure确实为OAuth 2.0令牌响应返回了一个id令牌(当openid作用域不存在时)。
来自Azure AD OAuth2.0 documentation,
id_token
未签名的JSON Web令牌(JWT)。该应用程序可以base64Url解码 此令牌的片段用于请求有关用户的信息 登录。该应用程序可以缓存值并显示它们,但它 不应该依赖它们来获得任何授权或安全边界。
正如文档所说,它只是显示最终用户。不得使用此id标记进行身份验证/授权。
另一方面,对于正确的OpenID Connect令牌响应,Auzre会向您发送签名的ID令牌,
<强> id_token 强>
应用请求的id_token。你可以使用id_token来 验证用户的身份并开始与用户进行会话。
验证相同文档的id_token部分解释了如何验证令牌
希望这能解决你的问题。