2017-10-17 97 views
4

我试图让Angular 4应用程序正确使用Azure AD B2C进行隐式身份验证。我使用msal.js来尝试使其工作。我已经检查了非常有限的official sample code,但它没有实际用处,因为它使用弹出窗口登录,我想重新定向。登录使用Azure AD B2C从Angular应用程序和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令牌”确实收到了我可以使用的值,但是时间有限。

问题是当我尝试获取身份验证令牌时。第一个电话,到​​返回一个错误,说: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页面(具有天气预报的页面),您可以看到验证令牌被​​正确兑换(打开浏览器控制台以获取所有日志)。但是,如果直接在fetchData上刷新页面,则可以看到与我描述的行为相同的行为,其中​​因超时错误而失败。

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

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

+0

我想知道会发生什么[如果你尝试localStorage](https://stackoverflow.com/questions/45201872/how-to-use-localstorage-with-msal-js)? – spottedmahn

+0

@spottedmahn刚刚尝试过,它的行为是一样的。 – Gimly

+0

@spottedmahn我发现了更多关于这个问题的信息,你能检查我的编辑吗? – Gimly

回答

2

OK,所以我面临的问题是由两个因素引起:

1)引起的初始化过程不是在构造函数调用结束时全面完成msal.js一个bug,和我在完全初始化之前调用了acquireTokenSilent()。这是在最新版本中解决的(截至撰写时,仍在项目的开发分支中)。 See this GitHub issue for more info

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

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

+0

你能源#1?你有一个Github的问题,你可以链接到? – spottedmahn

+1

@spottedmahn更新了GitHub问题的答案。 – Gimly

+0

@Gimly请问您可以将您的导入添加到示例中,我正在尝试使用和旧版本的msal(0.1.1),该文件引用auth服务中“out”目录中的文件。这似乎不再存在,所以我的进口不起作用? – Magrangs

0

查看MSAL js的source code,您应该能够使用acquireTokenRedirect而不是acquireTokenPopup。

+0

如果我有一个有效的'id_token',为什么我不能调用'acquireTokenSilent()'?我只是重定向用户登录,为什么我想再次重定向他们? – spottedmahn

+1

那么,acquireTokenRedirect似乎也不会好得多。它会创建一个双重重定向,就像@spottedmahn所说的那样。 – Gimly

+1

@parakh我更新了我的问题,提供了更多信息和一个可以复制问题的项目。 – Gimly

相关问题