この記事の目的
一言でいえば、先に山に入った者の務めをなるべく果たすということです。
Flutterを用いてフロントエンドを作り、認証機能にAWS Cognitoを使いたいと思っていました。
Flutter自体の情報が少ないので、まずは、AWSの公式のチュートリアルをやるのが良いと思いやってみました。
チュートリアルは所要時間70分と謳われていますが、私が実際にやったら、もっと(たぶん数時間+調査時間)が掛かりました。
AWS社への確認まではしていませんが、明らかに誤記と思われるようなところもあるので、 先に山に入った者の務め として、ハマりどころを記しておこうと思いました。
チュートリアルについての補足
現時点では、このチュートリアルは日本語版と英語版とでは内容が異なるようです。
日本語版は、画像管理のアプリであるのに対して、英語版はTodoアプリになっています。
また、日本語版チュートリアルは、モジュール 1: Flutter アプリを作成してデプロイする〜モジュール 5: 分析カテゴリを追加するで構成されていますが、現時点では、私は、モジュール 3: 認証を追加するまでしか実施していません。(モジュール 4以降は、当面実施する予定はありません…)
以下、この記事は、日本語版チュートリアルを対象に記載していきます。
手元の環境
- OS Ubuntu20.04
- IDE Android Studio 4.2
- Flutter 2.0.4
Flutterを2系に上げた関係で、非推奨になっているWidgetもありますが、今回の検証の趣旨ではないため、放置しています。
作業後のソースコード
以下のRepositoryに上げてあります。(ご参考までに)
https://github.com/akiraabe/aws_flutter
モジュール 1: Flutter アプリを作成してデプロイする
ここでのポイント
特にありません。チュートリアルに準じてコーディングしていきます。
モジュール 2: Amplify を初期化する
ここでのポイント
まずは、「プロジェクトに依存関係を追加する」のステップで、チュートリアルでは、amplify_coreを使うように記載があります。
... # path:
amplify_core: '<1.0.0'
... # dev_dependencies
しかしながら、2020/8にamplify_flutterがリリースされているので、そちらを使う必要があるようです。
pubspec.yamlは、のdependenciesは以下のようになります。
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
camera:
path_provider:
path:
# amplify_core: '<1.0.0'
amplify_flutter: '<1.0.0'
amplify_auth_cognito: '<1.0.0'
次に、アプリケーションに統合するのステップでは、
チュートリアルでは、Amplifyクラスをインスタンス化して使うように記載があります。
しかし、実際にはインスタンス化するのではなく、Amplifyのstaticメソッドを直接使うようです。
// Amplifyの設定関数のみ記載
void _configureAmplify() async {
Amplify.addPlugins([AmplifyAuthCognito()]);
try {
await Amplify.configure(amplifyconfig);
print('Successfully configured Amplify 🎉');
} catch (e) {
print('Could not configure Amplify');
}
}
モジュール 3: 認証を追加する
機能を実装するのステップで、チュートリアルでは、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}');
}
}
しかし、正しくは、後段のverifyCodeと合わせて考えると、以下のようなコードが正しいと考えられます。
上記のチュートリアルの// 3のコードブロックの結果で、// 4のif文がTrueになり、loginWithCredentialsを実行します。しかし、この時点ではverifyCodeが完了していませんので、エラーとなり永遠にverifyCode画面に遷移出来ません。
void signUpWithCredentials(SignUpCredentials credentials) async {
try {
final userAttributes = {'email': credentials.email};
final result = await Amplify.Auth.signUp(
username: credentials.username,
password: credentials.password,
options: CognitoSignUpOptions(userAttributes: userAttributes));
print('AuthService#signUpWithCredentials is*NOT*SignUpComplete');
this._credentials = credentials;
final state = AuthState(authFlowStatus: AuthFlowStatus.verification);
authStateController.add(state);
} on AuthException catch (authError) {
print('Failed to sign up - ${authError.message}');
}
}
void verifyCode(String verificationCode) async {
try {
final result = await Amplify.Auth.confirmSignUp(
username: _credentials.username, confirmationCode: verificationCode);
if (result.isSignUpComplete) {
loginWithCredentials(_credentials);
} else {
// Follow more steps
}
} on AuthException catch (e) {
print('Could not verify code - ${e.message}');
}
}
まとめ
Amplifyを用いると他のAWSサービスとの統合には便利ですが、当然ながら、かなりAWSに依存する形になります。
AWSに依存した部分のテスタビリティーなども少々心配です。
当面は、Amplifyを使わずに、個別にAWSのサービスと連携する方向で様子見しようかなぁと思っています。