この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
CX事業本部デリバリー部の平内(SIN)です。
Flutterでの利用も提供されている、Amplify UI Componentsを使用すると、Cognitoと組み合わせて、ユーザーログインが簡単に準備できます。 なお、Amplify UI Componentsは、MFAにも対応しているため、Cognito側で設定を有効にするだけで、特に実装を追加する必要はありません。
今回は、Amplify UI Componentsを使用して、MFA対応の認証付きアプリを作成してみました。 ログイン時、及び、パスワードを忘れた場合(パスワード変更時)に、MFA(SMSに送られた検証コードの入力)が必要になります。
最初に、作成したアプリが動作している様子です。
ログイン時は、ユーザー名及び、パスワードに加えて、SMSに送られた検証コードの入力が必要です。 なお、一度ログインが完了するとログアウトしない限り、リフレッシュトークンの有効な期間(今回は30日と設定)は、認証なしで開けます。
2 動作環境
今回使用したバージョンは、以下の通りです。
% amplify --v
9.2.1
% flutter --version
Flutter 3.3.2 • channel stable • https://github.com/flutter/flutter.git
Framework • revision e3c29ec00c (8 days ago) • 2022-09-14 08:46:55 -0500
Engine • revision a4ff2c53d8
Tools • Dart 2.18.1 • DevTools 2.15.0
3 Flutterでのアプリ作成
最初に、Flutterアプリを作成し、必要なライブラリを追加します。
% flutter create sample_app
% cd sample_app
% flutter pub add amplify_flutter
% flutter pub add amplify_auth_cognito
% flutter pub add amplify_authenticator
4 Amplify(Auth)設定
続いて、Amplifyを初期化します。
% amplify init
Authの追加は、マニュアルで行います。
% amplify add auth
Do you want to use the default authentication and security configuration?
Default configuration
Default configuration with Social Provider (Federation)
❯ Manual configuration
I want to learn more.
使用するのは、サインアップとサインインのみです。
Select the authentication/authorization services that you want to use:
User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storage features for images or other content, Analytics, and more)
❯ User Sign-Up & Sign-In only (Best used with a cloud API only)
I want to learn more.
プロジェクト名及び、ユーザープール名は、デフォルトのままとしました。
Provide a friendly name for your resource that will be used to label this category in the project:
sampleapp519f64ce519f64ce
Provide a name for your user pool:
sampleapp519f64ce_userpool_519f64ce
ログインは、ユーザー名を使用することにします。
How do you want users to be able to sign in? (Use arrow keys)
❯ Username
Email
Phone Number
Email or Phone Number
I want to learn more.
UserPoolのグループ、管理用APIは、いづれもONとしました。
Do you want to add User Pool Groups?
❯ No
Do you want to add an admin queries API?
❯ No
ここが、MFAの設定ですが、認証時必須とし、SMSを用いるよう設定します。
Multifactor authentication (MFA) user login options:
OFF
❯ ON (Required for all logins, can not be enabled later)
OPTIONAL (Individual users can use MFA)
I want to learn more.
For user login, select the MFA types: (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◉ SMS Text Message
◯ Time-Based One-Time Password (TOTP)
SMSのメッセージの設定や認証コードを送るEメールの設定です。 デフォルトのまま。
Specify an SMS authentication message: (Your authentication code is {####})
パスワードを忘れた場合は、SMSを使用するようにします。
Email based user registration/forgot password:
Enabled (Requires per-user email entry at registration)
❯ Disabled (Uses SMS/TOTP as an alternative)
この時のSMSメッセージもデフォルトのままとしています。
Please specify an SMS verification message: (Your verification code is {####})
デフォルトのパスワードポリシーは、そのまま利用します。
Do you want to override the default password policy for this User Pool? (y/N)
サインアップ時に必要な情報は、すべてのチェックを外しておきます(電話番号は自動的に必須となります)
What attributes are required for signing up?
◯ Zone Info (This attribute is not supported by Facebook, Google, Login With Amazon, Signinwithapple.)
◯ Address (This attribute is not supported by Facebook, Google, Login With Amazon, Signinwithapple.)
◯ Birthdate (This attribute is not supported by Login With Amazon, Signinwithapple.)
❯◯ Email
◯ Family Name (This attribute is not supported by Login With Amazon.)
◯ Middle Name (This attribute is not supported by Google, Login With Amazon, Signinwithapple.)
◯ Gender (This attribute is not supported by Login With Amazon, Signinwithapple.)
トークンの有効期限は、デフォルトの30日です。
Specify the app's refresh token expiration period (in days): 30
Do you want to specify the user attributes this app can read and write? No
機能の追加、ソーシャルログイン、Lmabda関数のトリガーは特に使い予定がないため選択無しで行っていきます。
Do you want to enable any of the following capabilities? (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯ ◯ Add Google reCaptcha Challenge
◯ Email Verification Link with Redirect
◯ Add User to Group
◯ Email Domain Filtering (denylist)
◯ Email Domain Filtering (allowlist)
◯ Custom Auth Challenge Flow (basic scaffolding - not for production)
◯ Override ID Token Claims
OAuthフローは、未使用です。
Do you want to use an OAuth flow?
Yes
❯ No
I want to learn more.
? Do you want to configure Lambda Triggers for Cognito? (Y/n) N
マニュアルによる設定が完了したらpushします。
% amplify push
5 SMS送信
AmplifyのAuth設定で、SMSを有効にすると、下記のような警告が表示されます。
⚠️ You have enabled SMS based auth workflow. Verify your SNS account mode in the SNS console: https://console.aws.amazon.com/sns/v3/home#/mobile/text-messaging
If your account is in "Sandbox" mode, you can only send SMS messages to verified recipient phone numbers.
AWSアカウントのSMS送信は、当初、サンドボックスモードとなっているため、認証に使用する電話番号は、検証済みとする必要があります。
SMSサンドボックスを終了し、本稼働にすいれば、電話番号の検証は必要なくなります。
また、アカウントの使用制限は、デフォルトで1USD/月となっています。
日本宛に送信する場合のSMS料金は1通あたり$0.07451であるため、1月あたり、13 通程度でリミットとなってしまいます。 これ以上の送信をする場合は、上限緩和申請、及び、ここでの設定値を変更する必要があります。
https://aws.amazon.com/jp/sns/sms-pricing/?nc1=h_ls
上限緩和申請する場合のサービスクォータの名称は、SMS Message Spending in USDです。
6 Flutterの実装
実装したのコードは、以下の通りです。
認証周りについては、Amplify UI Componentsに全てお任せとなっています。
lib/main.dart
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_authenticator/amplify_authenticator.dart';
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:flutter/material.dart';
import 'package:sample_app/amplifyconfiguration.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _amplify = Amplify;
@override
initState() {
super.initState();
_configureAmplify();
}
Future<void> _configureAmplify() async {
try {
await _amplify.addPlugins([
AmplifyAuthCognito(),
]);
await _amplify.configure(amplifyconfig);
} catch (e) {
debugPrint(e.toString());
}
}
@override
Widget build(BuildContext context) {
return Authenticator(
child: MaterialApp(
debugShowCheckedModeBanner: true,
theme: ThemeData(
primarySwatch: Colors.red,
),
builder: Authenticator.builder(),
home: const HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
final title = 'Sample';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
drawer: AppDrawer(
title: title,
),
body: const Center(
child: Text(
"Hello World.",
),
),
);
}
}
class AppDrawer extends StatelessWidget {
const AppDrawer({super.key, required this.title});
final String title;
@override
Widget build(BuildContext context) {
return Drawer(
child: SingleChildScrollView(
child: Column(
children: [
AppBar(
title: Text(title),
automaticallyImplyLeading: false,
),
ListTile(
leading: const Icon(Icons.exit_to_app),
title: const Text('Logout'),
onTap: () {
Amplify.Auth.signOut();
},
),
],
),
),
);
}
}
7 最後に
今回は、Amplify UI Componentsを使用して、MFA対応の認証付きアプリを作成してみました。 認証周りは、自前で実装なると、準備するページを沢山あって、結構手間がかかります。提供されるコンポーネントで表現できる範囲で治ると、助かるのですが・・・