目标:在前端使用 Microsoft 登录对话框登录 Azure AD 用户。将令牌附加到后端请求中。在后端验证令牌,以确保只有授权用户可以访问代码。棘手的部分:手动验证,因为它不是唯一的验证方式。
我已经成功登录并发送token,但在验证时我得到了这样的错误。IDX10511: Signature validation failed. Keys tried: ...
这是我目前所掌握的信息
app.module.ts
@NgModule({
declarations: [
AppComponent,
RestrictedPageComponent
],
imports: [
HttpClientModule,
MsalModule.forRoot({
auth: {
clientId: '<CLIENT ID>',
}
}, {
consentScopes: [
'user.read',
'openid',
'profile',
],
protectedResourceMap: [
['https://localhost:44323/v1/login', ['user.read']], // frontend
['https://localhost:5001/api/Login', ['user.read']] // backend
]
}),
BrowserModule,
AppRoutingModule
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true
},
],
bootstrap: [AppComponent]
})
export class AppModule { }
登录.组件.ts
login() {
const loginRequest = { scopes: ['https://graph.microsoft.com/User.ReadWrite'] };
this.authService.loginPopup(loginRequest);
}
而这似乎可以正常工作。我可以通过微软登录进行登录,MsalInterceptor会将不记名标记添加到后端请求头中。
在后端,我现在只想验证token是否有效,用户是否被正确认证。
private JwtSecurityToken Validate(string token)
{
var stsDiscoveryEndpoint = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
// also tried "https://login.microsoftonline.com/<TENANT ID>/v2.0/.well-known/openid-configuration"
var openIdConnectConfigurationRetriever = new OpenIdConnectConfigurationRetriever();
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, openIdConnectConfigurationRetriever);
var config = configManager.GetConfigurationAsync().Result;
var validationParameters = new TokenValidationParameters
{
IssuerSigningKeys = config.SigningKeys,
// just for now
ValidateAudience = false,
ValidateIssuer = false,
ValidateLifetime = false
};
var tokenHandler = new JwtSecurityTokenHandler();
IdentityModelEventSource.ShowPII = true;
token = token.Replace("Bearer ", string.Empty); // weird - the token starts with "Bearer " and is not valid like this
var result = tokenHandler.ValidateToken(token, validationParameters, out var jwt);
return jwt as JwtSecurityToken;
}
在调用 tokenHandler.ValidateToken(...
我总是得到一个错误,如 IDX10511: Signature validation failed. Keys tried: ...
.我不知道我是否正确理解和使用了整个概念.我越是阅读关于Azure Bearer标记和验证的用法,就越是让我困惑。
我可以在 http:/jwt.io 但签名总是无效的。
后台可以在不传递任何共享秘籍或客户端id的情况下验证token吗?"一开始这个方法正确吗?"我不知道我是否用了正确的端点来调用前端和后端,以及不同的端点所扮演的角色是什么?
编辑:我不确定我是否使用了正确的端点来调用前端和后端,以及不同的端点所扮演的角色(例如:有租户id或没有)。如果有人能解释一下就好了。
BR马蒂亚斯
看起来你的前端正在获取微软Graph API的访问令牌,该令牌只适用于MS Graph API,而不是你的API,这些Graph API令牌的构建方式也很特殊,你不应该尝试验证它们。
相反,在你的前端,你需要为你的API指定作用域。
consentScopes: [
'your-api-client-id-or-app-id-uri/user_impersonation',
'openid',
'profile',
],
protectedResourceMap: [
['https://localhost:44323/v1/login', ['user.read']], // frontend
['https://localhost:5001/api/Login', ['your-api-client-id-or-app-id-uri/user_impersonation']] // backend
]
为此,您需要在 Azure AD 中进入您的 API 的应用程序注册,进入 Expose an API 选项卡,并在那里添加一个作用域.然后您将完整的作用域 ID(其中包括您的 API 客户端 ID 或应用程序 ID URI + 作用域 ID),并在获取令牌时将其用作作用域.Azure AD 然后应该给您一个旨在为您的 API 提供的令牌。
如果你使用的是ASP.NET Core,你需要验证Azure AD令牌的最小配置是。
// In ConfigureServices
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o =>
{
o.Authority = "https://login.microsoftonline.com/your-tenant-id";
o.Audience = "your-app-client-id";
});
// In Configure (between UseRouting and UseEndpoints)
app.UseAuthentication();
app.UseAuthorization();
现在,在某些情况下,如果您的API配置为在Azure AD中接收v1令牌,则令牌可能包含API客户端ID或应用程序ID URI.在这种情况下,您可以配置多个有效受众。
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o =>
{
o.Authority = "https://login.microsoftonline.com/your-tenant-id";
o.TokenValidationParameters = new TokenValidationParameters
{
ValidAudiences = new[]
{
"your-api-client-id",
"your-api-app-id-uri"
}
};
})