msal.js angular 6 SPA回调和错误处理
msal.js angular 6 SPA callback and errors handling
我在 angular 6 SPA 上使用 msal.js 来处理身份验证,我有几个问题:
首先,我找不到关于如何使用库处理错误的明确示例,所以我左挑右挑,得出了下一个结果:
@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);
});
}
}
我的 httpinterceptor 中使用了 getAuthenticationToken 函数来设置不记名令牌。
这工作正常,除非我的令牌过期并发出下一个错误:
main.c20e047e67b91051727f.js:1 AADB2C90077: User does not have an
existing session and request prompt parameter has a value of 'None'.
Correlation ID: 3a627592-5ab0-4e54-b01d-e4296e4d4002 Timestamp:
2018-11-27 08:30:32Z |interaction_required
在我尝试处理这种情况时,您可以看到回调检查错误代码内容。问题是,我的回调在 acquireTokenSilent 失败后永远不会被调用......我想知道为什么以及我是否做错了什么?
对于 acquireTokenSilent,我猜您可以将错误处理为承诺拒绝。虽然不理想。
其次,回调中的上下文与我的服务不一样,我无权访问"this",据我所知,它已被库覆盖。我对 "AADB2C90118 forgotten password error" 的临时 hack 是用适当的权限肮脏地创建一个新的 userAgentAplication,有没有办法在回调中访问我的服务上下文并避免这样做?
Edit 我设法让事情顺利进行:"this" 在回调中引用了 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".
我的最终版本。工作正常。
import {of, Observable, empty, throwError } from 'rxjs';
import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
import * as Msal from 'msal';
import { User } from "msal/lib-commonjs/User";
import { ApiService } from './api.service';
import { BackendRoutes } from './backend.routes';
@Injectable()
export class AuthenticationService {
private _clientApplication: Msal.UserAgentApplication;
private _authority: string;
private _authorityPasseReset: string;
private _authorityEditProfile: string;
private _authoritySignIn: string;
private _authoritySignUp: string;
constructor(private apiService: ApiService, private backendRoutes: BackendRoutes) {
// this._authority = `https://login.microsoftonline.com/tfp/${environment.tenant}/${environment.signInPolicy}`;
this._authority = `https://${environment.tenant}.b2clogin.com/${environment.tenant}.onmicrosoft.com/`;
this._authorityPasseReset = this._authority + `${environment.passResetPolicy}`;
this._authorityEditProfile = this._authority + `${environment.editProfilePolicy}`;
this._authoritySignIn = this._authority + `${environment.signInPolicy}`;
this._authoritySignUp = this._authority + `${environment.signUpPolicy}`;
this._clientApplication =
new Msal.UserAgentApplication(
environment.clientID,
this._authoritySignIn,
this.msalHandler,
{
cacheLocation: 'localStorage',
redirectUri: window.location.origin + '/acceuil',
validateAuthority: false
});
}
init() {
this.refreshToken()
.then(token => console.debug('token refreshed'))
.catch(err => this.msalHandler(err, null, null, null));
}
msalHandler(errorDesc: any, token: any, error: any, tokenType: any) {
let userAgent: Msal.UserAgentApplication = <any>(this);
if (errorDesc.indexOf("AADB2C90118") > -1) {
//Forgotten password
userAgent.authority = this._authorityPasseReset;
userAgent.loginRedirect(environment.b2cScopes);
} else if (errorDesc.indexOf("AADB2C90077") > -1) {
//Expired Token, function call from interceptor with proper context
this.logout();
}
}
login(): void {
this._clientApplication.loginRedirect(environment.b2cScopes);
}
register(): void {
this._clientApplication.authority = this._authoritySignUp;
this._clientApplication.loginRedirect(environment.b2cScopes);
}
logout(): void {
this._clientApplication.logout();
}
editProfile(): void {
this._clientApplication.authority = this._authorityEditProfile;
this._clientApplication.loginRedirect(environment.b2cScopes);
}
refreshToken(): Promise<string> {
return this._clientApplication.acquireTokenSilent(environment.b2cScopes, this._authoritySignIn, this.getUser())
}
getAuthenticationToken(): Promise<string> {
return this._clientApplication.acquireTokenSilent(environment.b2cScopes)
.then(token => token)
.catch(error => {
return Promise.reject(error);
});
}
我在 angular 6 SPA 上使用 msal.js 来处理身份验证,我有几个问题: 首先,我找不到关于如何使用库处理错误的明确示例,所以我左挑右挑,得出了下一个结果:
@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);
});
}
}
我的 httpinterceptor 中使用了 getAuthenticationToken 函数来设置不记名令牌。 这工作正常,除非我的令牌过期并发出下一个错误:
main.c20e047e67b91051727f.js:1 AADB2C90077: User does not have an existing session and request prompt parameter has a value of 'None'. Correlation ID: 3a627592-5ab0-4e54-b01d-e4296e4d4002 Timestamp: 2018-11-27 08:30:32Z |interaction_required
在我尝试处理这种情况时,您可以看到回调检查错误代码内容。问题是,我的回调在 acquireTokenSilent 失败后永远不会被调用......我想知道为什么以及我是否做错了什么? 对于 acquireTokenSilent,我猜您可以将错误处理为承诺拒绝。虽然不理想。
其次,回调中的上下文与我的服务不一样,我无权访问"this",据我所知,它已被库覆盖。我对 "AADB2C90118 forgotten password error" 的临时 hack 是用适当的权限肮脏地创建一个新的 userAgentAplication,有没有办法在回调中访问我的服务上下文并避免这样做?
Edit 我设法让事情顺利进行:"this" 在回调中引用了 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".
我的最终版本。工作正常。
import {of, Observable, empty, throwError } from 'rxjs';
import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
import * as Msal from 'msal';
import { User } from "msal/lib-commonjs/User";
import { ApiService } from './api.service';
import { BackendRoutes } from './backend.routes';
@Injectable()
export class AuthenticationService {
private _clientApplication: Msal.UserAgentApplication;
private _authority: string;
private _authorityPasseReset: string;
private _authorityEditProfile: string;
private _authoritySignIn: string;
private _authoritySignUp: string;
constructor(private apiService: ApiService, private backendRoutes: BackendRoutes) {
// this._authority = `https://login.microsoftonline.com/tfp/${environment.tenant}/${environment.signInPolicy}`;
this._authority = `https://${environment.tenant}.b2clogin.com/${environment.tenant}.onmicrosoft.com/`;
this._authorityPasseReset = this._authority + `${environment.passResetPolicy}`;
this._authorityEditProfile = this._authority + `${environment.editProfilePolicy}`;
this._authoritySignIn = this._authority + `${environment.signInPolicy}`;
this._authoritySignUp = this._authority + `${environment.signUpPolicy}`;
this._clientApplication =
new Msal.UserAgentApplication(
environment.clientID,
this._authoritySignIn,
this.msalHandler,
{
cacheLocation: 'localStorage',
redirectUri: window.location.origin + '/acceuil',
validateAuthority: false
});
}
init() {
this.refreshToken()
.then(token => console.debug('token refreshed'))
.catch(err => this.msalHandler(err, null, null, null));
}
msalHandler(errorDesc: any, token: any, error: any, tokenType: any) {
let userAgent: Msal.UserAgentApplication = <any>(this);
if (errorDesc.indexOf("AADB2C90118") > -1) {
//Forgotten password
userAgent.authority = this._authorityPasseReset;
userAgent.loginRedirect(environment.b2cScopes);
} else if (errorDesc.indexOf("AADB2C90077") > -1) {
//Expired Token, function call from interceptor with proper context
this.logout();
}
}
login(): void {
this._clientApplication.loginRedirect(environment.b2cScopes);
}
register(): void {
this._clientApplication.authority = this._authoritySignUp;
this._clientApplication.loginRedirect(environment.b2cScopes);
}
logout(): void {
this._clientApplication.logout();
}
editProfile(): void {
this._clientApplication.authority = this._authorityEditProfile;
this._clientApplication.loginRedirect(environment.b2cScopes);
}
refreshToken(): Promise<string> {
return this._clientApplication.acquireTokenSilent(environment.b2cScopes, this._authoritySignIn, this.getUser())
}
getAuthenticationToken(): Promise<string> {
return this._clientApplication.acquireTokenSilent(environment.b2cScopes)
.then(token => token)
.catch(error => {
return Promise.reject(error);
});
}