2017-10-17 153 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

相關問題