🐷

Amplifyのアプリで「Eメールまたはユーザ名」でログインできるようにする

2022/12/05に公開

前置き

みなさまどうもこんにちは、やぐちはるおでございます。2022 年もとうとう暮れの師走となってしまいました。残すところ 30 日も無いわけでございますが、本年はいかほどにお過ごしだったでしょうか。

あたしはというと(中略)背筋をピン!と奮い立たせ

あたしはというと、大層忙しい年となってしまいました。退職して起業して結婚して来年には子供が生まれる予定でございます。こんだけ忙しい中で、あたしが世のため人のために成したことと言えば、……言えば言えば、言えばと言っても特に何もしてはおらず、日がな一日、積み木にも劣る今日の積み上げをツイットしていたくらいです。

--

これじゃあ 2022 年は何の成果も得られてないじゃないかと、締め切り間近のレポートのごとく焦燥感に駆られるままあたしに何か出来ることはないかと模索を続けて早 2 時間。気づいたら再び Twitter を眺めておりました。

--

Twitter、不思議な魔力がございますね。あたしが Twitter を始めてから 10 年以上経ちますが、未だに「TL をずっと眺めていたら何か有意義な情報が得られるのではないか」という射幸心に煽られながら、未だ離れられずにいるわけでございます。

--

さてさてそんな折、タイムラインの上流からどんぶらこどんぶらこと流れてきたツイットを見てみると、いつもの Qiita の記事でございました。最近は会社のアプリ開発が忙しいもんで、TL に流れてきた技術記事をあまり読んでいませんでしたが、少し目を引くタイトルだったからか、流れてきた記事のリンクをクリックしていました。

--

すると記事の内容よりも記事タイトルのすぐ上にあった文字に目が行ったわけでございます。

「Advent Calendar」

そうかそうか、もうそんな時期か。今年も「本番環境でやらかしちゃった人」カレンダーを眺めて年を越そうかと考えながら、2022 年は何のせいかも得られてないじゃないかと焦燥感に駆られたことはすっかり忘れ、他におもろいカレンダーが無いかと探すこと早 10 分。偶然にも本記事が該当する AWS Amplify のカレンダーを見つけるに至りました。

--

AWS Amplify といえば AWS 版の Firebase。といえば聞こえはいいですが、実際に使ってみると Firebase ほど使いやすさに優れてはおりません。しかし発表から現在に至るまでものすごいペースで改善が続けられ、数年のうちには Firebase と比較しても遜色ない開発ツールとなるものと思っています。

--

とは言いつつも現在はまだまだ不便なところが多いツールではございます。こんな書き方するからにゃあ、と みなさまお察しでございましょうが、あたしはいま現在、Amplify を使ったアプリ開発を継続的に実施しています。何を隠そう起業先では Firebase と Amplify を比較したうえで Amplify を選定しております。決して血迷ってなどおりません。あのときはただ挑戦的だっただけでございます。

--

Amplify を使ってみた所感は、またいつかどこかで機会があれば徒然なるままに綴ってみたいと思いますが、おそらくそんなことはしないので、あたしのツイットを監視しといていただくのが一番手っ取り早いかと存じます。

--

話を戻しますが AWS Amplify であればこの 1 年で使ってきた経験が活かせるぞと一念発起、積み木にも劣る積み上げツイットをする指と、ただただ TL を眺めるためだけに曲がりに曲がった背筋をピン!と奮い立たせ

そんなわけで本記事を書くに至ったわけでございます。

TL;DR

  • Amplify CLI を使った認証では「E メールまたはユーザ名」をログイン ID として設定出来ない
  • Cognito コンソール画面を直接いじることで「E メールまたはユーザ名」をログイン ID に利用できる
  • Amplify コンソール画面と Amplify CLI の両方から Cognito 設定を紐づける作業が必要となる

0. 前提条件

  • Amplify Hosting 設定済み
  • Amplify CLI は Ver. 10.0.0 以下です。$ amplify -vで確認できます
  • Amplify で CloudFormation, CDK のいずれかを使えば可能かもしれませんが、当記事記載時点では試していません。有識者求ム
  • Amplify Studio は使っていませんが、コマンドで実行している部分を Studio の画面操作に置き換えれば良さそうです。誰か試してみて

1. Amplify の認証について

AWS Amplify では、アプリ内で簡単にログインを実現するために「認証」と呼ばれる機能を持っています。この機能は、Amplify CLI で以下のコマンドを実行するだけで導入することができます。

$ amplify add auth

上記コマンドを実行すると以下のようにログイン ID として何を用いるか質問されます。

? How do you want users to be able to sign in?
> Username
  Email
  Phone Number
  Email or Phone Number
  I want to learn more.

ここで問題が発生しました。

Amplify CLI では「E メールまたはユーザ名」が設定できない

上記の質問に対する選択肢を見ると、「E メールまたはユーザ名」が選択できません。この質問で「E メール」と指定して、ログインに「ユーザ名」を入力すると以下のエラーが返ってきます。

message: "Username should be an email."

一応 AWS サポートにも確認しましたが、現時点の CLI では「E メールまたはユーザ名」をログイン ID として用いることは不可能とのことでした[1]。そこで今回は Amplify「認証」機能の実体である Amazon Cognito を直接いじって解決します。

Amplify 認証の実体は Amazon Cognito

Amazon Cognito は Amplify「認証」機能の実体であり、俗に言う「裏で動いているサービス」になります。Cognito の方では「E メールまたはユーザ名」をログイン ID として扱う設定が可能ですが、Amplify CLI だけで完結させるのと比べると、以下の点などが少し面倒です。

  • Cognito におけるユーザプールと ID プールの理解
  • Cognito リソースを手動作成して Amplify と紐づける作業
  • 新しいアプリ環境を作るたびに作業を実施

以下で 2 つ目の作業手順について説明します。[2]

2. Cognito コンソール画面 でリソースを作成する

まずはブラウザで AWS にログインして Cognito コンソール画面でユーザプールを開きます。

Cognitoユーザプール

「E メールまたはユーザ名」で認証できるユーザプールを作成

「ユーザプールを作成」を押して、作成画面を開きます。ここで設定する必要があるのは以下の 3 つで、あとはデフォルトでも大丈夫です。よく読んで適当に設定してください。

1. サインインオプションで「ユーザ名」と「E メール」にチェック

Cognitoユーザプール作成1

2. ユーザプール名を(アプリ名)-userpool-(Amplify環境名)のように設定

Cognitoユーザプール作成2

名前はぶっちゃけ何でも良いんですが、Amplify の環境の数だけ作ることになるので、こう書けば区別できます。

3. 「アプリケーションクライアント名」を(アプリ名)-client-webのように設定

Cognitoユーザプール作成3

名前はぶっちゃけ何でも良いんですが、Web アプリ用とネイティブアプリ用の 2 つ作るので、こう書けば区別できます。

4. アプリケーションクライアントを追加で作成

先程「最初のアプリケーションクライアント」では Web アプリ用のクライアントを作成しました。前述の通り、Amplify では Web 用とネイティブ用の 2 つ作る必要がありますが、2 つ目はユーザプールを作成後になります。作成したユーザプールの画面を開き、「アプリケーションの統合」タブから「アプリケーションクライアントを作成」を押します。

Cognitoユーザプール作成4

「アプリケーションクライアント名」を(アプリ名)-client-nativeのように設定したら作成します。名前はぶっちゃけ(以下略)。アプリケーションクライアントが 2 つ作成出来てれば OK です。

Cognitoユーザプール作成5

上記ユーザプールを紐づけた ID プールを作成する

次に ID プール(フェデレーティッド ID)を開き、「新しい ID プールの作成」を押します。

Cognito IDプール作成1

ID プール名は(アプリ名)-idpool-(Amplify環境名)のようにします。ぶっ(以下略)。また「認証されていない ID に対してアクセスを有効にする」にチェックをつけます。これはログインしていないユーザに、API 呼び出しを許可したりするために用います。

Cognito IDプール作成2

次に認証プロバイダーで、先程作成した 2 つのアプリケーションクライアントを設定します。ユーザプール ID とアプリクライアント ID はユーザプール側のページで確認できます。

Cognito IDプール作成3

最後に「プールの作成」→「許可」で ID プール作成完了です。

3. Cognito のリソースを Amplify に紐づける

次は作成したユーザプールと ID プールを Amplify で使えるように紐づけ設定を実施します。ドキュメントなどに記載されている通り$ amplify import authを実行すれば簡単に出来るかと思いきや、環境変数を別途設定しないとビルドが落ちる罠が待っているので注意です。

Amplify CLI でリソースのインポート

アプリのルートディレクトリで以下のコマンドを実行して、4 つの質問に答えます。

$ amplify import auth

「認証リソースの種類はどれですか?」
→ ユーザプールと ID プール

? What type of auth resource do you want to import? ...
> Cognito User Pool and Identity Pool
  Cognito User Pool only

「インポートしたいユーザプールを選んでください」
→ 先程作成したユーザプール

? Select the User Pool you want to import: ...
amplify_backend_manager_dvtrc10ijuzs3 (ap-northeast-1_***)
appname-userpool-dev (ap-northeast-1_***)

「Web アプリ用クライアントを選んでください」
→ ***-client-web

? Select a Web client to import: ...
appname-client-native (17nc***)
appname-client-web (73he***)

「ネイティブアプリ用クライアントを選んでください」
→ ***-client-native

? Select a Native client to import: ...
appname-client-native (17nc***)
appname-client-web (73he***)

以下の表示が出ればインポート完了です。

✅ Cognito User Pool 'appname-userpool-dev' and Identity Pool 'appname-idpool-dev' was successfully imported.

ここで終わりかと思ってビルドすると以下のエラーが出ます。こんなの、絶対おかしいよ。

2022-02-03T08:18:17.545Z [INFO]: [0mError: auth headless is missing the following inputParams userPoolId, webClientId, nativeClientId, identityPoolId[0m
[0m at ensureHeadlessParameters (/root/.nvm/versions/node/v14.18.1/lib/node_modules/@aws-amplify/cli/node_modules/@aws-amplify/amplify-category-auth/src/provider-utils/awscloudformation/import/index.ts:1312:11)[0m
[0m at headlessImport (/root/.nvm/versions/node/v14.18.1/lib/node_modules/@aws-amplify/cli/node_modules/@aws-amplify/amplify-category-auth/src/provider-utils/awscloudformation/import/index.ts:1169:40)[0m
[0m at importedAuthEnvInit (/root/.nvm/versions/node/v14.18.1/lib/node_modules/@aws-amplify/cli/node_modules/@aws-amplify/amplify-category-auth/src/provider-utils/awscloudformation/import/index.ts:946:32)[0m
[0m at runMicrotasks (<anonymous>)[0m
[0m at processTicksAndRejections (internal/process/task_queues.js:95:5)[0m
[0m at updateConfigOnEnvInit (/root/.nvm/versions/node/v14.18.1/lib/node_modules/@aws-amplify/cli/node_modules/@aws-amplify/amplify-category-auth/src/provider-utils/awscloudformation/index.js:52:72)[0m
[0m at /root/.nvm/versions/node/v14.18.1/lib/node_modules/@aws-amplify/cli/node_modules/@aws-amplify/amplify-category-auth/src/index.js:349:22[0m
  2022-02-03T08:18:17.577Z [ERROR]: !!! Build failed
  2022-02-03T08:18:17.577Z [ERROR]: !!! Non-Zero Exit Code detected
  2022-02-03T08:18:17.577Z [INFO]: # Starting environment caching...
  2022-02-03T08:18:17.577Z [INFO]: # Uploading environment cache artifact...
  2022-02-03T08:18:17.733Z [INFO]: # Environment caching completed

エラー文の 1 行目を見ると、次の入力パラメータが無いよって言ってます。

  1. userPoolId
  2. webClientId
  3. nativeClientId
  4. identityPoolId

これの解決法は Amplify 公式ドキュメントの認証ページ にありました[3]。どうやら Amplify ビルド時の環境変数として設定してあげれば良いようです。

Amplify コンソールで環境変数設定

Amplify コンソール画面でアプリを選択し、「アプリの設定」→「環境変数」を押して環境変数設定画面を開きます。

Amplify 環境変数設定1

右上の「変数の管理」を押して、以下 4 つの環境変数を設定します。

  • AMPLIFY_USERPOOL_ID
  • AMPLIFY_IDENTITYPOOL_ID
  • AMPLIFY_WEBCLIENT_ID
  • AMPLIFY_NATIVECLIENT_ID

ここで面倒なのが、単純に変数を追加しただけでは、すべての Amplify 環境に適用されてしまいます。そのため「アクション  ▼」→「変数の上書きを追加する」から環境専用の変数を更に追加設定してあげないといけません[4]

Amplify 環境変数設定2

最後にビルド&デプロイ

最後にアプリをビルド&デプロイします。実際にこの設定をした画面とアプリがこちらになります。Amplify が用意した UI 使わずに自前でログイン画面作りました。これはステマという説が濃厚です。

https://app.tripqot.com/

アプリログイン画面

後書き

Amplify は割りと大きく仕様が変わるので、1 年以上経過した解説記事と全然状況が異なっていることが、稀によくあります。基本的には公式ドキュメントGitHub issueで調べるようにするのが吉です。会社で開発している方は、ぜひ AWS サポートの有料プランに入るのをおすすめします。ちゃんと解決するまで付き合ってくれます。

あとよかったらTwitterフォローしてください。最近は Amplify について話していることは稀ですが、Amplify を使ったアプリ開発を続けているので質問など投げかけてもらえればお答えさせていただきます。

脚注
  1. 社内で「ユーザ名か E メールのどちらでログイン ID を統一するか」と意見を交えたのですが、見事に「いつも E メール使ってる派」と「いつもユーザ名使ってる派」で東西に分裂し、長期間に渡る冷戦の末に「どちらを入力してもログイン可能にする」という融和政策が取られました。 ↩︎

  2. ユーザプール、ID プールについてはこの記事で扱うにはそこそこ重いため、詳しく知りたい方は別途解説記事を読んでください。新しいアプリ環境については、この記事を読んだ後なら少々のトライアンドエラーで問題なく実施出来ると思います。わかんなかったら Twitter で LINE してください。 ↩︎

  3. ページの一番下に書いてあって普通に気づかなかったけど、ビルド通すために必須ならもうちょい分かりやすいところに書いといてほしいですね ↩︎

  4. 環境が一つしか無いうちは気にしなくて良いかも知れませんが、環境を追加したときにおそらくビルドエラーが出て「???」ってなります。 ↩︎

Discussion