開発環境

Flutter×Amplify環境でネイティブアプリの開発を行っており、認証にはCognitoを使用している。

やりたいこと

アプリの初回認証成功時に、DynamoBDのUsersテーブルにユーザー情報を保存したい。

以下の値を保存する

  • cognito_sub: Cognitoユーザープールの各ユーザに割り当てられるsubと呼ばれるID
  • email: 認証時に取得したメールアドレス ← 今回はここを保存したい
  • auth_type: 認証タイプ: Email, googleなど

処理の流れ

  1. ユーザーがemail/password方式、またはソーシャルプロバイダー(Googleなど)で認証を行う
  2. 認証結果がtrueの場合、Amplify.Auth.getCurrentUser()を呼び出してuserId(cognito_sub)を取得する
  3. 2で取得したuserIdを元に、Usersテーブルにユーザーが存在するかをチェックする
  4. ユーザーが存在しない場合、データベースに以下の値を保存する
    • cognito_sub: Cognitoユーザープールの各ユーザに割り当てられるsubと呼ばれるID
    • email: 認証時に取得したメールアドレス ←今回はここを保存したい
    • auth_type: 認証タイプ: Email, googleなど

問題

Amplifyに用意されているAmplify.Auth.getCurrentUser()で現在のユーザー情報を取得できるのだが、レスポンスは以下のようになっていた。フィールドにemailが含まれていないため、データベースに登録処理を行う際にデータが不足する状態となる。

{
  "userId": "xxxx",
  "username": "xxxxx",
  "signInDetails": {
    "signInType": "hostedUi",
    "provider": {
      "name": "google",
      "identityPoolProvider": null
    }
  }

解決策

Amplify.Auth.fetchUserAttributes()というメソッドを使用する。

公式ドキュメント: Fetch the current user’s attributes

以下のようにメソッドを用意してあげて、ウィジェット側から呼び出すことでデータを取得できる。

/*
  Cognitoのユーザープールにアクセスし、追加情報を取得する
*/
Future<List<AuthUserAttribute>> getCurrentUserAttributes() async {
  final userAttributes = await Amplify.Auth.fetchUserAttributes();
  return userAttributes;
}

ちなみに、上記関数の戻り値 List<AuthUserAttribute>は以下のようになっている。

[{
  "userAttributeKey": "sub",
  "value": "xxxx"
}, AuthUserAttribute {
  "userAttributeKey": "identities",
  "value": "[{\"userId\":\"xxxx\",\"providerName\":\"Google\".....}]"
}, AuthUserAttribute {
  "userAttributeKey": "email_verified",
  "value": "false"
}, AuthUserAttribute {
  "userAttributeKey": "email", ←emailのデータが返却されている
  "value": "example@example.com"
}]

あとはレスポンスを受け取ったウィジェット側で配列処理を行えばemailの値を取得できる。

// Cognitoユーザープールの詳細情報を取得する
final loginUserAttributes = await getCurrentUserAttributes();
final emailAttribute = loginUserAttributes.firstWhere((attribute) =>
  attribute.userAttributeKey == AuthUserAttributeKey.email).value;
カテゴリー: awsFlutter