我的Azure b2c登录页面的“忘记密码”链接有时会重定向回到登录页面。单击该按钮后,大约有75%的时间它将重定向到登录页面,否则将成功重定向到用于更改密码的页面。
这是我的AuthenticationService:
export class AuthenticationService {
private id_token: string;
private access_token: string;
private applicationSettings: ApplicationSettings;
private authority: string;
clientApplication: UserAgentApplication;
jwtHelper: JwtHelper;
constructor(private settingsProvider: SettingsProvider) {
this.applicationSettings = settingsProvider.configuration;
this.authority = this.getAuthority();
this.jwtHelper = new JwtHelper();
this.clientApplication = new Msal.UserAgentApplication(
this.applicationSettings.clientID,
this.authority,
(errorDesc: any, token: any, error: any, tokenType: any) => {
this.logonCallback.call(this, errorDesc, token, error, tokenType);
},
this.applicationSettings.clientOptions
);
}
login(): void {
this.clientApplication.loginRedirect(
this.applicationSettings.b2cScopes);
}
loginPopup(): void {
var storedThis = this;
this.clientApplication.loginPopup(this.applicationSettings.b2cScopes)
.then((idToken) => {
this.id_token = idToken;
console.log("ID token:", idToken);
this.getAccessToken(this.applicationSettings.b2cScopes)
.catch((reason) => {
console.log('Unable to acquire token after login:', reason);
storedThis.logout();
});
}, function (error) {
console.log(error);
});
}
getAccessToken(scopes: string[]): Promise<string> {
var storedThis = this;
if(this.access_token) {
return new Promise((resolve, reject) => {
resolve(this.access_token)
});
}
let tokenPromise = this.clientApplication.acquireTokenSilent(scopes);
tokenPromise.then((token) => {
this.access_token = token;
console.log("Access token:", token);
});
tokenPromise.catch((reason) => {
this.clientApplication.acquireTokenPopup(scopes)
.then((token) => {
this.access_token = token;
console.log("Access token:", token);
}, function (error) {
console.log('Unable to acquire token using popup:', error);
storedThis.logout();
});
});
return tokenPromise;
}
logout(): void {
sessionStorage.removeItem('customerId');
sessionStorage.removeItem('customerIsActive');
this.clientApplication.logout();
};
isAuthenticated(): boolean {
let user = this.clientApplication.getUser();
return user !== null;
}
getUser() {
let user = this.clientApplication.getUser();
return user;
}
getB2cScopes() {
return this.applicationSettings.b2cScopes;
}
// Called after loginRedirect or acquireTokenPopup
private logonCallback(errorDesc: any, token: any, error: any, tokenType: any) {
// Password reset functionality
if (errorDesc) {
if (errorDesc.indexOf('AADB2C90118') > -1) {
localStorage.removeItem('theme');
this.clientApplication = new Msal.UserAgentApplication(
this.applicationSettings.clientID,
this.getPasswordResetAuthority(),
this.passwordResetCallback,
{
"redirectUri": this.applicationSettings.baseUrl + "/login"
}
);
this.login();
}
}
// Redirect to previous page functionality
var loginRedirectPath = sessionStorage.getItem('loginRedirectPath');
if (loginRedirectPath != null) {
sessionStorage.removeItem('loginRedirectPath');
window.location.replace(
this.settingsProvider.configuration.clientOptions.redirectUri + loginRedirectPath);
return;
}
// Get access token
if (!errorDesc || errorDesc.indexOf('AADB2C90118') == -1) {
console.log("ErrorNr: AADB2C90118");
this.getAccessToken(this.applicationSettings.b2cScopes)
.catch((reason) => {
console.log('Unable to acquire token after login:', reason);
});
}
}
getAuthority() {
return this.applicationSettings.b2cDomain + "/tfp/" +
this.applicationSettings.tenant + "/" +
this.applicationSettings.signUpSignInPolicy;
}
getPasswordResetAuthority() {
return this.applicationSettings.b2cDomain + "/tfp/" +
this.applicationSettings.tenant + "/" +
this.applicationSettings.passwordResetPolicy;
}
passwordResetCallback() {
this.logout();
}
}
这是我的AuthGuard:
export class AuthGuard implements CanActivate {
constructor(private authenticationService: AuthenticationService, private router: Router, private themeProvider: ThemeProvider) { }
canActivate(): any {
console.log('auth gaurd');
let userIsAuthenticated = this.authenticationService.isAuthenticated();
if (userIsAuthenticated) {
return true;
}
this.authenticationService.login();
return false;
}
}
在app.module中的路由中,AuthGuard的用法如下:
{ path: '', canActivate: [AuthGuard], children: [ ...
这是我的配置:
{
"tenant": "XXXXX.onmicrosoft.com",
"clientID": "XXXXX",
"signUpSignInPolicy": "B2C_1_Sign_Up_or_In",
"passwordResetPolicy": "B2C_1_Password_Reset_Policy",
"baseUrl": "http://localhost:4200",
"b2cScopes": [
"XXXXX"
],
"clientOptions": {
"redirectUri": "http://localhost:4200",
"postLogoutRedirectUri": "http://localhost:4200",
"validateAuthority": true,
"cacheLocation": "sessionStorage"
},
"b2cDomain": "https://login.microsoftonline.com"
}
答案 0 :(得分:0)
我解决了这个问题。由于更改密码时用户未登录,因此我的AuthGuard将尝试运行登录功能。为了解决这个问题,我在获取重置密码错误代码时在会话存储中添加了一条注释,如下所示:
if (errorDesc.indexOf('AADB2C90118') > -1) {
...
sessionStorage.setItem('changePassword', 'true'); // Added this line
...
然后,我在AuthGuard中检查了此注释。如果已设置注释,那么我不想运行登录功能,请参见下文。
var changePassword = sessionStorage.getItem("changePassword");
if (changePassword == null)
this.authenticationService.login();
else
sessionStorage.removeItem("changePassword");