AWS の開始方法
Flutter アプリケーションを構築する
AWS Amplify を使用してシンプルな Flutter アプリケーションを作成する
モジュール 3: 認証を追加する
このモジュールでは、Amplify CLI とライブラリを使用して、認証を設定し、アプリに追加します。
はじめに
アプリに追加する最初の Amplify カテゴリは、認証です。Amplify は、内部で Amazon Cognito を利用してユーザープールと ID プールを管理します。
このモジュールでは、ユーザーのサインアップ、確認、ログイン、サインアウトの方法を学習します。わずか数行のコードで、各画面の機能を実装できます。
学習内容
- 認証カテゴリの設定
- ユーザーのサインアップ
- ユーザー E メールの検証
- 認証されたユーザーのログイン
- 認証されたユーザーのサインアウト
主要な概念
認証 – 認証は、ユーザーを検証および管理するプロセスであり、ユーザーがアプリのリソースとやり取りできるようにするために行います。
所要時間
10 分
使用するサービス
実装
-
認証サービスを作成する
Amplify プロジェクトに認証サービスを追加するには、ターミナルからプロジェクトのあるルートディレクトリでこのコマンドを実行する必要があります。
amplify add auth
認証サービスの設定に関するいくつかの質問が表示されます。Enter キーを押して各質問のデフォルトの値を選択します。結果の出力は以下のようになります。
➜ photo_gallery git:(master) ✗ amplify add auth Using service: Cognito, provided by: awscloudformation The current configured provider is Amazon Cognito. Do you want to use the default authentication and security configuration? Default configuration Warning: you will not be able to edit these selections. How do you want users to be able to sign in? Username Do you want to configure advanced settings? No, I am done.
認証のリソースが完全に設定されると、次のような出力が表示されます。
Successfully added resource photogallery42b5391b locally
上記の出力のとおり、リソースはローカルにのみ追加されています。ローカルに実施した変更でバックエンドを設定するには、以下のコマンドを実行する必要があります。
amplify push
ローカルの変更をバックエンドに送信する前に、Amplify CLI は以下の変更をプッシュするか確認するためにステータスレポートを表示します。
Current Environment: dev | Category | Resource name | Operation | Provider plugin | | -------- | -------------------- | --------- | ----------------- | | Auth | photogallery42b5391b | Create | awscloudformation | ? Are you sure you want to continue? Yes
ローカルの変更をバックエンドに送信する前に、Amplify CLI は以下の変更をプッシュするか確認するためにステータスレポートを表示します。
✔ All resources are updated in the cloud
また、/lib/amplifyconfiguration.dart ファイルを表示して認証値を調査することで認証リソースが適切に設定されているか検証することもできます。
-
依存関係をインストールする
Visual Studio Code に戻り、pubspec.yaml を開いて次の依存関係を追加します。
... # amplify_core: '<1.0.0' amplify_auth_cognito: '<1.0.0' ... # dev_dependencies:
このファイルを保存して、Visual Studio Code に Amplify Auth Cognito プラグインをインストールさせます。保存時に依存関係がインストールされない場合は、ターミナルから「$ flutter pub get」を実行することもできます。
次のような出力が得られるはずです。
exit code 0
-
プラグインを設定する
認証の依存関係がインストールされたので、main.dart ファイルの _MyAppState._configureAmplify() の Amplify インスタンスに認証プラグインを追加できます。
... // void _configureAmplify() async { _amplify.addPlugin(authPlugins: [AmplifyAuthCognito()]); ... // try {
アプリを実行し、ログに成功のメッセージが引き続き表示されるか確認します。
成功のメッセージが引き続き表示される場合は、認証フローの機能を実装開始できます。成功のメッセージが表示されない場合は、上記のステップを繰り返すか、または「Amplify を初期化する」モジュールに移動し、そこですべてのステップを正しく完了したかを確かめます。
-
機能を実装する
先の「Flutter アプリを作成する」モジュールでは、呼び出された関数に基づいて AuthState の更新を処理するよう AuthService を実装しました。今度は、ユーザーが各プロセスを正常に完了したときにのみ状態を更新するように、それぞれの関数を更新する必要があります。
auth_service.dart で AuthService に AuthCredentials プロパティを追加します。
... // final authStateController = StreamController<AuthState>(); AuthCredentials _credentials; ... // void showSignUp() {
このプロパティはサインアッププロセス中、メモリに SignUpCredentials を保持するのに使用されます。これによりユーザーは E メールアドレスの検証後すぐにログインした状態になります。このプロパティを追加しなかった場合、ユーザーはログイン画面に移動して手動でログインすることになります。
signUpWithCredentials を次のとおり更新します。
// 1 void signUpWithCredentials(SignUpCredentials credentials) async { try { // 2 final userAttributes = {'email': credentials.email}; // 3 final result = await Amplify.Auth.signUp( username: credentials.username, password: credentials.password, options: CognitoSignUpOptions(userAttributes: userAttributes)); // 4 if (result.isSignUpComplete) { loginWithCredentials(credentials); } else { // 5 this._credentials = credentials; // 6 final state = AuthState(authFlowStatus: AuthFlowStatus.verification); authStateController.add(state); } // 7 } on AuthError catch (authError) { print('Failed to sign up - ${authError.cause}'); } }
- この関数はサインアッププロセス中、await を使用するため、async に更新する必要があります。
- サインアップの一環としてユーザーの E メールを渡すため userAttributes を作成する必要があります。
- Cognito にサインアップするための E メールを含むユーザー属性と一緒に、認証情報により提供されたユーザー名とパスワードを渡します。これは非同期のプロセスであるため、await キーワードを使用する必要があります。
- 結果が正常に返された場合、次のステップは E メールを検証することです。理由にかかわらずサインアッププロセスが完了した場合は、単純にユーザーをアプリにログインさせます。
- ユーザーが E メールを検証する際に、_credentials に SignUpCredentials を保存します。
- 以前に実施した際と同様に AuthState を verification に更新します。ただし、サインインが正常に行われ、かつサインアッププロセスが完了していないことが確定した後に限ります。
- サインアップが何らかの理由で失敗した場合、ログにエラーを出力します。
verifyCode を次のように更新します。
// 1 void verifyCode(String verificationCode) async { try { // 2 final result = await Amplify.Auth.confirmSignUp( username: _credentials.username, confirmationCode: verificationCode); // 3 if (result.isSignUpComplete) { loginWithCredentials(_credentials); } else { // 4 // Follow more steps } } on AuthError catch (authError) { print('Could not verify code - ${authError.cause}'); } }
- signUpWithCredentials で実施したように、verifyCode も非同期関数としてマークする必要があります。
- _credentials を使用して、ユーザー名を指定し、VerificationPage から入力されたコードを confirmSignUp に渡します。
- confirmSignUp からの結果がサインアップの完了を明示している場合、サインアップ中に作成された _credentials でユーザーのログインを試行します。ユーザーは引き続き Amplify にログインする必要があるため、この成功のケースではこれ以上 AppState を更新しないことに注意します。
- サインアップが完了しない場合、この結果を利用して、サインアップ完了のために必要な追加の手順を探します。これは、このアプリでは発生しないはずです。
認証フローのサインアップ部分を実装しましたが、今度はログイン部分を更新する必要があります。loginWithCredentials を以下のように更新します。
// 1 void loginWithCredentials(AuthCredentials credentials) async { try { // 2 final result = await Amplify.Auth.signIn( username: credentials.username, password: credentials.password); // 3 if (result.isSignedIn) { final state = AuthState(authFlowStatus: AuthFlowStatus.session); authStateController.add(state); } else { // 4 print('User could not be signed in'); } } on AuthError catch (authError) { print('Could not login - ${authError.cause}'); } }
- loginWithCredentials は AuthCredentials をパラメータとして受け取るため、LoginCredentials または SignUpCredentials が渡されると動作します。
- AuthCredentials のユーザー名とパスワードを Amplify のサインインメソッドに渡し、結果を待ちます。
- サインインが成功し、かつユーザーが現在サインインしていることを結果の isSignedIn プロパティが確認したら、状態を session に更新します。
- このアプリではこの状態に到達しないはずです。ユーザーが間違った認証情報を入力するか、またはその他のエラーが発生した場合は、catch ブロックを使用します。
今度は logOut メソッドを更新します。
void logOut() async { try { // 1 await Amplify.Auth.signOut(); // 2 showLogin(); } on AuthError catch (authError) { print('Could not log out - ${authError.cause}'); } }
- オプションを何も渡さずに Auth.signOut() を呼び出すと、ユーザーをすべてのデバイス上からサインアウトするのではなく、このデバイス上のユーザーのみをサインアウトします。
- サインアウトが成功した場合、状態を更新する showLogin() メソッドを再利用してユーザーをログイン画面に戻すことができます。
最後に、ユーザーが前回のセッション中にログイン済みの状態でアプリを閉じた場合に、自動的にユーザーをログインした状態にできるようにする必要があります。AuthService にこの最後の関数を追加します。
void checkAuthStatus() async { try { await Amplify.Auth.fetchAuthSession(); final state = AuthState(authFlowStatus: AuthFlowStatus.session); authStateController.add(state); } catch (_) { final state = AuthState(authFlowStatus: AuthFlowStatus.login); authStateController.add(state); } }
checkAuthStatus は現在の AuthSession の取得を試行します。これが成功すると、ユーザーはサインインします。この取得が失敗した場合、ユーザーはログインできず、LoginPage を提示されるはずです。
今、_MyAppState の initState メソッド内の showLogin を呼び出しています。これを checkAuthStatus に変更しましょう。
... // _configureAmplify(); _authService.checkAuthStatus(); ... // initState closing }
これらが唯一、既存の認証フローを補完するのに必要な修正です。アプリを構築して実行すれば、サインアップ、E メール確認、サインアウト、再度のサインインが可能になるはずです。