FlutterとAWSで始めるサービス開発 (5)AWS Cognitoでログイン


はじめに

前回の「(4)AWS Cognitoへの新規アカウント登録」では、Cognitoユーザープールに新規のアカウントを追加しました。今回はそのアカウントを利用してログインを行いたいと思います。

前回からの変更点

前回のコードからの変更点を順に説明します。

ログインセッション

ログインセッションを保存するためのグローバル変数を追加しました。

CognitoUserSession session;

MaterialAppのroutesにログイン結果画面用の定義を追加

'/TopPage'という名前で、ログイン後に遷移する画面の定義を追加しました。

      routes: <String, WidgetBuilder>{
        '/': (_) => new MyHomePage(),
        '/TopPage': (_) => new TopPage(),
        '/RegisterUser': (_) => new RegisterUserPage(),
        '/ConfirmRegistration': (_) => new ConfirmRegistration(null),
      },

ログイン画面の変更

ログインを実行するために、メールアドレス、パスワードを入力するためのテキストフィールド、ログインボタンを追加しました。ログインボタンを押下したら、_signIn()メソッドが実行されるように実装しています。

class MyHomePage extends StatelessWidget {
  final _mailAddressController = TextEditingController();
  final _passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ログイン'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: TextField(
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: '[email protected]',
                  labelText: 'メールアドレス',
                ),
                controller: _mailAddressController,
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: TextField(
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: 'password',
                  labelText: 'パスワード',
                ),
                obscureText: true,
                controller: _passwordController,
              ),
            ),
            Container(
              alignment: Alignment.centerRight,
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                child: Text('ログイン'),
                color: Colors.indigo,
                shape: StadiumBorder(),
                textColor: Colors.white,
                onPressed: () => _signIn(context),
              ),
            ),
            Divider(color: Colors.black),
            RaisedButton(
              child: Text('新しいアカウントの作成'),
              color: Colors.indigo,
              textColor: Colors.white,
              shape: StadiumBorder(),
              onPressed: () => Navigator.of(context).pushNamed('/RegisterUser'),
            ),
          ],
        ),
      ),
    );
  }

  void _signIn(BuildContext context) async {
    var cognitoUser = new CognitoUser(_mailAddressController.text, userPool);
    var authDetails = new AuthenticationDetails(
        username: _mailAddressController.text,
        password: _passwordController.text);
    try {
      session = await cognitoUser.authenticateUser(authDetails);
      Navigator.of(context).pushReplacementNamed('/TopPage');
    } catch (e) {
      await showDialog<int>(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('エラー'),
            content: Text(e.message),
            actions: <Widget>[
              FlatButton(
                child: Text('OK'),
                onPressed: () => Navigator.of(context).pop(1),
              ),
            ],
          );
        },
      );
    }
  }
}

実装した画面は以下になります。

ログイン結果画面の追加

以下のようにログイン結果画面を追加しました。ログインセッションのアクセストークンのJWTを画面に表示するのみです。

class TopPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('トップページ'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('ログイン成功'),
            Divider(color: Colors.black),
            Text(session.getAccessToken().getJwtToken()),
          ],
        ),
      ),
    );
  }
}

実装した画面は以下になります。

ログイン

実際にログインする際の処理を改めて説明します。class MyHomePage_signIn()メソッドに処理があります。ログイン画面で入力されたメールアドレスとパスワードを利用します。まず、CognitoUserクラスをインスタンス化します。引数にはユーザー名であるメールアドレスとユーザープールのインスタンスになります。次に、ログインに必要な詳細情報をAuthenticationDetailsクラスをインスタンス化して作ります。メールアドレスとパスワードをセットします。最後に、ログインに必要な詳細情報を引数にCognitoUserクラスauthenticateUserメソッドを実行することでログイン処理が行われサーバーのセッションを取得できます。

画面遷移

ログインに成功したら、Navigator.of(context).pushReplacementNamed('/TopPage')にて画面遷移をします。pushReplacementNamedメソッドは今存在する画面スタックをすべて置き換えて、引数で与えられた'/TopPage'の画面に置き換えます。これにより下記で示すような画面遷移をし、ログイン結果画面がスタックに積まれた唯一の画面として表示されま。

まとめ

ユーザープールに作成したアカウントでのログイン処理を確認できました。次回「(6)AWS Cognito 「パスワードを忘れた方はこちら」」とし、ユーザーがログインパスワードを忘れてしまった場合の処理を作っていきたいと思います。