將驗證新增至 Xamarin.Android 應用程式

在本教學課程中,您會使用 Microsoft Entra ID 將 Microsoft 驗證新增至 TodoApp 專案。 完成本教學課程之前,請確定您已 建立專案並部署後端

提示

雖然我們使用 Microsoft Entra ID 進行驗證,但您可以使用任何您想要與 Azure Mobile Apps 搭配使用的驗證連結庫。

將驗證新增至後端服務

您的後端服務是標準 ASP.NET 6 服務。 任何示範如何啟用 ASP.NET 6 服務驗證與 Azure Mobile Apps 搭配運作的教學課程。

若要為您的後端服務啟用 Microsoft Entra 驗證,您需要:

  • 使用 Microsoft Entra ID 註冊應用程式。
  • 將驗證檢查新增至 ASP.NET 6 個後端專案。

註冊應用程式

首先,在 Microsoft Entra 租用戶中註冊 Web API,並遵循下列步驟來新增範圍:

  1. 登入 Azure 入口網站

  2. 如果您有多個租使用者的存取權,請使用 頂端功能表中的 [目錄 + 訂 用帳戶] 篩選,切換至您要在其中註冊應用程式的租使用者。

  3. 搜尋並選取 [Microsoft Entra ID]

  4. 在 [管理] 底下,選取 [應用程式註冊]> [新增註冊]

    • 名稱:輸入應用程式的名稱;例如 TodoApp 快速入門。 您應用程式的使用者會看到此名稱。 稍後可加以變更。
    • 支援的帳戶類型任何組織目錄中的帳戶(任何 Microsoft Entra 目錄 - 多租使用者)和個人 Microsoft 帳戶(例如 Skype、Xbox)
  5. 選取註冊

  6. 在 [管理] 底下,選取 [公開 API>新增範圍]。

  7. 針對 [ 應用程式識別碼 URI],選取 [ 儲存並繼續],以接受預設值。

  8. 輸入下列詳細資料:

    • 範圍名稱access_as_user
    • 神秘 可以同意?管理員 和使用者
    • 管理員 同意顯示名稱Access TodoApp
    • 管理員 同意描述Allows the app to access TodoApp as the signed-in user.
    • 使用者同意顯示名稱Access TodoApp
    • 使用者同意描述Allow the app to access TodoApp on your behalf.
    • 狀態已啟用
  9. 選取 [新增範圍 ] 以完成新增範圍。

  10. 請注意範圍的值,類似於 api://<client-id>/access_as_user (稱為 Web API 範圍)。 設定用戶端時,您需要範圍。

  11. 選取 [概觀]

  12. 請注意 Essentials 區段中的應用程式(用戶端)標識碼(稱為 Web API 應用程式識別碼)。 您需要此值來設定後端服務。

開啟 Visual Studio 並選取 TodoAppService.NET6 專案。

  1. 以滑鼠右鍵按兩下 TodoAppService.NET6 項目,然後選取 [ 管理 NuGet 套件...]。

  2. 在新的索引標籤中,選取 [流覽],然後在搜尋方塊中輸入 Microsoft.Identity.Web

    Screenshot of adding the M S A L NuGet in Visual Studio.

  3. 選取套件 Microsoft.Identity.Web ,然後按 [安裝]。

  4. 請遵循提示來完成套件的安裝。

  5. 開啟 [Program.cs]。 將下列內容新增至 語句清單 using

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
  1. 將下列程式代碼直接新增至 builder.Services.AddDbContext()的呼叫上方:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
  1. 將下列程式代碼直接新增至 app.MapControllers()的呼叫上方:
app.UseAuthentication();
app.UseAuthorization();

您的 Program.cs 現在看起來應該像這樣:

using Microsoft.AspNetCore.Datasync;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using TodoAppService.NET6.Db;
  
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
  
if (connectionString == null)
{
  throw new ApplicationException("DefaultConnection is not set");
}
  
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDatasyncControllers();
  
var app = builder.Build();
  
// Initialize the database
using (var scope = app.Services.CreateScope())
{
  var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
  await context.InitializeDatabaseAsync().ConfigureAwait(false);
}
  
// Configure and run the web service.
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
  1. Controllers\TodoItemController.cs編輯 。 [Authorize]將屬性新增至 類別。 您的類別看起來應該像這樣:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Datasync;
using Microsoft.AspNetCore.Datasync.EFCore;
using Microsoft.AspNetCore.Mvc;
using TodoAppService.NET6.Db;

namespace TodoAppService.NET6.Controllers
{
  [Authorize]
  [Route("tables/todoitem")]
  public class TodoItemController : TableController<TodoItem>
  {
    public TodoItemController(AppDbContext context)
      : base(new EntityTableRepository<TodoItem>(context))
    {
    }
  }
}
  1. appsettings.json編輯 。 新增下列區塊:
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },

<client-id>將取代為您稍早記錄的 Web API 應用程式識別碼。 完成後,看起來應該像這樣:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

再次將您的服務發佈至 Azure:

  1. 以滑鼠右鍵按兩下 TodoAppService.NET6 項目,然後選取 [ 發佈...]。
  2. 選取索引標籤右上角的 [ 發佈] 按鈕。

開啟瀏覽器並前往 https://yoursite.azurewebsites.net/tables/todoitem?ZUMO-API-VERSION=3.0.0。 請注意,服務現在會 401 傳回回應,指出需要驗證。

Screenshot of the browser showing an error.

向身分識別服務註冊您的應用程式

Microsoft 資料同步架構內建支援任何在 HTTP 交易標頭內使用 Json Web 令牌 (JWT) 的驗證提供者。 此應用程式會使用 Microsoft 驗證連結庫 (MSAL) 來要求這類令牌,並將登入的使用者授權給後端服務。

設定原生用戶端應用程式

您可以註冊原生用戶端,以允許使用 Microsoft 身分識別連結庫 (MSAL) 等用戶端連結庫來驗證裝載在應用程式中的 Web API。

  1. Azure 入口網站 中,選取 [Microsoft Entra ID> 應用程式註冊>[新增註冊]。

  2. 在 [ 註冊應用程式] 頁面中:

    • 輸入應用程式註冊的名稱。 您可能想要使用名稱來區別後端服務所使用的名稱 native-quickstart
    • 選取任何組織目錄中的帳戶(任何 Microsoft Entra 目錄 - 多租使用者)和個人 Microsoft 帳戶(例如 Skype、Xbox)。
    • 在 [重新導向 URI] 中
      • 選取 [公用用戶端] (行動裝置和桌面版)
      • 輸入 URL quickstart://auth
  3. 選取註冊

  4. 選取 [API 許可權>][新增許可權>我的 API]。

  5. 選取您稍早為後端服務建立的應用程式註冊。 如果您沒有看到應用程式註冊,請確定您已新增 access_as_user 範圍。

    Screenshot of the scope registration in the Azure portal.

  6. 在 [選取許可權] 底,選取 [access_as_user],然後選取 [新增許可權]。

  7. 選取 [驗證>行動裝置和傳統型應用程式]。

  8. 核取 旁的 https://login.microsoftonline.com/common/oauth2/nativeclient方塊。

  9. 核取旁邊的 msal{client-id}://auth 方塊(以您的應用程式識別碼取代 {client-id} )。

  10. 選取 [ 新增 URI],然後在字段中新增 http://localhost 額外的 URI。

  11. 選取頁面底部的 [ 儲存 ]。

  12. 選取 [概觀]。 記下 應用程式(用戶端)標識碼 (稱為 原生用戶端應用程式識別符),因為您需要它才能設定行動應用程式。

我們已定義三個重新導向 URL:

  • http://localhost 由 WPF 應用程式使用。
  • https://login.microsoftonline.com/common/oauth2/nativeclient 由 UWP 應用程式使用。
  • msal{client-id}://auth 是由行動裝置 (Android 和 iOS) 應用程式使用。

將 Microsoft Identity Client 新增至您的應用程式

TodoApp.sln在 Visual Studio 中開啟方案,並將專案設定TodoApp.Android為啟始專案。 將 Microsoft Identity Library (MSAL) 新增至 TodoApp.Android 專案:

Microsoft Identity Library (MSAL) 新增至平台專案:

  1. 以滑鼠右鍵按兩下項目,然後選取 [ 管理 NuGet 套件...]。

  2. 選取 [瀏覽] 索引標籤。

  3. 在搜尋方塊中輸入 Microsoft.Identity.Client ,然後按 Enter。

  4. Microsoft.Identity.Client選取結果,然後按兩下 [安裝]。

    Screenshot of selecting the MSAL NuGet in Visual Studio.

  5. 接受許可協議以繼續安裝。

將原生用戶端標識碼和後端範圍新增至組態。

TodoApp.Data開啟專案並編輯Constants.cs檔案。 為和 Scopes新增常數ApplicationId

  public static class Constants
  {
      /// <summary>
      /// The base URI for the Datasync service.
      /// </summary>
      public static string ServiceUri = "https://demo-datasync-quickstart.azurewebsites.net";

      /// <summary>
      /// The application (client) ID for the native app within Microsoft Entra ID
      /// </summary>
      public static string ApplicationId = "<client-id>";

      /// <summary>
      /// The list of scopes to request
      /// </summary>
      public static string[] Scopes = new[]
      {
          "<scope>"
      };
  }

<client-id>將 取代為您在 Microsoft Entra ID 中註冊用戶端應用程式時收到的 Native Client Application ID,並以<scope>您在註冊服務應用程式時使用公開 API 時複製的 Web API 範圍取代 。

MainActivity.cs開啟專案中的TodoApp.Android檔案。 在檔案頂端,新增下列using語句:

using Android.Content;
using Microsoft.Identity.Client;
using Microsoft.Datasync.Client;
using System.Linq;
using System.Threading.Tasks;
using Debug = System.Diagnostics.Debug;

在 類別頂端 MainActivity ,新增下列欄位:

public IPublicClientApplication identityClient;

在 方法中 OnCreate() ,變更 的定義 TodoService

TodoService = new RemoteTodoService(GetAuthenticationToken);

新增下列程式代碼以定義 GetAuthenticationToken() 方法:

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    if (identityClient == null)
    {
        identityClient = PublicClientApplicationBuilder.Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .WithParentActivityOrWindow(() => this)
            .Build();
    }

    var accounts = await identityClient.GetAccountsAsync();
    AuthenticationResult result = null;
    bool tryInteractiveLogin = false;

    try
    {
        result = await identityClient
            .AcquireTokenSilent(Constants.Scopes, accounts.FirstOrDefault())
            .ExecuteAsync();
    }
    catch (MsalUiRequiredException)
    {
        tryInteractiveLogin = true;
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"MSAL Silent Error: {ex.Message}");
    }

    if (tryInteractiveLogin)
    {
        try
        {
            result = await identityClient
                .AcquireTokenInteractive(Constants.Scopes)
                .ExecuteAsync()
                .ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"MSAL Interactive Error: {ex.Message}");
        }
    }

    return new AuthenticationToken
    {
        DisplayName = result?.Account?.Username ?? "",
        ExpiresOn = result?.ExpiresOn ?? DateTimeOffset.MinValue,
        Token = result?.AccessToken ?? "",
        UserId = result?.Account?.Username ?? ""
    };
}

方法 GetAuthenticationToken() 可與 Microsoft Identity Library (MSAL) 搭配運作,以取得適合將登入使用者授權至後端服務的存取令牌。 接著,此函式會傳遞至 RemoteTodoService ,以建立用戶端。 如果驗證成功, AuthenticationToken 則會使用授權每個要求所需的資料來產生 。 如果沒有,則會改為產生過期的不正確令牌。

新增下列方法,以處理來自身分識別用戶端的回呼:

protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    // Return control to MSAL
    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}

使用下列程式代碼建立新的類別 MsalActivity

using Android.App;
using Android.Content;
using Microsoft.Identity.Client;

namespace TodoApp.Android
{
    [Activity(Exported = true)]
    [IntentFilter(new[] { Intent.ActionView },
        Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
        DataHost = "auth",
        DataScheme = "msal{client-id}")]
    public class MsalActivity : BrowserTabActivity
    {
    }
}

將取代 {client-id} 為原生用戶端的應用程式識別碼(與 相同 Constants.ApplicationId)。

如果您的專案以 Android 11 版(API 第 30 版)或更新版本為目標,您必須更新 , AndroidManifest.xml 以符合 Android 套件可見性需求。 開啟 Properties/AndroidManifest.xml ,並將下列 queries/intent 節點新增至 manifest 節點:

<manifest>
  ...
  <queries>
    <intent>
      <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
  </queries>
</manifest>

測試應用程式

執行或重新啟動應用程式。

當應用程式執行時,會開啟瀏覽器以要求您進行驗證。 如果您之前尚未向應用程式進行驗證,應用程式會要求您同意。 驗證完成之後,系統瀏覽器就會關閉,且您的應用程式會如先前一樣執行。

下一步

接下來,藉由 實作離線存放區,將您的應用程式設定為離線運作。

進一步閱讀