🍎

【Flutter × Cognito】クライアントシークレットの利用で躓いたこと

2023/03/11に公開

使用するパケージ

amazon_cognito_identity_dart_2: ^3.2.0
https://pub.dev/packages/amazon_cognito_identity_dart_2

サマリ

  • CognitoUserPool クラス以外に、CognitoUser クラスにもクライアントシークレットを設定できる
  • resendConfirmationCode(),confirmRegistration()の処理を実行するときに CognitoUser オブジェクトにクライアントシークレットを設定する
  • もしかしたら他の処理でも CognitoUser オブジェクトにクライアントシークレットを設定しないといけないかも

躓いた所

Cognito を利用した認証フローを作成中、認証コードの再送処理を実装している際に
クライアントシークレットの設定で混乱した。

ErrorPattern

Pattern1:CognitoUser オブジェクトにクライアントシークレットを設定していない

CognitoUserPool オブジェクト側にのみクライアントシークレットを設定していて、CognitoUser オブジェクトにはクライアントシークレットを設定していない状態だと、resendConfirmationCode()を実行したときに怒られます

詳細

エラーメッセージ:
CognitoClientException{statusCode: 400, code: NotAuthorizedException, name: NotAuthorizedException, message: Client XXXXXXXXXXXXXXXXXXXXXXXXXX is configured for secret but secret was not received}

意訳:
あんたのとこに登録されている XXX のクライアントにはシークレットが設定されてるのに受け取れなかったんだけど!!

final CognitoUser cognitoUser = CognitoUser(
      email,
      cognitoUserPoolWithSecret,
    );

修正方法:
CognitoUser オブジェクト生成時にもクライアントシークレットを設定してあげる

final CognitoUser cognitoUser = CognitoUser(
      email,
      cognitoUserPoolWithoutSecret,
      clientSecret: cognitoClientSecret,
    );

final CognitoUser cognitoUser = CognitoUser(
      email,
      // CognitoUserPoolオブジェクトと重複してシークレットを設定してもOK
      cognitoUserPoolWithSecret,
      clientSecret: cognitoClientSecret,
    );

Pattern2:公式のドキュメント通りに実装する(ええぇ)

公式のサンプルプログラムに掲載されている型宣言に不適切な箇所があり、脳死でコピペして使ってると型が違うよと怒られます。

詳細

エラーメッセージ:
type '_Map<String, dynamic>' is not a subtype of type 'String'

意訳:
型が違うよ(Map<String, dynamic>は String に格納できないよ)

final String status;
try {
      // statusに代入しようとすると'flutter: type '_Map<String, dynamic>' is not a subtype of type 'String''のエラーが出る
      status = await cognitoUser.resendConfirmationCode();
    } catch (e) {
      if (context.mounted) {
        print(e);
        createSnackBar(context, 'エラーが発生しました。アプリを再起動してお試しください。 $e');
        return;
      }
    }

修正方法:
status の型宣言を dynamic にする
→resendConfirmationCode()の戻り値自体が dynamic

// ここ
final dynamic status;
try {
  status = await cognitoUser.resendConfirmationCode();
} catch (e) {
  print(e);
}

Discussion