Angular集成MSAL认证遇AADSTS50011错误:重定向URI不匹配
解决Angular MSAL令牌过期后重定向URI不匹配问题
针对你遇到的子页面进入、令牌过期后触发AADSTS50011错误的问题,这几个方案能强制Azure AD重定向回主页:
- 显式指定所有登录请求的重定向URI
不管是主动登录还是令牌过期触发的登录请求,都手动指定redirectUri为主页地址,别让MSAL自动用当前子页面的URL。
比如调用登录方法时:
this.msalService.loginRedirect({ redirectUri: 'https://office.app-local.com/' });
处理静默获取令牌失败的情况时,也要加上这个参数:
this.msalService.acquireTokenSilent({ scopes: ['你的权限范围'], redirectUri: 'https://office.app-local.com/' }).catch(error => { // 静默失败就跳主页登录 return this.msalService.loginRedirect({ redirectUri: 'https://office.app-local.com/' }); });
- 自定义MSAL路由守卫
如果用了MsalGuard,自己写个守卫继承它,在令牌过期需要登录时,先跳回主页再触发登录流程:
import { Injectable } from '@angular/core'; import { MsalGuard, MsalGuardConfiguration, MsalService } from '@azure/msal-angular'; import { Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { Observable, of } from 'rxjs'; import { catchError } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class CustomMsalGuard extends MsalGuard { constructor(private router: Router, msalGuardConfig: MsalGuardConfiguration, msalService: MsalService) { super(msalGuardConfig, msalService); } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { return super.canActivate(route, state).pipe( catchError(() => { // 先跳主页,再发起登录重定向 this.router.navigate(['/']).then(() => { this.msalService.loginRedirect({ redirectUri: 'https://office.app-local.com/' }); }); return of(false); }) ); } }
之后把路由配置里的MsalGuard换成这个自定义守卫就行。
- 全局锁定MSAL的重定向URI
在初始化MsalModule时,不仅在auth里设置redirectUri,还要在authRequest里也指定一遍,彻底禁用自动推导当前页面URI的行为:
MsalModule.forRoot(new PublicClientApplication({ auth: { clientId: '你的客户端ID', authority: '你的租户授权地址', redirectUri: 'https://office.app-local.com/', postLogoutRedirectUri: 'https://office.app-local.com/' }, cache: { cacheLocation: BrowserCacheLocation.LocalStorage } }), { interactionType: InteractionType.Redirect, authRequest: { scopes: ['你的权限范围'], redirectUri: 'https://office.app-local.com/' // 全局统一登录请求的重定向地址 } })
- HTTP拦截器里处理令牌过期
如果项目用了HTTP拦截器给请求加令牌,在拦截器里检测到令牌过期的401错误时,先跳回主页再触发登录:
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { MsalService } from '@azure/msal-angular'; import { Router } from '@angular/router'; @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private msalService: MsalService, private router: Router) {} intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const account = this.msalService.getAccount(); if (account) { request = request.clone({ setHeaders: { Authorization: `Bearer ${account.idToken}` } }); } return next.handle(request).pipe( catchError(error => { // 检测令牌过期或无效的情况 if (error.status === 401 || (error.error?.error && error.error.error.includes('invalid_token'))) { this.router.navigate(['/']).then(() => { this.msalService.loginRedirect({ redirectUri: 'https://office.app-local.com/' }); }); } return throwError(error); }) ); } }
内容的提问来源于stack exchange,提问作者andrew.fox
相关产品推荐
相关产品推荐

