typescript - Logga in omdirigera en användare med Azure AD B2C från en Angular-applikation och msal.js
Jag försöker få en Angular 4-app att korrekt göra en implicit autentisering med Azure AD B2C. Jag använder msal.js för att försöka få det att fungera. Jag har kollat på den mycket begränsade officiella exempel-koden, men den är inget riktigt till hjälp eftersom den använder ett popup-fönster för inloggning och jag vill göra en omdirigering.
Det jag har nu är följande autentiseringstjänst som jag injicerar i min app och som ska ta hand om all autentisering.
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();
}
}
Men det fungerar inte. Jag får ID-token korrekt, och den är giltig, så "Id token" får ett värde som jag kan använda, men bara under en begränsad tid.
Problemet är när jag försöker få autentiseringstoken. Det första anropet, till acquireTokenSilent, returnerar ett fel som säger: Token renewal operation failed due to timeout: null.
Sedan får jag ett popup-fönster som frågar efter ett användarnamn och lösenord, vilket efter ett tag försvinner och jag får ett felmeddelande som säger Användaren har ingen befintlig session och begärd prompt-parameter har värdet 'None'..
Redigera:
Så, jag tror att jag förstår exakt vad som pågår och hur man kan återskapa problemet på en exempelapplikation som du kan få här: https://github.com/Gimly/NetCoreAngularAzureB2CMsal
Om du ansluter från startsidan och sedan går till sidan fetchData (den med väderprognosen) kan du se att auth-token korrekt löses in av acquireTokenSilent (öppna webbläsarens konsol för att få alla loggar). Men om du uppdaterar sidan direkt på fetchData kan du se samma beteende som jag beskrev, med acquireTokenSilent som misslyckas med felet om en timeout.
Min bästa gissning skulle vara att, av någon anledning, även om getUser returnerar ett korrekt värde, är msal inte helt initierat innan jag anropar getAuthenticationToken och det är anledningen till att det misslyckas helt.
Nu är den verkliga frågan... Hur ser jag till att det är helt initialiserat innan jag försöker få token?
Svar #1
Okej, så problemet jag stötte på berodde på två saker:
1) en bugg i msal.js som gjorde att initieringsprocessen inte slutfördes helt vid slutet av konstruktörsanropet, och jag kallade acquireTokenSilent() innan det hade initierats helt. Detta åtgärdades i den senaste versionen (vid skrivande stund fortfarande i projektets utvecklingsgren). Se denna GitHub-issue för mer information.
2) Jag hade inte fixat omdirigerings-URI:n, vilket fick biblioteket att ta den aktuella URL:en som omdirigerings-URI, vilket skulle misslyckas eftersom den inte fanns i listan över tillåtna omdirigerings-URI:er.
Efter att de två problemen har åtgärdats fungerar koden jag postade i min fråga som förväntat.
Svar #2
Om du tittar på källkoden för MSAL js bör du kunna använda acquireTokenRedirect istället för acquireTokenPopup.