次の方法で共有


Xamarin.Forms アプリに認証を追加する

手記

この製品は提供終了です。 .NET 8 以降を使用するプロジェクトの代わりに、Community Toolkit Datasync ライブラリを参照してください。

このチュートリアルでは、Microsoft Entra ID を使用して Microsoft 認証をアプリに追加します。 このチュートリアルを完了する前に、プロジェクト 作成し、バックエンドをデプロイしていることを確認してください。

手記

iOS アプリにはキーチェーン アクセスが必要であるため、iOS プロビジョニング プロファイルを設定する必要があります。 プロビジョニング プロファイルには、実際の iOS デバイスまたは有料の Apple Developer アカウント (シミュレーターを使用している場合) が必要です。 この制限により認証を使用できない場合は、このチュートリアルをスキップし、アプリ へのオフライン アクセス 追加に進むことができます。

先端

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 portalにサインインします。

  2. 複数のテナントにアクセスできる場合は、上部のメニューの ディレクトリとサブスクリプション フィルターを使用して、アプリケーションを登録するテナントに切り替えます。

  3. Microsoft Entra ID検索して選択します。

  4. [管理] で、[新しい登録][アプリの登録] 選択します。

    • 名前: アプリケーションの名前を入力します。たとえば、TodoApp クイック スタートを します。 アプリのユーザーには、この名前が表示されます。 後で変更できます。
    • サポートされているアカウントの種類: 任意の組織ディレクトリ (任意の Microsoft Entra ディレクトリ - マルチテナント) と個人の Microsoft アカウント (Skype、Xbox など) にアカウントを
  5. [登録] を選択します。

  6. [管理] で、[API の公開][スコープの追加] 選択します。

  7. アプリケーション ID 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 アプリケーション IDと呼ばれます) の アプリケーション (クライアント) ID に注意してください。 バックエンド サービスを構成するには、この値が必要です。

Visual Studio を開き、TodoAppService.NET6 プロジェクトを選択します。

  1. プロジェクトを右クリックし、[NuGet パッケージの管理]<選択します。..します。

  2. 新しいタブで、[参照選択し、検索ボックス 「Microsoft.Identity.Web」と入力します。

    Visual Studio で M S A L NuGet を追加するスクリーンショット。

  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 アプリケーション ID に置き換えます。 完了すると、次のようになります。

{
  "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 応答を返すようになったことに注意してください。

エラーが表示されているブラウザーのスクリーンショット。

ID サービスにアプリを登録する

Microsoft Data Sync Framework には、HTTP トランザクションのヘッダー内で Json Web トークン (JWT) を使用する認証プロバイダーが組み込まれています。 このアプリケーションは、Microsoft Authentication Library (MSAL) を使用してこのようなトークンを要求し、サインインしているユーザーをバックエンド サービスに承認します。

ネイティブ クライアント アプリケーションを構成する

ネイティブ クライアントを登録して、Microsoft Identity Library (MSAL) などのクライアント ライブラリを使用して、アプリでホストされている Web API への認証を許可できます。

  1. Azure portalで、[新規登録][Microsoft Entra IDアプリの登録] を 選択します。

  2. [アプリケーション の登録] ページで、次の手順を実行します。

    • アプリ登録の 名前 を入力します。 名前 native-quickstart を使用して、バックエンド サービスで使用される名前と区別することができます。
    • 任意の組織ディレクトリ (任意の Microsoft Entra ディレクトリ - マルチテナント) と個人の Microsoft アカウント (Skype、Xbox など)アカウントを選択します。
    • リダイレクト URI :
      • パブリック クライアント (モバイル & デスクトップ) を選択します
      • URL quickstart://auth を入力します
  3. [登録] を選択します。

  4. [API のアクセス許可 選択[マイ APIにアクセス許可追加します。

  5. バックエンド サービス用に先ほど作成したアプリ登録を選択します。 アプリの登録が表示されない場合は、access_as_user スコープを追加したことを確認してください。

    Azure portal でのスコープの登録のスクリーンショット。

  6. [アクセス許可選択] で、access_as_userを選択し、[アクセス許可の追加]選択します。

  7. [認証>モバイルアプリケーションとデスクトップアプリケーションを選択します。

  8. [https://login.microsoftonline.com/common/oauth2/nativeclient] の横にあるチェック ボックスをオンにします。

  9. msal{client-id}://auth の横にあるチェック ボックスをオンにします ({client-id} をアプリケーション ID に置き換えます)。

  10. [URIの追加] を選択し、追加の URI のフィールドに http://localhost を追加します。

  11. ページ 下部にある [保存] を選択します。

  12. [概要]選択します。 モバイル アプリを構成するために必要な アプリケーション (クライアント) ID (ネイティブ クライアント アプリケーション IDと呼ばれます) を書き留めます。

次の 3 つのリダイレクト URL を定義しました。

  • http://localhost は、WPF アプリケーションで使用されます。
  • https://login.microsoftonline.com/common/oauth2/nativeclient は、UWP アプリケーションで使用されます。
  • msal{client-id}://auth は、モバイル (Android および iOS) アプリケーションで使用されます。

Microsoft Identity Client をアプリに追加する

Visual Studio で TodoApp.sln ソリューションを開き、TodoApp.Forms プロジェクトをスタートアップ プロジェクトとして設定します。

Microsoft Identity Library (MSAL) をプラットフォーム プロジェクトに追加します。

  1. プロジェクトを右クリックし、[NuGet パッケージの管理 選択します。..します。

  2. [参照] タブ 選択します。

  3. 検索ボックスに「Microsoft.Identity.Client」と入力し、Enter キーを押します。

  4. 結果を選択し、[インストール] をクリックします。

    Visual Studio で MSAL NuGet を選択するスクリーンショット。

  5. 使用許諾契約書に同意してインストールを続行します。

ネイティブ クライアント ID とバックエンド スコープを構成に追加します。

TodoApp.Data プロジェクトを開き、Constants.cs ファイルを編集します。 ApplicationIdScopesの定数を追加します。

  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>"
      };
  }

は、Microsoft Entra ID でクライアント アプリケーションを登録するときに受け取った ネイティブ クライアント アプリケーション ID に置き換え、サービス アプリケーションの登録中に API を公開 使用したときにコピーした Web API スコープ に置き換えます。

TodoApp.Forms プロジェクトを開きます。 次の内容で IPlatform.cs という名前の新しいファイルを追加します。

using Microsoft.Identity.Client;

namespace TodoApp.Forms
{
    public interface IPlatform
    {
        IPublicClientApplication GetIdentityClient(string applicationId);
    }
}

このインターフェイスは、後で共有プロジェクトがプラットフォームに適した ID クライアントをプラットフォーム プロジェクトに要求できるようにするために使用されます。

App.xaml.csを開きます。 次の using ステートメントを追加します。

using Microsoft.Datasync.Client;
using Microsoft.Identity.Client;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

App クラスで、次の 2 つの新しいプロパティを追加します。

public IPublicClientApplication IdentityClient { get; set; }
public IPlatform PlatformService { get; }

読み取るコンストラクターを調整します。

public App(IPlatform platformService)
{
    InitializeComponent();

    PlatformService = platformService;
    TodoService = new RemoteTodoService(GetAuthenticationToken);
    MainPage = new NavigationPage(new MainPage(this, TodoService));
}

GetAuthenticationToken メソッドをクラスに追加します。

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    if (IdentityClient == null)
    {
        IdentityClient = PlatformService.GetIdentityClient(Constants.ApplicationId);
    }

    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 が生成されます。 そうでない場合は、期限切れの無効なトークンが代わりに生成されます。

認証用に Android アプリを構成する

TodoApp.Forms.Android プロジェクトを開きます。 次のコードを使用して、新しいクラス MsalActivity を作成します。

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

namespace TodoApp.Forms.Droid
{
    [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} をネイティブ クライアントのアプリケーション ID (Constants.ApplicationIdと同じ) に置き換えます。

プロジェクトが Android バージョン 11 (API バージョン 30) 以降を対象とする場合は、AndroidManifest.xml を更新して、Android パッケージの表示要件満たす必要があります。 TodoApp.Forms.Android/Properties/AndroidManifest.xml を開き、次の queries/intent ノードを manifest ノードに追加します。

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

MainActivity.csを開きます。 MainActivity クラスの定義に IPlatform を追加します。

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IPlatform

OnCreate() メソッドの LoadApplication() 呼び出しを変更します。

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

    Xamarin.Essentials.Platform.Init(this, savedInstanceState);
    global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
    LoadApplication(new App(this));
}

クラスの下部に次のコードを追加します。

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);
}

public IPublicClientApplication GetIdentityClient(string applicationId)
{
    var identityClient = PublicClientApplicationBuilder.Create(applicationId)
        .WithAuthority(AzureCloudInstance.AzurePublic, "common")
        .WithRedirectUri($"msal{applicationId}://auth")
        .WithParentActivityOrWindow(() => this)
        .Build();
    return identityClient;
}

共有プロジェクトで認証が必要な場合は、GetIdentityClient()から ID クライアントを取得し、システム ブラウザーを開く内部アクティビティに切り替えます。 認証が完了すると、システム ブラウザーは定義済みのリダイレクト URL (msal{client-id}://auth) にリダイレクトします。 MsalActivity はリダイレクト URL をトラップし、OnActivityResult()を呼び出してメイン アクティビティに戻ります。 その後、MSAL 認証ヘルパーが呼び出され、トランザクションが完了します。

認証用に iOS アプリを構成する

TodoApp.Forms.iOS プロジェクトで AppDelegate.cs ファイルを開きます。 AppDelegate クラスの定義に IPlatform を追加します。

public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IPlatform

読み取る FinishedLaunching() メソッドを変更します。

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App(this));
    return base.FinishedLaunching(app, options);
}

クラスの末尾に次のコードを追加します。

public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
    bool result = AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
    return result || base.OpenUrl(app, url, options);
}

public IPublicClientApplication GetIdentityClient(string applicationId)
{
    var identityClient = PublicClientApplicationBuilder.Create(applicationId)
        .WithIosKeychainSecurityGroup("com.microsoft.adalcache")
        .WithRedirectUri($"msal{applicationId}://auth")
        .Build();
    return identityClient;
}

Entitlements.plistにキーチェーン アクセスを追加します。

  1. Entitlements.plist ファイルを開きます。

  2. キーチェーン選択します。

  3. キーチェーン グループ [新しい の追加] を選択します。

  4. 値として「com.microsoft.adalcache」と入力します。

    i O S エンタイトルメントを示すスクリーンショット。

プロジェクトにカスタムエンタイトルメントを追加します。

  1. プロジェクトを右クリックし、[プロパティ]選択します。

  2. iOS バンドル署名選択します。

  3. ユーザー設定エンタイトルメント フィールドの横にある ... ボタンを選択します。

  4. [] を選択し、[を開く] 選択します。

  5. Ctrl + S 押してプロジェクトを保存します。

    i O S バンドル署名プロパティを示すスクリーンショット。

Android アプリをテストする

スタートアップ プロジェクトとして 設定し、F5 押してアプリをビルドして実行します。 アプリが起動すると、アプリにサインインするように求められます。 最初の実行時に、アプリに同意するように求められます。 認証が完了すると、アプリは通常どおりに実行されます。

iOS アプリをテストする

手記

iOS アプリにはキーチェーン アクセスが必要であるため、プロビジョニング プロファイルを設定する必要があります。 プロビジョニング プロファイルには、実際のデバイスまたは有料の Apple デベロッパー アカウント (シミュレーターを使用している場合) が必要です。 詳細については、「iOSのデバイス プロビジョニング」を参照してください。

スタートアップ プロジェクトとして 設定し、F5 押してアプリをビルドして実行します。 アプリが起動すると、アプリにサインインするように求められます。 最初の実行時に、アプリに同意するように求められます。 認証が完了すると、アプリは通常どおりに実行されます。

次の手順

次に、オフライン ストアを実装 して、オフラインで動作するようにアプリケーションを構成します。

詳細については、次を参照してください。