繁体   English   中英

使用 Azure AD B2C 从 Angular 应用程序和 msal.js 登录重定向用户

[英]Login redirect a user with Azure AD B2C from an Angular application and msal.js

我正在尝试让 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正确兑换了 auth 令牌(打开浏览器控制台以获取所有日志)。 但是,如果您直接在 fetchData 上刷新页面,您会看到我描述的相同行为, acquireTokenSilent失败并显示超时错误。

我最好的猜测是,由于某种原因,即使getUser返回正确的值,在我调用getAuthenticationToken之前 msal 也没有完全初始化,这就是它完全失败的原因。

现在真正的问题是……在尝试获取令牌之前,我如何确保它已完全初始化?

好的,所以我面临的问题是由两件事引起的:

1) msal.js 中的一个错误导致初始化过程在构造函数调用结束时没有完全完成,我在它完全初始化之前调用了acquireTokenSilent() 这在最新版本中得到了修复(在撰写本文时,仍在项目的 dev 分支中)。 有关更多信息,请参阅此 GitHub 问题

2)我没有修复重定向 URI,这导致库将当前 URL 作为重定向 URI,这会失败,因为它不在允许的重定向 URI 列表中。

解决这两个问题后,我在问题中发布的代码按预期工作。

查看MSAL js 的源代码,您应该能够使用acquireTokenRedirect 而不是acquireTokenPopup。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM