如何解决Angular 9+MSAL v2应用中的AADSTS900561错误?
问题背景
应用编译正常,但访问时返回「Failed to load resource: the server responded with a status of 400 ()」错误,近期刚接入MSAL v2作为身份认证组件,已通过MSALInstanceFactory配置租户ID、客户端ID及环境变量。
提供的appmodule.ts代码
export function MSALInstanceFactory() : IPublicClientApplication{ const windowRef = new WindowRef(); const env: IEnvConstants = (windowRef.nativeWindow)['ENV']; return new PublicClientApplication({ auth: { clientId: env.msAdalAngularConfig.clientId, authority: `https://login.microsoftonline.com/${env.msAdalAngularConfig.tenant}`, redirectUri: window.location.origin, }, cache: { cacheLocation: 'localStorage', storeAuthStateInCookie: true, }, system: { loggerOptions: { loggerCallback(logLevel: any, message: any) { console.log(message); }, piiLoggingEnabled: false, }, }, }); @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, BrowserAnimationsModule, AppRoutingModule, CoreModule, MsalModule.forRoot( MSALInstanceFactory(), { interactionType: 'popup', authRequest: { scopes: [], }, } as MsalGuardConfiguration, { interactionType: 'redirect', } as MsalInterceptorConfiguration ), //MsAdalAngular6Module.forRoot(getAdalConfig), SharedModule, ], providers: [ //AuthenticationGuard, MsalGuard, Title, ThemeService, { provide: MSAL_INSTANCE, useFactory: MSALInstanceFactory }, { provide: MSAL_GUARD_CONFIG, useFactory:() =>({ interactionType: 'popup', authrequest:{ scopes : [], }, }as MsalGuardConfiguration), }, MsalService, { provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi:true, }, { provide : MSAL_INTERCEPTOR_CONFIG, useFactory: () =>({ interactionType: 'redirect' }as MsalInterceptorConfiguration), }, ], bootstrap: [AppComponent] }) export class AppModule { }
排查与解决步骤
1. 移除重复的MSAL实例配置
你在MsalModule.forRoot()中已传入MSALInstanceFactory(),同时又在providers数组里重复声明了MSAL_INSTANCE,这会导致配置冲突触发400错误。直接删除providers中的MSAL_INSTANCE配置项即可。
2. 修正authRequest拼写错误
在MSAL_GUARD_CONFIG的工厂函数里,属性名写成了小写的authrequest,正确的属性名是大写R开头的authRequest。拼写错误会导致MSAL无法识别认证请求配置,引发无效请求。修正后代码:
{ provide: MSAL_GUARD_CONFIG, useFactory:() =>({ interactionType: 'popup', authRequest:{ scopes : [], }, }as MsalGuardConfiguration), }
3. 验证环境变量加载正确性
在MSALInstanceFactory中添加日志,确认客户端ID和租户ID是否正确获取:
console.log('加载的Client ID:', env.msAdalAngularConfig.clientId); console.log('加载的Tenant ID:', env.msAdalAngularConfig.tenant);
如果返回空值或错误内容,检查环境变量window['ENV']的注入时机,确保在应用初始化前已正确挂载。
4. 补全MSAL拦截器的资源映射配置
当前MSAL_INTERCEPTOR_CONFIG仅配置了interactionType,缺少protectedResourceMap会导致MSAL拦截所有HTTP请求并尝试附加令牌,对静态资源等无需认证的请求触发无效令牌请求,返回400。补充需要拦截的API路径:
{ provide : MSAL_INTERCEPTOR_CONFIG, useFactory: () =>({ interactionType: 'redirect', protectedResourceMap: new Map([ ['https://你的API域名/**', ['api://你的客户端ID/权限范围']] ]) }as MsalInterceptorConfiguration), }
5. 核对Azure AD应用注册配置
- 确认Azure AD应用注册中的重定向URI与代码中
redirectUri: window.location.origin完全一致(包含HTTP/HTTPS协议、端口)。 - 检查应用注册是否启用了对应的认证流程(弹出式/重定向式),确保租户ID、客户端ID与代码配置匹配。
6. 开启MSAL详细日志定位问题
提升日志级别,获取更具体的错误信息:
system: { loggerOptions: { loggerCallback(logLevel: LogLevel, message: string) { console.log(logLevel, message); }, piiLoggingEnabled: false, logLevel: LogLevel.Verbose }, }
通过控制台日志,可直接定位400错误的具体原因(如无效客户端ID、权限范围错误等)。
内容的提问来源于stack exchange,提问作者Nicolas Cozzo

