[英]Login redirect a user with Azure AD B2C from an Angular application and msal.js
I'm trying to get an Angular 4 app to correctly do an implicit authentication with Azure AD B2C.我正在尝试让 Angular 4 应用程序正确地使用 Azure AD B2C 进行隐式身份验证。 I'm using msal.js to try and make it to work.
我正在使用 msal.js 来尝试使其工作。 I've checked the very limited official sample code , but it's of no real use as it's using a popup to login and I want to do a redirection.
我检查了非常有限的官方示例代码,但它没有实际用处,因为它使用弹出窗口登录,我想做一个重定向。
What I have now is the following authentication service that I'm injecting in my app and that should take care of all the authentication.我现在拥有的是我在我的应用程序中注入的以下身份验证服务,它应该负责所有身份验证。
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();
}
}
But it's not working.但它不起作用。 I get the ID token correctly, and it's valid, so the "Id token" does receive a value that I can use, but for a limited time.
我正确地获得了 ID 令牌,并且它是有效的,因此“Id 令牌”确实收到了一个我可以使用的值,但在有限的时间内。
The issue is when I try to get the authentication token.问题是当我尝试获取身份验证令牌时。 The first call, to
acquireTokenSilent
returns an error that says : Token renewal operation failed due to timeout: null
.第一次调用
acquireTokenSilent
返回一个错误,指出: Token renewal operation failed due to timeout: null
。
Then, I'm getting a popup that asks for a username and password, which, after a while disappears and I get an error that says User does not have an existing session and request prompt parameter has a value of 'None'.
然后,我收到一个要求输入用户名和密码的弹出窗口,一段时间后消失,我收到一条错误消息,提示
User does not have an existing session and request prompt parameter has a value of 'None'.
. .
Edit:编辑:
So, I think I understand what's going on exactly and to reproduce the issue on a sample application that you can get here: https://github.com/Gimly/NetCoreAngularAzureB2CMsal所以,我想我明白到底发生了什么,并在您可以在这里获得的示例应用程序上重现该问题: https : //github.com/Gimly/NetCoreAngularAzureB2CMsal
If you connect from the homepage and then go to the fetchData page (the one with the weather forecast) you can see the auth token be correctly redeemed by acquireTokenSilent
(open the browser console to get all the logs).如果您从主页连接,然后转到 fetchData 页面(有天气预报的页面),您可以看到
acquireTokenSilent
正确兑换了 auth 令牌(打开浏览器控制台以获取所有日志)。 But, if you refresh the page directly on fetchData, you can see the same behavior that I described, with acquireTokenSilent
failing with the error about a timeout.但是,如果您直接在 fetchData 上刷新页面,您会看到我描述的相同行为,
acquireTokenSilent
失败并显示超时错误。
My best guess would be that, fore some reason, even though getUser
returns a correct value, msal is not completely initialized before I call getAuthenticationToken
and it's the reason for it to fail completely.我最好的猜测是,由于某种原因,即使
getUser
返回正确的值,在我调用getAuthenticationToken
之前 msal 也没有完全初始化,这就是它完全失败的原因。
Now the real question... How do I make sure that it's completely initialized before trying to get the token?现在真正的问题是……在尝试获取令牌之前,我如何确保它已完全初始化?
OK, so the issue I was facing was caused by two things:好的,所以我面临的问题是由两件事引起的:
1) a bug in msal.js that caused the initialization process to not be fully completed at the end of the constructor call, and I was calling the acquireTokenSilent()
before it had fully initialized. 1) msal.js 中的一个错误导致初始化过程在构造函数调用结束时没有完全完成,我在它完全初始化之前调用了
acquireTokenSilent()
。 This was fixed in the latest version (as of writing, still in the dev branch of the project).这在最新版本中得到了修复(在撰写本文时,仍在项目的 dev 分支中)。 See this GitHub issue for more info .
有关更多信息,请参阅此 GitHub 问题。
2) I hadn't fixed the redirect URI, which caused the library to take the current URL as redirect URI which would fail because it wasn't in the list of allowed redirect URIs. 2)我没有修复重定向 URI,这导致库将当前 URL 作为重定向 URI,这会失败,因为它不在允许的重定向 URI 列表中。
After those two issues fixed, the code I posted in my question is working as expected.解决这两个问题后,我在问题中发布的代码按预期工作。
查看MSAL js 的源代码,您应该能够使用acquireTokenRedirect 而不是acquireTokenPopup。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.