[Azure] [Xamarin] 利用Xamarin進行Azure AD驗證與WebAPI的連接,並達成於WebAPI上進行二次Azure AD帳號驗證

在前篇[Azure] [Xamarin] 使用Xamarin.Forms達成Azure AD的帳號驗證中說明了如何透過Xamarin進行Azure AD帳號的驗證

本篇會延續這個主題,將Xamrin App要連接WebAPI時,進行二次Azure AD驗證的作法

[Azure] [Xamarin] 使用Xamarin.Forms達成Azure AD的帳號驗證這篇文章中有說明到,如何透過Xamarin的App進行Azure AD的登入驗證
但是這對於App與整體規劃架構來說是不夠的,因為行動化裝置中,取得WebAPI進行資料交換佔了App中相當大比例的動作
所以除了App端進行Azure AD帳號驗證外,也需要在WebAPI這一層再次的驗證,連入WebAPI的客戶端是否為正確的Azure AD帳號

設定的方式很簡單,依照下面的步驟就可以完成了

在Azure AD中,加入一個應用程式,這個應用程式必須有別於上一篇文章中所建立的類別,請選擇[WEB應用程式和/或WEB API]

應用程式屬性設定中,分別輸入登入URL以及應用程式識別碼URI,其中,[應用程式識別碼URI]請先記下來,等一下會用到

建立完成後,進入應用程式的設定頁,加入一份金鑰,金鑰加入後,按下儲存才會顯示在畫面上,請第一時間將這個金鑰值記錄下來

在應用程式設定頁中,其他應用程式的權限項目,加上下方的設定[Read directory data]

委派的權限請加入[Read directory data][Sign in and read user profile]

用戶端識別碼也請記下來,等下會用到

接著,回到上一篇文章裡,已經建好的原生App的應用程式設定中,將剛剛建好的WebApp/WebAPI應用程式加入,並設定委派權限

到這裡,Azure AD上的設定都已經完成了,接著就可以回到Visual Studio中,建立一個全新的WebAPI的WebApp

在這個WebAPI中,加入[Microsoft.IdentityModel.Clients.ActiveDirectory]這個Nuget套件

另外也要加入[Microsoft.Owin.Security.ActiveDirectory]這個Nuget套件

在專案上點右鍵,並選擇[設定 Azure AD 驗證]

在設定Azure AD驗證的畫面中,將網域,以及應用程式識別 URI填入,然後選擇現有的Azure AD應用程式設定

接著,請在用戶端密碼欄位上,加入剛剛取得的金鑰字串

在Web.Config裡,加入下面的設定

<add key="ida:Tenant" value="[Domain名稱]" />
<add key="ida:Audience" value="[應用程式識別碼 URI]" />
<add key="ida:ClientID" value="[用戶端識別碼GUID]" />
<add key="ida:Password" value="[金鑰]" />

這邊的設定主要是在告訴Microsoft.IdentityModel.Clients.ActiveDirectory套件,Azure AD上驗證的資訊

在設定Azure AD驗證完成之後,Web.Config的內容會自動加入,無需手動編輯

接著開啟App_Start\Startup.Auth.cs,加入下方程式碼

using Microsoft.Owin.Security.ActiveDirectory;
public void ConfigureAuth(IAppBuilder app)
{
    app.UseWindowsAzureActiveDirectoryBearerAuthentication(
        new WindowsAzureActiveDirectoryBearerAuthenticationOptions
        {
            Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
            TokenValidationParameters = new TokenValidationParameters
            {
                ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
            },
        });
}
在設定Azure AD驗證完成之後,Startup.Auth.cs的內容也會自動加入,無需手動編輯

設定完成後,就把這個WebAPI直接發佈至雲端WebApp

發佈過程中,有一個設定為[啟用組織驗證],請記得取消打勾,因為我們剛剛已經把組織驗證所有的動作都作完了,這裡無需再次執行

接著,回到Xamarin的App,將Xamarin裡,graphResourceUri這個參數,從原本的https://graph.windows.net,更改成[應用程式識別碼  URI],並在Xamarin中加上下面的程式碼

public static string clientId = "[在這裡填上原生App用戶端識別碼]";
public static string returnUri = "[在這裡填上原生App重新導向URI]";
public static string authority = "https://login.windows.net/common";
private const string graphResourceUri = "[在這裡填上WebApp/WebAPI的應用程式識別 URI]";
public static string graphApiVersion = "2013-11-08";

// 登入的驗證
var data = await iAuth.Authenticate(authority, graphResourceUri, clientId, returnUri);
var userName = data.UserInfo.GivenName + " " + data.UserInfo.FamilyName;
await DisplayAlert("Token", userName, "Ok", "Cancel");

// 取得WebAPI的資訊
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "[WebAPI的URL]");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", data.AccessToken);
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
await DisplayAlert("webapi", content, "Ok");

這段主要的目的,就是當連入WebAPI的時候,同時把從AAD上取得的AccessToken的Header一同傳至WebAPI端,讓WebAPI進行二次驗證的動作

最後,打開模擬器,並執行Xamarin的程式,可以順利取得WebAPI上的值了

如果是透過瀏覽器直接打開WebAPI的頁面,則會跳出沒有授權的訊息

這樣一來,要完成前端AAD驗證與後端WebAPI的介接動作,就大功告成了,對於WebAPI的安全性設定,也就有更進一步的保障

網路上找到的文章或是官方提供的文件都很片段與零散,所以參考文件請斟酌使用

參考資料:
Protect a Web API using Bearer tokens from Azure AD
Azure Active Directory Code Samples
https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof
How to protect a Web API backend with Azure Active Directory and API Management
ASP.NET Web API - Secure ASP.NET Web API with Windows Azure AD and Microsoft OWIN Components
Authentication Scenarios for Azure AD
Secure ASP.NET Web API 2 using Azure Active Directory, Owin Middleware, and ADAL

範例程式已放上GitHub:
https://github.com/madukapai/maduka-Xamarin