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

概要

このトピックでは、クライアント アプリケーションから App Service モバイル アプリのユーザーを認証する方法について説明します。 このチュートリアルでは、App Service でサポートされている ID プロバイダーを使用して、Xamarin Forms クイック スタート プロジェクトに認証を追加します。 モバイル アプリによって正常に認証、承認されると、ユーザー ID 値が表示され、制限付きのテーブル データにアクセスできます。

前提条件

このチュートリアルで最善の結果が得られるように、最初にチュートリアル「Xamarin.Forms アプリの作成」を完了しておくことをお勧めします。 このチュートリアルを完了すると、マルチプラットフォーム TodoList アプリである Xamarin Forms プロジェクトを作成できます。

ダウンロードしたクイック スタートのサーバー プロジェクトを使用しない場合は、認証拡張機能パッケージをプロジェクトに追加する必要があります。 サーバーの拡張機能パッケージの詳細については、「 Work with the .NET backend server SDK for Azure Mobile Apps (Azure Mobile Apps 用の .NET バックエンド サーバー SDK を操作する)」を参照してください。

アプリケーションを認証に登録し、App Services を構成する

最初に、ID プロバイダーのサイトでアプリを登録する必要があります。その後、プロバイダーによって生成された資格情報を Mobile Apps バックエンドに設定します。

  1. 次のプロバイダー固有の指示に従い、任意の ID プロバイダーを構成します。

  2. アプリ内でサポートするプロバイダーごとに、前の手順を繰り返します。

許可されている外部リダイレクト URL にアプリを追加する

認証をセキュリティで保護するには、アプリ用の新しい URL スキームの定義が必要になります。 これによって、認証プロセスが完了すると認証システムからアプリにリダイレクトできます。 このチュートリアル全体を通して、URL スキーム appname を使用します。 ただし、選択したあらゆる URL スキームを使用できます。 URL スキームは、モバイル アプリに対して一意である必要があります。 サーバー側でリダイレクトを有効にするには、以下の手順に従います。

  1. Azure Portal で、App Service を選択します。

  2. [認証/承認] メニュー オプションをクリックします。

  3. [Allowed External Redirect URLs (許可されている外部リダイレクト URL)]url_scheme_of_your_app://easyauth.callback を入力します。 この文字列の url_scheme_of_your_app は、モバイル アプリケーションの URL スキームです。 プロトコルの通常の URL 仕様 (文字と数字のみを使用し、文字で始まる) に従う必要があります。 数か所で URL スキームに合わせてモバイル アプリケーション コードを調整する必要があるため、選択した文字列をメモしておく必要があります。

  4. [OK] をクリックします。

  5. [保存] をクリックします。

アクセス許可を、認証されたユーザーだけに制限する

既定では、Mobile Apps バックエンドの API は匿名で呼び出すことができます。 次に、認証されたクライアントのみにアクセスを制限する必要があります。

  • Node.js バックエンド (Azure Portal 経由):

    Mobile Apps の設定で、[ 簡易テーブル ] をクリックし、テーブルを選択します。 [アクセス許可の変更] をクリックし、すべてのアクセス許可に対して [Authenticated access only (認証済みアクセスのみ)] を選択し、[保存] をクリックします。

  • .NET バックエンド (C#):

    サーバープロジェクトで、 Controllers>TodoItemControllerに移動します。 次のように、 [Authorize] 属性を TodoItemController クラスに追加します。 アクセスを特定のメソッドのみに制限するには、この属性を、クラスではなく、そのメソッドのみに適用するだけです。 サーバー プロジェクトを発行します。

      [Authorize]
      public class TodoItemController : TableController<TodoItem>
    
  • Node.js バックエンド (Node.js コード経由) :

    テーブルへのアクセスに対して認証を要求するには、Node.js サーバー スクリプトに次の行を追加します。

      table.access = 'authenticated';
    

    詳細については、「方法: テーブルへのアクセスに認証を要求する」を参照してください。 自社サイトからクイック スタート コード プロジェクトをダウンロードする方法については、「 方法: Git を使用して Node.js バックエンド クイック スタート コード プロジェクトをダウンロードする」を参照してください。

ポータブル クラス ライブラリに認証を追加する

Mobile Apps は、MobileServiceClientLoginAsync 拡張メソッドを使用して App Service 認証でユーザーをサインインさせます。 このサンプルでは、アプリにプロバイダーのサインイン インターフェイスが表示される、サーバー側管理認証フローを使用します。 詳細については、「 サーバー側管理認証」を参照してください。 運用アプリでユーザー エクスペリエンスを向上させるには、代わりにクライアントによって管理された認証を使用することを検討してください。

Xamarin Forms プロジェクトで認証するには、アプリのポータブル クラス ライブラリに IAuthenticate インターフェイスを定義します。 次に、ポータブル クラス ライブラリで定義されているユーザー インターフェイスに [サインイン] ボタンを追加します。このボタンは、認証を開始するためにクリックします。 認証が成功すると、モバイル アプリ バックエンドからデータが読み込まれます。

アプリでサポートされているプラットフォームごとに IAuthenticate インターフェイスを実装します。

  1. Visual Studio または Xamarin Studio で、ポータブルクラスライブラリプロジェクトである名前で、ポータブルを使用してプロジェクトから app.xaml を開き、次 using のステートメントを追加します。

     ```csharp
     using System.Threading.Tasks;
     ```
    
  2. App.cs に、次の IAuthenticate インターフェイス定義を、App クラス定義の直前に追加します。

     ```csharp
     public interface IAuthenticate
     {
         Task<bool> Authenticate();
     }
     ```
    
  3. インターフェイスをプラットフォーム固有の実装で初期化するように、次の静的メンバーを App クラスに追加します。

     ```csharp
     public static IAuthenticate Authenticator { get; private set; }
    
     public static void Init(IAuthenticate authenticator)
     {
         Authenticator = authenticator;
     }
     ```
    
  4. ポータブル クラス ライブラリ プロジェクトから TodoList.xaml を開き、既存のボタンの後ろに、 buttonsPanel レイアウト要素の次の Button 要素を追加します。

     ```xml
       <Button x:Name="loginButton" Text="Sign-in" MinimumHeightRequest="30"
         Clicked="loginButton_Clicked"/>
     ```
    

    このボタンは、モバイル アプリ バックエンドによるサーバー側管理認証をトリガーします。

  5. ポータブル クラス ライブラリ プロジェクトから TodoList.xaml.cs を開き、 TodoList クラスに次のフィールドを追加します。

     ```csharp
     // Track whether the user has authenticated.
     bool authenticated = false;
     ```
    
  6. OnAppearing メソッドを次のコードに置き換えます。

     ```csharp
     protected override async void OnAppearing()
     {
         base.OnAppearing();
    
         // Refresh items only when authenticated.
         if (authenticated == true)
         {
             // Set syncItems to true in order to synchronize the data
             // on startup when running in offline mode.
             await RefreshItems(true, syncItems: false);
    
             // Hide the Sign-in button.
             this.loginButton.IsVisible = false;
         }
     }
     ```
    

    このコードにより、認証の完了後にのみ、データがサービスによって更新されるようになります。

  7. Clicked イベントの次のハンドラーを TodoList クラスに追加します。

     ```csharp
     async void loginButton_Clicked(object sender, EventArgs e)
     {
         if (App.Authenticator != null)
             authenticated = await App.Authenticator.Authenticate();
    
         // Set syncItems to true to synchronize the data on startup when offline is enabled.
         if (authenticated == true)
             await RefreshItems(true, syncItems: false);
     }
     ```
    
  8. 変更を保存し、ポータブル クラス ライブラリ プロジェクトをリビルドしてエラーがないことを確認します。

Android アプリに認証を追加する

このセクションでは、Android アプリ プロジェクト内に IAuthenticate インターフェイスを実装する方法について説明します。 Android デバイスをサポートしない場合、このセクションはスキップしてください。

  1. Visual Studio または Xamarin Studio で、droid プロジェクトを右クリックし、 [スタートアップ プロジェクトに設定] をクリックします。

  2. F5 キーを押してデバッガーでプロジェクトを開始し、アプリの開始後に、状態コード 401 のハンドルされない例外 (許可されていません) が発生することを確認します。 401 コードは、バックエンドへのアクセスが承認済みのユーザーのみに制限されているために生成されます。

  3. Android プロジェクトの MainActivity.cs を開き、次の using ステートメントを追加します。

     ```csharp
     using Microsoft.WindowsAzure.MobileServices;
     using System.Threading.Tasks;
     ```
    
  4. 次のように、MainActivity クラスを更新して IAuthenticate インターフェイスを実装します。

     ```csharp
     public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity, IAuthenticate
     ```
    
  5. 次のように、MobileServiceUser フィールドのほか、IAuthenticate インターフェイスに必要な Authenticate メソッドを追加して、MainActivity クラスを更新します。

     ```csharp
     // Define an authenticated user.
     private MobileServiceUser user;
    
     public async Task<bool> Authenticate()
     {
         var success = false;
         var message = string.Empty;
         try
         {
             // Sign in with Facebook login using a server-managed flow.
             user = await TodoItemManager.DefaultManager.CurrentClient.LoginAsync(this, 
                 MobileServiceAuthenticationProvider.Facebook, "{url_scheme_of_your_app}");
             if (user != null)
             {
                 message = string.Format("you are now signed-in as {0}.",
                     user.UserId);
                 success = true;
             }
         }
         catch (Exception ex)
         {
             message = ex.Message;
         }
    
         // Display the success or failure message.
         AlertDialog.Builder builder = new AlertDialog.Builder(this);
         builder.SetMessage(message);
         builder.SetTitle("Sign-in result");
         builder.Create().Show();
    
         return success;
     }
    
     public override void OnResume()
     {
         base.OnResume();
         Xamarin.Essentials.Platform.OnResume();
     }
     ```
    

    Facebook 以外の ID プロバイダーを使用している場合、 MobileServiceAuthenticationProviderには別の値を選択してください。

  6. <application> 要素に次の XML を追加して、AndroidManifest.xml ファイルを更新します。

    <activity android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity" android:launchMode="singleTop" android:noHistory="true">
      <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="{url_scheme_of_your_app}" android:host="easyauth.callback" />
      </intent-filter>
    </activity>
    

    {url_scheme_of_your_app} を自分の URL スキームで置換します。

  7. LoadApplication() の呼び出しの前にある MainActivity クラスの OnCreate メソッドに次のコードを追加します。

     ```csharp
     // Initialize the authenticator before loading the app.
     App.Init((IAuthenticate)this);
     ```
    

    このコードにより、アプリの読み込み前に Authenticator が初期化されるようになります。

  8. アプリをリビルドして実行します。その後で、選択した認証プロバイダーを使用してサインインし、認証されたユーザーとしてデータにアクセスできることを確認します。

トラブルシューティング

アプリケーションが でクラッシュしたJava.Lang.NoSuchMethodError: No static method startActivity

場合によっては、Visual Studio で単なる警告として表示されるサポート パッケージの競合が実行時にこの例外としてアプリケーション クラッシュとして表示されます。 この場合、プロジェクトで参照されるすべてのサポート パッケージのバージョンが同じであることを確認する必要があります。 Azure Mobile Apps の NuGet パッケージには、Android プラットフォームに関して Xamarin.Android.Support.CustomTabs の依存関係があるため、プロジェクトで新しいサポート パッケージを使用する場合は、必要なバージョンを使用してこのパッケージを直接インストールし、競合を回避する必要があります。

iOS アプリに認証を追加する

このセクションでは、iOS アプリ プロジェクト内に IAuthenticate インターフェイスを実装する方法について説明します。 iOS デバイスをサポートしない場合、このセクションはスキップしてください。

  1. Visual Studio または Xamarin Studio で、iOS プロジェクトを右クリックし、 [スタートアップ プロジェクトに設定] をクリックします。

  2. F5 キーを押してデバッガーでプロジェクトを開始し、アプリの開始後に、状態コード 401 のハンドルされない例外 (許可されていません) が発生することを確認します。 401 応答は、バックエンドへのアクセスが承認済みのユーザーのみに制限されているために生成されます。

  3. iOS プロジェクトの AppDelegate.cs を開き、次の using ステートメントを追加します。

     ```csharp
     using Microsoft.WindowsAzure.MobileServices;
     using System.Threading.Tasks;
     ```
    
  4. 次のように、AppDelegate クラスを更新して IAuthenticate インターフェイスを実装します。

     ```csharp
     public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IAuthenticate
     ```
    
  5. 次のように、MobileServiceUser フィールドのほか、IAuthenticate インターフェイスに必要な Authenticate メソッドを追加して、AppDelegate クラスを更新します。

     ```csharp
     // Define an authenticated user.
     private MobileServiceUser user;
    
     public async Task<bool> Authenticate()
     {
         var success = false;
         var message = string.Empty;
         try
         {
             // Sign in with Facebook login using a server-managed flow.
             if (user == null)
             {
                 user = await TodoItemManager.DefaultManager.CurrentClient
                     .LoginAsync(UIApplication.SharedApplication.KeyWindow.RootViewController,
                     MobileServiceAuthenticationProvider.Facebook, "{url_scheme_of_your_app}");
                 if (user != null)
                 {
                     message = string.Format("You are now signed-in as {0}.", user.UserId);
                     success = true;
                 }
             }
         }
         catch (Exception ex)
         {
            message = ex.Message;
         }
    
         // Display the success or failure message.
         UIAlertController avAlert = UIAlertController.Create("Sign-in result", message, UIAlertControllerStyle.Alert);
         avAlert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
         UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(avAlert, true, null);
    
         return success;
     }
     ```
    

    Facebook 以外の ID プロバイダーを使用している場合、[MobileServiceAuthenticationProvider] には別の値を選択してください。

  6. 次のように OpenUrl メソッド オーバーロードを追加して、AppDelegate クラスを更新します。

     ```csharp
     public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
     {
         if (TodoItemManager.DefaultManager.CurrentClient.ResumeWithURL(app, url, options))
             return true;
         return base.OpenUrl(app, url, options);
     }
     ```
    
  7. LoadApplication() の呼び出しの前の FinishedLaunching メソッドに、次のコード行を追加します。

     ```csharp
     App.Init(this);
     ```
    

    このコードにより、アプリの読み込み前に Authenticator が初期化されるようになります。

  8. Info.plist を開き、 [URL Type] を追加します。 [Identifier] を任意の名前に、 [URL Schemes] をアプリの URL スキームに、 [Role] を [None] に設定します。

  9. アプリをリビルドして実行します。その後で、選択した認証プロバイダーを使用してサインインし、認証されたユーザーとしてデータにアクセスできることを確認します。

Windows 10 (Phone を含む) アプリ プロジェクトに認証を追加する

このセクションでは、Windows 10 アプリ プロジェクト内に IAuthenticate インターフェイスを実装する方法について説明します。 同じ手順をユニバーサル Windows プラットフォーム (UWP) プロジェクトにも適用できますが、UWP プロジェクトを使用します (相違点が注記されています)。 Windows デバイスをサポートしない場合、このセクションはスキップしてください。

  1. Visual Studio で、UWP プロジェクトを右クリックし、 [スタートアップ プロジェクトに設定] をクリックします。

  2. F5 キーを押してデバッガーでプロジェクトを開始し、アプリの開始後に、状態コード 401 のハンドルされない例外 (許可されていません) が発生することを確認します。 401 応答は、バックエンドへのアクセスが承認済みのユーザーのみに制限されているために発生します。

  3. Windows アプリ プロジェクトの MainPage.xaml.cs を開き、次の using ステートメントを追加します。

     ```csharp
     using Microsoft.WindowsAzure.MobileServices;
     using System.Threading.Tasks;
     using Windows.UI.Popups;
     using <your_Portable_Class_Library_namespace>;
     ```
    

    <your_Portable_Class_Library_namespace> を、ポータブル クラス ライブラリの名前空間に置き換えます。

  4. 次のように、MainPage クラスを更新して IAuthenticate インターフェイスを実装します。

     public sealed partial class MainPage : IAuthenticate
    
  5. 次のように、MobileServiceUser フィールドのほか、IAuthenticate インターフェイスに必要な Authenticate メソッドを追加して、MainPage クラスを更新します。

     ```csharp
     // Define an authenticated user.
     private MobileServiceUser user;
    
     public async Task<bool> Authenticate()
     {
         string message = string.Empty;
         var success = false;
    
         try
         {
             // Sign in with Facebook login using a server-managed flow.
             if (user == null)
             {
                 user = await TodoItemManager.DefaultManager.CurrentClient
                     .LoginAsync(MobileServiceAuthenticationProvider.Facebook, "{url_scheme_of_your_app}");
                 if (user != null)
                 {
                     success = true;
                     message = string.Format("You are now signed-in as {0}.", user.UserId);
                 }
             }
    
         }
         catch (Exception ex)
         {
             message = string.Format("Authentication Failed: {0}", ex.Message);
         }
    
         // Display the success or failure message.
         await new MessageDialog(message, "Sign-in result").ShowAsync();
    
         return success;
     }
     ```
    

    Facebook 以外の ID プロバイダーを使用している場合、 MobileServiceAuthenticationProviderには別の値を選択してください。

  6. LoadApplication() の呼び出しの前にある MainPage クラスのコンストラクター内に次のコード行を追加します。

     ```csharp
     // Initialize the authenticator before loading the app.
     <your_Portable_Class_Library_namespace>.App.Init(this);
     ```
    

    <your_Portable_Class_Library_namespace> を、ポータブル クラス ライブラリの名前空間に置き換えます。

  7. UWP を使用している場合は、以下の OnActivated メソッドのオーバーライドを App クラスに追加します。

     ```csharp
     protected override void OnActivated(IActivatedEventArgs args)
     {
        base.OnActivated(args);
    
         if (args.Kind == ActivationKind.Protocol)
         {
             ProtocolActivatedEventArgs protocolArgs = args as ProtocolActivatedEventArgs;
             MobileServiceClientExtensions.ResumeWithURL(TodoItemManager.DefaultManager.CurrentClient,protocolArgs.Uri);
         }
     }
     ```
    
  8. Package.appxmanifest を開き、 [プロトコル] 宣言を追加します。 [表示名] を任意の名前に設定し、 [名前] をアプリの URL スキームに設定します。

  9. アプリをリビルドして実行します。その後で、選択した認証プロバイダーを使用してサインインし、認証されたユーザーとしてデータにアクセスできることを確認します。

次のステップ

これで基本的な認証チュートリアルは完了しましたので、引き続き次のいずれかのチュートリアルのご利用を検討してください。

  • アプリへのプッシュ通知の追加

    アプリにプッシュ通知のサポートを追加して、Azure Notification Hubs を使ってプッシュ通知を送信するようにモバイル アプリ バックエンドを構成する方法について説明します。

  • アプリのオフライン同期の有効化

    モバイル アプリ バックエンドを使用してオフライン サポートをアプリに追加する方法について説明します。 オフライン同期を使用すると、エンド ユーザーはネットワークにアクセスできなくても、データの表示、追加、変更など、モバイル アプリケーションとやり取りできます。