[Azure] 即使使用WebAPI進行二次Azure AD驗證,也可以透過GraphAPI取得帳號詳細資訊

在前篇文章[Azure] 透過GraphAPI,取得Azure AD上帳號的詳細資訊中提到可以透過GraphAPI取得Azure AD的帳號資訊
但是若是App與WebAPI上啟用了二次驗證的情況下,驗證得到的結果就會出錯無法取得資訊

Azure AD與WebAPI的二次驗證可以參考之前的文章
[Azure] [Xamarin] 利用Xamarin進行Azure AD驗證與WebAPI的連接,並達成於WebAPI上進行二次Azure AD帳號驗證

在這種情況下若是驗證成功後,再進行GraphAPI欲取得使用者帳號資訊,就會發生下圖的錯誤
"Authentication_MissingOrMalformed", "Access Token missing or malformed"

這是很矛盾的一件事,因為加上了WebAPI的二次驗證,必須將ResourceUri採用WebApp/WeAPI的應用程式識別Uri,但是卻又在取得Azure AD上帳號及詳細資訊時發生驗證失敗的問題

要解決的方式,很簡單,也讓人覺得很不可思議
作法就是...

graph.windows.net與自訂的應用程式識別Uri各別都執行一次驗證就可以

真的很蠢,不過這是目前能夠得到的最佳解法....

程式碼如下所示

// 如果要進行App驗證,請使用下面的graphResourceUri
private const string graphResourceUri = "https://graph.windows.net";

// 如果要啟用WebAPI整合驗證,請使用下面的graphResourceUri
private const string graphAppResourceUri = "[在這裡填上WebAPI的應用程式識別 URI]";

/// <summary>
/// 點選登入的動作
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void btnLogin_Click(object sender, EventArgs e)
{
    // 進行自訂應用程式識別Uri登入,並取得基本的AAD資訊
    var objAppAuthResult = await iAuth.Authenticate(authority, graphAppResourceUri, clientId, returnUri);
    // 進行graph.windows.net的登入
    var objGraphAuthResult = await iAuth.Authenticate(authority, graphResourceUri, clientId, returnUri);

    // 取得 WebAPI上的資訊,並於WebAPI進行二次驗證(使用自訂應用程式識別Uri的驗證結果登入)
    var client = new HttpClient();
    var request = new HttpRequestMessage(HttpMethod.Get, webAPIUri);
    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", objAppAuthResult.AccessToken);
    var response = await client.SendAsync(request);
    var content = await response.Content.ReadAsStringAsync();
    await DisplayAlert("webapi", content, "Ok");

    // 取得AAD中詳細的資訊 (使用graph.windows.net的驗證結果登入)
    Models.AzureAD.UserProfile objProfile = await this.GetAADUserInfo(objGraphAuthResult);
    lblUserDisplayName.Text = objProfile.displayName;
}

這段程式碼主要是在一開始的時候,就進行兩次Azure AD的驗證,分別是graph.windows.net與自訂應用程式識別Uri的登入驗證
然後下方在取得WebAPI值的時候,傳入自訂應用程式識別Uri的驗證Token,要取得Azure AD詳細資訊時,用graph.windows.net的驗證Token

這樣作的話就可以取得兩個不同的Token並進行操作
所幸的是,驗證登入的動作不會因為分別取得兩個不同的Token而要登入兩次,對使用者來說,只要登入一次就可以了

得到的結果,WebAPI上的值可以正確取得

Azure AD上的使用者詳細資訊也可以取得

範例程式下載:
https://github.com/madukapai/maduka-Xamarin