带有 Angular4 和 WebAPI Core2 令牌验证问题的 Azure AD B2C
Azure AD B2C with Angular4 and WebAPI Core2 token validation issue
似乎 Azure 文档无法给出一个明确的例子来正确地做到这一点。
有Angular4 (WebApp) 和WebAPI Core 2.0 back-end。在Azure B2C 中配置了两个应用程序。 WebApp 在其 API 访问权限中有 WebAPI 应用程序。
Web 应用程序被重定向到 https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize。在那里,提供了凭据,然后 AAD B2C 使用 access_token、token_type、expires_in、id_token url 参数回调 WebApp 页面。
然后,WebApp 在授权 header 中使用 access_token 向 back-end 的受保护端点发出请求。 MessageReceivedAsync 在请求到达 back-end 时被调用,并一直通过验证令牌。
但是,当进程退出方法时,它进入的下一步是 AuthenticationFailed 错误。
"IDX10501: Signature validation failed. Unable to match 'kid': 'Base64_kid',
token: '{"alg":"RS256","typ":"JWT","kid":"Base64_kid"}.{"iss":"number of claims"}'."
我的理解是 Audience 是 WebAPI 应用程序 ID。我只有 SingIn/Up 政策。
我在这里缺少什么来完成 jwt 手动验证 w/o 错误?另一个问题,当 claimsPrincipal 在令牌验证时创建时,它如何进入请求上下文才能访问受保护的端点?
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.Authority = string.Format("https://login.microsoftonline.com/{0}/v2.0/",
Configuration["Authentication:AzureAd:ida:Tenant"], Configuration["Authentication:AzureAd:ida:Policy"]);
options.Audience = Configuration["Authentication:AzureAd:ida:ClientId"];
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = AuthenticationFailed,
OnMessageReceived = MessageReceivedAsync,
OnChallenge = Challenge,
OnTokenValidated = TokenValidated
};
});
...
}
private Task MessageReceivedAsync(MessageReceivedContext arg)
{
string jwtToken = null;
var aadInstance = Configuration["Authentication:AzureAd:ida:AADInstance"];
var tenant = Configuration["Authentication:AzureAd:ida:Tenant"];
var audience = Configuration["Authentication:AzureAd:ida:Audience"];
var policy = Configuration["Authentication:AzureAd:ida:Policy"];
var authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
string _issuer = string.Empty;
List<SecurityKey> _signingTokens = null;
var authHeader = arg.HttpContext.Request.Headers["Authorization"];
// 7 = (Bearer + " ").Length
var token = authHeader.ToString().Substring(7);
try
{
string stsDiscoveryEndpoint = string.Format("{0}/v2.0/.well-known/openid-configuration?p={1}", authority, policy);
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint,
new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration config = null;
var openIdConfigTask = Task.Run(async () => {
config = await configManager.GetConfigurationAsync();
});
openIdConfigTask.Wait();
_issuer = config.Issuer;
_signingTokens = config.SigningKeys.ToList();
}
catch(Exception ex)
{
...
}
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidAudience = audience,
ValidIssuer = _issuer,
IssuerSigningKeys = _signingTokens
};
var claimsPrincipal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);
//Thread.CurrentPrincipal = claimsPrincipal; ?
//var ticket = new AuthenticationTicket(claimsPrincipal, arg.Scheme.Name); ?
//arg.HttpContext.User = claimsPrincipal; ?
return Task.FromResult(0);
}
options.Audience
属性 是正确的(即 Web API 应用程序的应用程序标识符)但是 JWT 承载身份验证中间件正在下载错误的签名密钥,因为您没有似乎将 options.Authority
属性 设置为正确的值。
它必须包含 Azure AD B2C 策略。
您应该将其设置为:
https://login.microsoftonline.com/tfp/{tenant}/{policy}/v2.0/'
如:
https://login.microsoftonline.com/tfp/{Configuration["Authentication:AzureAd:ida:Tenant"]}/{Configuration["Authentication:AzureAd:ida:Policy"]}/v2.0/
.
作为令牌验证的结果,HttpContext.User
对象包含来自令牌的声明,因此您可以控制访问,例如通过范围。
似乎 Azure 文档无法给出一个明确的例子来正确地做到这一点。
有Angular4 (WebApp) 和WebAPI Core 2.0 back-end。在Azure B2C 中配置了两个应用程序。 WebApp 在其 API 访问权限中有 WebAPI 应用程序。
Web 应用程序被重定向到 https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize。在那里,提供了凭据,然后 AAD B2C 使用 access_token、token_type、expires_in、id_token url 参数回调 WebApp 页面。
然后,WebApp 在授权 header 中使用 access_token 向 back-end 的受保护端点发出请求。 MessageReceivedAsync 在请求到达 back-end 时被调用,并一直通过验证令牌。
但是,当进程退出方法时,它进入的下一步是 AuthenticationFailed 错误。
"IDX10501: Signature validation failed. Unable to match 'kid': 'Base64_kid',
token: '{"alg":"RS256","typ":"JWT","kid":"Base64_kid"}.{"iss":"number of claims"}'."
我的理解是 Audience 是 WebAPI 应用程序 ID。我只有 SingIn/Up 政策。
我在这里缺少什么来完成 jwt 手动验证 w/o 错误?另一个问题,当 claimsPrincipal 在令牌验证时创建时,它如何进入请求上下文才能访问受保护的端点?
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.Authority = string.Format("https://login.microsoftonline.com/{0}/v2.0/",
Configuration["Authentication:AzureAd:ida:Tenant"], Configuration["Authentication:AzureAd:ida:Policy"]);
options.Audience = Configuration["Authentication:AzureAd:ida:ClientId"];
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = AuthenticationFailed,
OnMessageReceived = MessageReceivedAsync,
OnChallenge = Challenge,
OnTokenValidated = TokenValidated
};
});
...
}
private Task MessageReceivedAsync(MessageReceivedContext arg)
{
string jwtToken = null;
var aadInstance = Configuration["Authentication:AzureAd:ida:AADInstance"];
var tenant = Configuration["Authentication:AzureAd:ida:Tenant"];
var audience = Configuration["Authentication:AzureAd:ida:Audience"];
var policy = Configuration["Authentication:AzureAd:ida:Policy"];
var authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
string _issuer = string.Empty;
List<SecurityKey> _signingTokens = null;
var authHeader = arg.HttpContext.Request.Headers["Authorization"];
// 7 = (Bearer + " ").Length
var token = authHeader.ToString().Substring(7);
try
{
string stsDiscoveryEndpoint = string.Format("{0}/v2.0/.well-known/openid-configuration?p={1}", authority, policy);
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint,
new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration config = null;
var openIdConfigTask = Task.Run(async () => {
config = await configManager.GetConfigurationAsync();
});
openIdConfigTask.Wait();
_issuer = config.Issuer;
_signingTokens = config.SigningKeys.ToList();
}
catch(Exception ex)
{
...
}
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidAudience = audience,
ValidIssuer = _issuer,
IssuerSigningKeys = _signingTokens
};
var claimsPrincipal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);
//Thread.CurrentPrincipal = claimsPrincipal; ?
//var ticket = new AuthenticationTicket(claimsPrincipal, arg.Scheme.Name); ?
//arg.HttpContext.User = claimsPrincipal; ?
return Task.FromResult(0);
}
options.Audience
属性 是正确的(即 Web API 应用程序的应用程序标识符)但是 JWT 承载身份验证中间件正在下载错误的签名密钥,因为您没有似乎将 options.Authority
属性 设置为正确的值。
它必须包含 Azure AD B2C 策略。
您应该将其设置为:
https://login.microsoftonline.com/tfp/{tenant}/{policy}/v2.0/'
如:
https://login.microsoftonline.com/tfp/{Configuration["Authentication:AzureAd:ida:Tenant"]}/{Configuration["Authentication:AzureAd:ida:Policy"]}/v2.0/
.
作为令牌验证的结果,HttpContext.User
对象包含来自令牌的声明,因此您可以控制访问,例如通过范围。