Я пытаюсь заставить приложение Angular 4 правильно выполнять неявную аутентификацию с помощью Azure AD B2C. Я использую msal.js, чтобы заставить его работать. Я проверил очень ограниченный официальный образец кода, но это бесполезно, так как для входа в систему используется всплывающее окно, а я хочу выполнить перенаправление.
Теперь у меня есть следующая служба аутентификации, которую я внедряю в свое приложение и которая должна позаботиться обо всей аутентификации.
import { Injectable } from '@angular/core';
import * as Msal from 'msal';
@Injectable()
export class AuthenticationService {
private tenantConfig = {
tenant: "example.onmicrosoft.com",
clientID: "redacted (guid of the client)",
signUpSignInPolicy: "b2c_1_signup",
b2cScopes: ["https://example.onmicrosoft.com/demo/read", "openid"]
}
private authority = "https://login.microsoftonline.com/tfp/" + this.tenantConfig.tenant + "/" + this.tenantConfig.signUpSignInPolicy;
private clientApplication: Msal.UserAgentApplication;
constructor() {
this.clientApplication = new Msal.UserAgentApplication(this.tenantConfig.clientID, this.authority, this.authCallback);
}
public login(): void {
this.clientApplication.loginRedirect(this.tenantConfig.b2cScopes);
}
public logout(): void {
this.clientApplication.logout();
}
public isOnline(): boolean {
return this.clientApplication.getUser() != null;
}
public getUser(): Msal.User {
return this.clientApplication.getUser();
}
public getAuthenticationToken(): Promise<string> {
return this.clientApplication.acquireTokenSilent(this.tenantConfig.b2cScopes)
.then(token => {
console.log("Got silent access token: ", token);
return token;
}).catch(error => {
console.log("Could not silently retrieve token from storage.", error);
return this.clientApplication.acquireTokenPopup(this.tenantConfig.b2cScopes)
.then(token => {
console.log("Got popup access token: ", token);
return token;
}).catch(error => {
console.log("Could not retrieve token from popup.", error);
this.clientApplication.acquireTokenRedirect(this.tenantConfig.b2cScopes);
return Promise.resolve("");
});
});
}
private authCallback(errorDesc: any, token: any, error: any, tokenType: any) {
console.log("Callback")
if (token) {
console.log("Id token", token);
}
else {
console.log(error + ":" + errorDesc);
}
this.getAuthenticationToken();
}
}
Но это не работает. Я получаю токен ID правильно, и он действителен, поэтому токен Id действительно получает значение, которое я могу использовать, но в течение ограниченного времени.
Проблема в том, что я пытаюсь получить токен аутентификации. Первый вызов acquireTokenSilent
возвращает ошибку: Token renewal operation failed due to timeout: null
.
Затем я получаю всплывающее окно с запросом имени пользователя и пароля, которое через некоторое время исчезает, и я получаю сообщение об ошибке User does not have an existing session and request prompt parameter has a value of 'None'.
.
Изменить:
Итак, я думаю, что понимаю, что именно происходит, и воспроизведу проблему в примере приложения, которое вы можете получить здесь: https://github.com/Gimly/NetCoreAngularAzureB2CMsal
Если вы подключитесь с домашней страницы, а затем перейдете на страницу fetchData (ту, которая содержит прогноз погоды), вы увидите, что токен аутентификации правильно активирован acquireTokenSilent
(откройте консоль браузера, чтобы получить все журналы). Но если вы обновите страницу непосредственно в fetchData, вы увидите то же поведение, что я описал, с acquireTokenSilent
ошибкой с ошибкой о тайм-ауте.
Я могу предположить, что по какой-то причине, хотя getUser
возвращает правильное значение, msal не инициализируется полностью до того, как я вызываю getAuthenticationToken
, и это причина его полного отказа.
Теперь реальный вопрос ... Как мне убедиться, что он полностью инициализирован, прежде чем пытаться получить токен?