Flutter Amplifyでアプリ(iOS)から自身の属性情報を取得しようとするとエラーとなる際の確認ポイント

2023.03.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 Delivery部の若槻です。

以前のエントリで、Flutter(iOS)アプリでAmplify SDKを使ってAmazon Cognitoの認証をする実装をしました。

この時にAmplifyのセッションを使って自身の属性情報を取得しようとした際にハマったので対処について共有します。

事象

Flutter Amplifyを使って自身の属性情報を取得したい場合は、ドキュメントを見るとfetchCurrentUserAttributes()を使えば良さそう。

Future<void> fetchCurrentUserAttributes() async {
  try {
    final result = await Amplify.Auth.fetchUserAttributes();
    for (final element in result) {
      print('key: ${element.userAttributeKey}; value: ${element.value}');
    }
  } on AuthException catch (e) {
    print(e.message);
  }
}

試してみます。環境は以前のエントリで作成したアプリを流用しています。

import 'package:flutter/material.dart';
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_flutter/amplify_flutter.dart';

import 'amplifyconfiguration.dart';

class AuthProvider extends ChangeNotifier {
  bool signedIn = false;

  Future<void> _configure() async {
    if (!Amplify.isConfigured) {
      await Amplify.addPlugin(AmplifyAuthCognito());
      await Amplify.configure(amplifyconfig);
    }

    try {
      var currentUser = await Amplify.Auth.getCurrentUser();
      print(currentUser.userId);
      print(currentUser.username);

      var userAttributes = await Amplify.Auth.fetchUserAttributes();
      for (final element in userAttributes) {
        print('key: ${element.userAttributeKey}; value: ${element.value}');
      }

      signedIn = true;
    } on AuthException catch (e) {
      print(e);
      signedIn = false;
    }

    notifyListeners();
  }
}

しかし実行すると例外がスローされてしまいます。getCurrentUser()までは実行できていますが、fetchUserAttributes()でエラーが発生してしまいます。

flutter: 5ed9abb6-f549-4d8c-9288-c39012b8f4bd
flutter: 5ed9abb6-f549-4d8c-9288-c39012b8f4bd
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: NotAuthorizedException(message: Access Token does not have required scopes, recoverySuggestion: Check whether the given values are correct and the user is authorized to perform the operation., underlyingException: null)
#0      AmplifyAuthCognitoMethodChannel.fetchUserAttributes (package:amplify_auth_cognito/method_channel_auth_cognito.dart:297:7)
<asynchronous suspension>
#1      AuthProvider._configure (package:flutter_sample_app/auth_provider.dart:20:26)
<asynchronous suspension>

原因、解決

アクセストークンのスコープにaws.cognito.signin.user.adminが含まれていないことが原因でした。

Amazon Cognitoの一部のAPIはaws.cognito.signin.user.adminスコープを付与する必要があるようです。

aws.cognito.signin.user.admin スコープは、UpdateUserAttributes および VerifyUserAttribute などのアクセストークンを必要とする Amazon Cognito ユーザープール API 操作へのアクセス権を付与します。

Amplify.configure()で読み込みコンフィグファイルのスコープにaws.cognito.signin.user.adminを追加します。

const amplifyconfig = '''{
  "auth": {
    "plugins": {
      "awsCognitoAuthPlugin": {
        "CognitoUserPool": {
          "Default": {
            "PoolId": "<COGNITO USER POOL ID>",
            "AppClientId": "<COGNITO USER POOL APP CLIENT ID>",
            "Region": "<REGION>"
          }
        },
        "Auth": {
          "Default": {
            "OAuth": {
              "WebDomain": "<COGNITO WEB DOMAIN>",
              "AppClientId": "<COGNITO USER POOL APP CLIENT ID>",
              "SignInRedirectURI": "<myapp>://",
              "SignOutRedirectURI": "<myapp>://",
              "Scopes": [
                "email",
                "openid",
                "profile",
                "aws.cognito.signin.user.admin"
              ]
            }
          }
        }
      }
    }
  }
}''';

また今回は認証画面にHosted UIを使っていたため、User pool clientのHosted UIの設定でもaws.cognito.signin.user.adminを追加します。(Hosted UIの設定で追加せず、コンフィグファイル側にのみ追加した場合はサインインすらできない状態となります。)

スコープ修正後に再度実行すると、emailおよびemail_verifiedなどの属性情報が取得できました。

Performing hot restart...                                               
Restarted application in 287ms.
flutter: 5ed9abb6-f549-4d8c-9288-c39012b8f4bd
flutter: 5ed9abb6-f549-4d8c-9288-c39012b8f4bd
flutter: key: sub; value: 5ed9abb6-f549-4d8c-9288-c39012b8f4bd
flutter: key: email; value: hoge@example.com
flutter: key: email_verified; value: true

おわりに

Flutter Amplifyでアプリ(iOS)から自身の属性情報を取得しようとするとエラーとなる際の確認ポイントについてでした。

なんで自分の情報を取得できないのか最初は混乱しましたが、fetchCurrentUserAttributes()も管理権限が必要なAPIの一種であるという観点が抜けていました。

参考

以上