在前篇文章[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上的使用者詳細資訊也可以取得