我正在使用msal.js处理认证,这是一个与Angular 6 SPA相关的IT技术。但是我遇到了一些问题:
首先,我无法找到如何使用该库处理错误的清晰示例,因此我不得不从各个方面进行尝试,最终得出了以下结果:
@Injectable()
export class AuthenticationService {
_clientApplication: Msal.UserAgentApplication;
_clientApplicationPR: Msal.UserAgentApplication;
private _authority: string;
constructor(private apiService: ApiService, private backendRoutes: BackendRoutes) {
this._authority = `https://login.microsoftonline.com/tfp/${environment.tenant}/${environment.signUpSignInPolicy}`;
this._clientApplication =
new Msal.UserAgentApplication(
environment.clientID,
this._authority,
this._authCallback,
{
cacheLocation: 'localStorage',
redirectUri: window.location.origin
});
}
private _authCallback(errorDesc: any, token: any, error: any, tokenType:
any) {
console.log("in call back");
if (token) {
this.addUser();
} else {
// console.log(`${error} - ${errorDesc}`);
if (errorDesc.indexOf("AADB2C90118") > -1) {
//Forgotten password
this._clientApplicationPR = new Msal.UserAgentApplication(
environment.clientID,
`https://login.microsoftonline.com/tfp/${environment.tenant}/${environment.passResetPolicy}`,
this._authCallback,
{
cacheLocation: 'localStorage',
redirectUri: window.location.origin
});
this._clientApplicationPR.loginRedirect(environment.b2cScopes);
} else if (errorDesc.indexOf("AADB2C90077") > -1) {
//Expired Token
this._clientApplication.acquireTokenRedirect(environment.b2cScopes);
}
}
}
getAuthenticationToken(): Promise<string> {
return
this._clientApplication.acquireTokenSilent(environment.b2cScopes)
.then(token => token)
.catch(error => {
return Promise.reject(error);
});
}
}
getAuthenticationToken函数被用于我的http拦截器中以设置Bearer令牌。除了在令牌过期时会发出以下错误之外,它都运行正常:
main.c20e047e67b91051727f.js:1 AADB2C90077: 用户没有现有的会话,并且请求提示参数的值为“None”。关联ID:3a627592-5ab0-4e54-b01d-e4296e4d4002 时间戳:2018-11-27 08:30:32Z |interaction_required
为了处理这种情况,您可以看到回调函数检查错误代码内容。问题是,在acquireTokenSilent失败后,我的回调函数从未被调用...我不知道为什么,也不知道我是否做错了什么? 对于acquireTokenSilent,我想您可以在Promise拒绝中处理错误,虽然不是理想的解决方案。
其次,回调函数中的上下文与我的服务上下文不同,我无法访问"this",从我读到的资料来看,它被库覆盖了。我的"AADB2C90118忘记密码错误"的临时技巧是使用适当的权限创建一个新的userAgentApplication,是否有任何方法可以在回调函数中访问我的服务上下文并避免这样做呢?
编辑我设法使事情顺利进行:"this" 在回调中引用userAgentApplication本身,因此您可以像这样操作,而无需创建新的userAgentApplication:
constructor(private apiService: ApiService, private backendRoutes: BackendRoutes) {
this._authority = `https://login.microsoftonline.com/tfp/${environment.tenant}/${environment.signUpSignInPolicy}`;
this._clientApplication =
new Msal.UserAgentApplication(
environment.clientID,
this._authority,
this.msalHandler,
{
cacheLocation: 'localStorage',
redirectUri: window.location.origin
});
}
msalHandler(errorDesc: any, token: any, error: any, tokenType: any) {
let userAgent: Msal.UserAgentApplication = <any>(this);
if (errorDesc.indexOf("AADB2C90118") > -1) {
//Forgotten password
userAgent.authority = `https://login.microsoftonline.com/tfp/${environment.tenant}/${environment.passResetPolicy}`;
userAgent.loginRedirect(environment.b2cScopes);
} else if (errorDesc.indexOf("AADB2C90077") > -1) {
//Expired Token
this.logout();
}
}
将此绑定到您的回调函数中:
this._clientApplication =
new Msal.UserAgentApplication(
environment.clientID,
this._authority,
this.msalHandler.bind(this),
{
cacheLocation: 'localStorage',
redirectUri: window.location.origin
});
以及我的拦截器:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return from(this.authenticationService.getAuthenticationToken()
.then(token => {
return req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
})
.catch(err => {
this.authenticationService.msalHandler(err,null,null,null);
return req;
}))
.switchMap(req => {
return next.handle(req);
});
}
我的信息如下:我在使用最新的"msal": "^0.2.3", "typescript": "~2.7.2", "@angular/core": "^6.0.3"。