AWS の開始方法

Android アプリケーションをビルドする

AWS Amplify を使用してシンプルな Android アプリケーションを作成する

モジュール 3: 認証を追加する

このモジュールでは、Amplify CLI とライブラリを使用して、認証を設定し、アプリに追加します。

はじめに

次に追加する機能はユーザー認証です。このモジュールでは、マネージド型のユーザー ID プロバイダーである Amazon Cognito を利用して、Amplify CLI とライブラリでユーザーを認証する方法を学びます。

また、Cognito でホストされるユーザーインターフェイスを使用してユーザー認証フロー全体を表示する方法を学び、ユーザーが数行のコードでサインアップ、サインイン、パスワードのリセットを行えるようにします。

「ホストされたユーザーインタフェイス」を使用するということは、アプリケーションで Cognito のウェブページを利用して、サインインとサインアップのユーザーインタフェイスフローを行うということです。アプリケーションのユーザーは、Cognito でホストされるウェブページにリダイレクトされ、サインイン後にアプリにリダイレクトされます。当然、Cognito と Amplify もネイティブ UI をサポートします。カスタム認証 UI の詳細については、こちらのワークショップ手順を参照してください。

学習内容

  • 認証サービスを作成してデプロイする
  • Cognito Hosted UI 認証を含めるように Android アプリケーションを設定する

主要な概念

Amplify ライブラリ – Amplify ライブラリにより、ウェブまたはモバイルアプリケーションから AWS のサービスを操作できます。

認証 – ソフトウェアでは、認証は、認証サービスまたは API を使用してユーザーの ID を確認および管理するプロセスです。

 所要時間

10 分

 使用するサービス

実装

  • 認証サービスを作成する

    認証サービスを作成するには、ターミナルを開いてこのコマンドを実行します

    amplify add auth
    
    ? Do you want to use the default authentication and security configuration? Select Default configuration with Social Provider and press enter
    ? How do you want users to be able to sign in? Select the default Username and press enter
    ? Do you want to configure advanced settings? Select the default No, I am done and press enter
    ? What domain name prefix do you want to use? Select the default and press enter
    Enter your redirect signin URI: type gettingstarted:// and press enter
    ? Do you want to add another redirect signin URI? Select the default N and press enter
    Enter your redirect signout URI: type gettingstarted:// and press enter
    ? Do you want to add another redirect signout URI? Select the default N and press enter
    ? Select the social providers you want to configure for your user pool: do not select any provider and press enter

    設定が成功すると、次のメッセージが表示されます (リソースの正確な名前は異なります)。

    Successfully added resource androidgettingstartedfc5a4717 locally
  • 認証サービスをデプロイする

    認証サービスがローカルで設定されたので、認証サービスをクラウドにデプロイできます。ターミナルのプロジェクトディレクトリでこのコマンドを実行します

    amplify push
    
    # press Y when asked to continue

    しばらくすると、下記のメッセージが表示されます。

    ✔ All resources are updated in the cloud
    
    Hosted UI Endpoint: https://androidgettingstarted-dev.auth.eu-central-1.amazoncognito.com/
    Test Your Hosted UI Endpoint: https://androidgettingstarted-dev.auth.eu-central-1.amazoncognito.com/login?response_type=code&client_id=1234567890&redirect_uri=gettingstarted://
  • Amplify 認証ライブラリをプロジェクトに追加する

    コードに進む前に、Android Studio に戻って、下記の依存関係をモジュールの build.gradle および以前に追加したさまざまな `amplifyframework` implementation に追加して、[Sync Now] が表示されたらクリックします。

    dependencies {
        ...
        // Amplify core dependency
        implementation 'com.amplifyframework:core:1.4.0'
        implementation 'com.amplifyframework:aws-auth-cognito:1.4.0'
    }
  • Amplify 認証ライブラリを実行時に設定する

    Android Studio に戻り、Backend.kt ファイルを開きます。バックエンドクラスで、前のセクション (initialize() メソッド) で追加した Amplify 初期化コードに行を追加します

    コードブロックが完成すると、下記のようになります。

    // inside Backend class
    fun initialize(applicationContext: Context) : Backend {
        try {
            Amplify.addPlugin(AWSCognitoAuthPlugin())
            Amplify.configure(applicationContext)
    
            Log.i(TAG, "Initialized Amplify")
        } catch (e: AmplifyException) {
            Log.e(TAG, "Could not initialize Amplify", e)
        }
        return this
    }

    必ずインポートステートメントを追加します。Android Studio では自動で追加されます (Mac ではコードエディタが検出したエラーごとに、Alt + Enter を押します)。

    前のステップと同様に、不足しているクラス定義ごとに求められる import ステートメントを追加します (赤い文字の上で Alt + Enter)。

    すべてが想定どおりに動作することを検証するには、プロジェクトをビルドします。[Build (構築)] メニューをクリックして、[Make Project (プロジェクトの作成)] を選択します。Mac の場合は、⌘F9 を押します。操作エラーがないようにします。

  • 認証を実行時にトリガーする

    残りのコードを変更すると、ユーザーのステータスを追跡できます (サインインの有無)。また、ユーザーがロックアイコンをクリックすると、SignIn/SignUp のユーザーインターフェイスをトリガーします。

    a.signIn および signOut メソッドを追加する
    バックエンドクラスの任意の場所に下記の 4 つのメソッドを追加します。
    private fun updateUserData(withSignedInStatus : Boolean) {
        UserData.setSignedIn(withSignedInStatus)
    }
    
    fun signOut() {
        Log.i(TAG, "Initiate Signout Sequence")
    
        Amplify.Auth.signOut(
            { Log.i(TAG, "Signed out!") },
            { error -> Log.e(TAG, error.toString()) }
        )
    }
    
    fun signIn(callingActivity: Activity) {
        Log.i(TAG, "Initiate Signin Sequence")
    
        Amplify.Auth.signInWithWebUI(
            callingActivity,
            { result: AuthSignInResult ->  Log.i(TAG, result.toString()) },
            { error: AuthException -> Log.e(TAG, error.toString()) }
        )
    }

    次に、不足しているクラス定義ごとに求められる import ステートメントを追加します (赤い文字の上で Alt + Enter)。選択肢として複数のクラスがあるときは、下記のスクリーンショットのとおり、必ず Amplify パッケージから選択します。

    AndroidAppTutorial_Modiule3_Image1

    これらのメソッドから UserData.isSignedIn フラグは更新しません。これは、次のセクションで実施します。

    b.認証ハブのリスナーを追加する

    認証ステータスの変更を追跡するには、Amplify によって送信される認証イベントにサブスクライブするためのコードを追加します。ハブは Backend.initialize() メソッドで初期化します。

    認証イベントを受信したら、updateUserData() メソッドを呼び出します。このメソッドによって UserData オブジェクトの同期が維持されます。UserData.isSignedIn プロパティの LiveData<Boolean> は、値が変わると、このプロパティにサブスクライブされたオブザーバーに通知されることを意味します。このメカニズムは、ユーザーインターフェイスの自動リフレッシュに使用します。詳細は、Android ドキュメントの LiveData に関するセクションを参照してください。

    また、アプリケーションの起動時に以前の認証ステータスを確認するコードも追加します。アプリケーションは起動すると、Cognito セッションが既に存在するかどうかを確認し、それに応じて UserData を更新します。

    Backend.initialize() で、try/catch ブロックの後で、なおかつ return ステートメントの前に、以下のコードを追加します。

    // in Backend.initialize() function, after the try/catch block but before the return statement 
    
    Log.i(TAG, "registering hub event")
    
    // listen to auth event
    Amplify.Hub.subscribe(HubChannel.AUTH) { hubEvent: HubEvent<*> ->
    
        when (hubEvent.name) {
            InitializationStatus.SUCCEEDED.toString() -> {
                Log.i(TAG, "Amplify successfully initialized")
            }
            InitializationStatus.FAILED.toString() -> {
                Log.i(TAG, "Amplify initialization failed")
            }
            else -> {
                when (AuthChannelEventName.valueOf(hubEvent.name)) {
                    AuthChannelEventName.SIGNED_IN -> {
                        updateUserData(true)
                        Log.i(TAG, "HUB : SIGNED_IN")
                    }
                    AuthChannelEventName.SIGNED_OUT -> {
                        updateUserData(false)
                        Log.i(TAG, "HUB : SIGNED_OUT")
                    }
                    else -> Log.i(TAG, """HUB EVENT:${hubEvent.name}""")
                }
            }
        }
    }
    
    Log.i(TAG, "retrieving session status")
    
    // is user already authenticated (from a previous execution) ?
    Amplify.Auth.fetchAuthSession(
        { result ->
            Log.i(TAG, result.toString())
            val cognitoAuthSession = result as AWSCognitoAuthSession
            // update UI
            this.updateUserData(cognitoAuthSession.isSignedIn)
            when (cognitoAuthSession.identityId.type) {
                AuthSessionResult.Type.SUCCESS ->  Log.i(TAG, "IdentityId: " + cognitoAuthSession.identityId.value)
                AuthSessionResult.Type.FAILURE -> Log.i(TAG, "IdentityId not present because: " + cognitoAuthSession.identityId.error.toString())
            }
        },
        { error -> Log.i(TAG, error.toString()) }
    )

    すべてが想定どおりに動作することを検証するには、プロジェクトをビルドします。[Build (構築)] メニューをクリックして、[Make Project (プロジェクトの作成)] を選択します。Mac の場合は、⌘F9 を押します。操作エラーがないようにします。

    c.ユーザーインターフェイスコードを更新する

    コードの最後の変更はユーザーインターフェイスに関連しています。メインアクティビティに FloatingActionButton を追加します。

    res/layout で activity_main.xml を開き、既存の FloatingActionButton を以下に置き換えます。

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fabAuth"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_baseline_lock"
        app:fabCustomSize="60dp"
        app:fabSize="auto"
        />

    res/drawable にロックアイコンを追加します。[drawable] を右クリックし、[New (新規)] を選択し、次に [Vector Asset (ベクターアセット)] を選択します。clipart から [Lock] アイコンを選択して、名前として ic_baseline_lock (_24 は不要) と入力し、Clip Art から閉じたロックアイコンを選択します。[Next (次へ)]、[Finish (終了)] の順にクリックします。

    同じ手順を、開いたロックアイコンで繰り返します。

    AndroidAppTutorial_Modiule3_Image2
    AndroidAppTutorial_Modiule3_Image3

    この結果、drawable ディレクトリには下記のファイルがあるはずです。

    AndroidAppTutorial_Modiule3_Image4

    新しく作成されたボタンをコード内でリンクさせます。java/com.example.androidgettingstarted/ で MainActivity.kt を開いて、以下のコードを追加します。

    // anywhere in the MainActivity class
    private fun setupAuthButton(userData: UserData) {
    
        // register a click listener
        fabAuth.setOnClickListener { view ->
    
            val authButton = view as FloatingActionButton
    
            if (userData.isSignedIn.value!!) {
                authButton.setImageResource(R.drawable.ic_baseline_lock_open)
                Backend.signOut()
            } else {
                authButton.setImageResource(R.drawable.ic_baseline_lock_open)
                Backend.signIn(this)
            }
        }
    }

    引き続き MainActivity で、onCreate() メソッドの末尾に以下のコードを追加します

    setupAuthButton(UserData)
    
    UserData.isSignedIn.observe(this, Observer<Boolean> { isSignedUp ->
        // update UI
        Log.i(TAG, "isSignedIn changed : $isSignedUp")
    
        if (isSignedUp) {
            fabAuth.setImageResource(R.drawable.ic_baseline_lock_open)
        } else {
            fabAuth.setImageResource(R.drawable.ic_baseline_lock)
        }
    })

    上記のコードによって、Userdata.isSignedIn の値にオブザーバーが登録されます。isSignedIn の値が変わると、クロージャが呼び出されます。ここでは、ロックアイコンだけを変更し、ユーザーが認証されたら開いて、ユーザーにセッションがない場合には閉じるようにします。

    すべてが想定どおりに動作することを検証するには、プロジェクトをビルドします。[Build (構築)] メニューをクリックして、[Make Project (プロジェクトの作成)] を選択します。Mac の場合は、⌘F9 を押します。操作エラーがないようにします。

    d.AndroidManifest.xml と MainActivity を更新する

    最後に、Cognito でホストされるユーザーインターフェイスによって提供されるウェブ認証シーケンスの最後でアプリを起動する必要があります。マニフェストファイルに新しいアクティビティを追加します。gettingstarted URI スキームが受信されると、アクティビティが呼び出されます。

    Android Studio では、manifest の直下で、AndroidManifest.xml を開き、アプリケーションエレメント内に下記のアクティビティを追加します。

        <activity
    android:name="com.amazonaws.mobileconnectors.cognitoauth.activities.CustomTabsRedirectActivity">
            <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="gettingstarted" />
            </intent-filter>
        </activity>
    

    java/com/example.androidgettingstarted の直下で、MainActivity.kt を開き、下記のコードをクラスの任意の場所に追加します。

    // MainActivity.kt
    // receive the web redirect after authentication
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        Backend.handleWebUISignInResponse(requestCode, resultCode, data)
    }

    java/com/example.androidgettingstarted の直下で、Backend.kt を開き、下記のコードをクラスの任意の場所に追加します。

    // Backend.kt
    // pass the data from web redirect to Amplify libs 
    fun handleWebUISignInResponse(requestCode: Int, resultCode: Int, data: Intent?) {
        Log.d(TAG, "received requestCode : $requestCode and resultCode : $resultCode")
        if (requestCode == AWSCognitoAuthPlugin.WEB_UI_SIGN_IN_ACTIVITY_CODE) {
            Amplify.Auth.handleWebUISignInResponse(data)
        }
    }

    e.ビルドとテスト

    すべてが想定どおりに動作することを検証するには、プロジェクトをビルドして実行します。ツールバーの [Run (実行)] アイコン ▶️ をクリックするか、または「^ R」と入力します。操作エラーがないようにします。アプリケーションが起動すると、画面右下に閉じたロックフローティングボタンが表示されます。

    サインアップの全体的な流れは下記のとおりです。

    AndroidAppTutorial_Modiule3_Image5
    AndroidAppTutorial_Modiule3_Image6
    AndroidAppTutorial_Modiule3_Image7
    AndroidAppTutorial_Modiule3_Image8
    AndroidAppTutorial_Modiule3_Image9

まとめ

これで、数行のコードでユーザー認証がアプリに追加されました。 次のモジュールでは、アプリに API を追加します。

このモジュールは役に立ちましたか?

ありがとうございます
このチュートリアルで良かった点をお聞かせください。
閉じる
ご期待に添えず申し訳ありません
古い説明、わかりにくい説明、間違った説明はございませんでしたか? このチュートリアルの改善のために、ぜひフィードバックをお寄せください。
閉じる

GraphQL API とデータベースを追加する