Cognitoの、あともう少し...と思うところ 

![image.png](https://qiita-image-store.s3.amazonaws.com/0/120358/1ec6cc8c-a7d1-6ae6-248a-1b5e37b2911f.png)

## 概要

最近、個人で開発しているSPAサイトでCognitoを使ってUser認証機能を実装したのですが、その際に感じた、「Cognitoさん、あともう少し頑張って...」と思うところを書いていこうと思います！

はじめに、Cognito自体はとても便利という前提の上で書かれています。つまり、ここに書いているのは、最高のCognitoをより最高にするには、こういう細かいところもカバーして欲しいなぁという贅沢な要望なのです。
なので、決してCognitoを批判する内容ではないことを念押ししておきます:sweat_smile:

※ 2018年9月時点でのCognitoの機能の事を指しているので、今後のアップデートできっと良くなっていくはず...きっと...

## Cognitoとは

まず、Cognitoについて語っていく前にCognitoとはなんぞやという説明をしようと思います。

> Amazon Cognito を使用すれば、ウェブアプリケーションおよびモバイルアプリに素早く簡単にユーザーのサインアップ/サインインおよびアクセスコントロールの機能を追加できます。Amazon Cognito は、数百万人のユーザーにスケールし、Facebook、Google、Amazon などのソーシャル ID プロバイダー、および SAML 2.0 によるエンタープライズ ID プロバイダーを使用したサインインをサポートします。
https://aws.amazon.com/jp/cognito/

てな感じで、ユーザの認証系が簡単に作れちゃうAWSのマネージドサービスのことです。

Cognito単体で認証する場合は5万ユーザは無料で作れてしまうスグレモノ:relaxed:
https://aws.amazon.com/jp/cognito/pricing/

## Cognitoのいいところ

実際に使ってみるとわかるが、ボタンをポチポチするだけで簡単に構築できて、 `User Pool Id` と `client_id` を使ってリクエストを投げれば簡単にユーザを登録することが出来てしまいます。

SPAやモバイルのようなクライアントで動くものにも対応しており、 [aws-amplify](https://aws-amplify.github.io/)という、これまたAWSさんが提供してくれているライブラリを使えば、簡単にCognitoを使ったUser認証をサービスに組み込むことが出来ます。

Facebook LoginやGoogle Loginにも当然対応しており、ソーシャルログインもお手の物です。

アクセス許可に関してもAWSサービスとの連携がやりやすいのが特徴です。認証フェデレートでログイン後にIAMユーザと同じようにAWSリソースへのアクセス許可も出すことが出来ます(例えば、ログインしたユーザしか見れない画像がS3のバケットに入ってる的なものを実装できちゃう)。

更に、とてもありがたいことに、Emailの存在確認用の確認コードを送る機能や、Passwordの再発行機能も全て組み込まれています。

また、認証後にも便利なサービスが用意されています。そう、[Cognito Sync](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-sync.html)だ...。
(これに関しては、実際に使っていないので詳細は語ら(れ)ないです。ご興味がある方は是非使ってみて僕に所感を教えて下さいw)

## Cognitoの、あともう少し...と思うところ

### 1. 用意されているUIが...

[こちら](https://dev.classmethod.jp/client-side/javascript/amplify-custom-signup/)の記事でも紹介されているのだが、[aws-amplify-react](https://github.com/aws-amplify/amplify-js/tree/master/packages/aws-amplify-react)というライブラリを使うと既に用意されているUIを用いることができます。
つまり、サインインページやサインアップページを作る必要がないのです！
実際に用意されているUIがこんな感じ(リンク先から拝借)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/120358/67d4a538-b248-bf25-788f-c10809de1b5b.png)

うーん、海外っぽいUIだな。まぁ、でもThemeを適応出来るらしいし、[インスタグラム](https://github.com/richardzcode/a-theme-react)のログイン画面っぽく出来るらしいし良いか...。
ん？おかしいFieldをカスタマイズできない、、、電話番号なんて入力してもらう必要ないのに...:sob:!!!

という感じで、UIを用意してくれていてすごい楽にできると思って、Themeを色々試してみたり、AWSコンソールのCognitoのUI customizationページを色々弄って見ても、Fieldを変更することはできませんでした...。
最終的に `aws-amplify-react` のコードを遡った結果、結局ほとんど自前で作らないと行けないということが判明し、悲しい結末に到達しました :innocent:

とはいえ、これは自分でUIを作れば良い話なので、自分で解決することが出来ます。

===== 2020.06 追記 =====

Cognitoを使っていたサービスをクローズしたため追えていませんでしたが、どうやらサインアップ時のカスタムフィールドの指定が可能になったそうです:tada:
https://github.com/aws-amplify/amplify-js/issues/2160#issuecomment-469000756

書き方としては以下のように`signUpFields`というオプションを渡すことで、カスタムフィールドの生成を可能にするらしいです。
簡単ですね、最高です:tada:

```js
export default withAuthenticator(App,{
  signUpConfig:{
    hideAllDefaults: true,
    signUpFields: [
      {
        label: 'UserName',
        key: 'username',
        placeholder: 'Enter your email',
        required: true,
        displayOrder: 1,
        type: 'string'
      },
      {
        label: 'Password',
        key: 'password',
        placeholder: 'Enter password',
        required: true,
        displayOrder: 2,
        type: 'password'
      }
    ]
  }
});


```

@makuidawasa さん、教えて頂きありがとうございます！:smile:

### 確認リンクを押した後が...

Cognitoのサインアップフローには、2つの確認方法があります。

1. 登録してもらったメールアドレス宛に、確認コードを送信し、サービス側で入力してもらうというもの
2. 登録してもらったメールアドレス宛に、確認用リンクを送信し、リンクを踏んでもらうというもの

自分は、2つ目の確認用リンクのほうが圧倒的に楽だと思いました。何故かと言うと、確認コードの場合、メールで送信した確認コードを入力する画面を作成しなければならないからです。また、UX的にも「メールで送られてきたコードをコピペして...」と、めんどくさいフローになってしまいます。
上記の理由から、確認リンクを送信する方法を選択したのだが、これが想像しない事態を起こす...

![image.png](https://qiita-image-store.s3.amazonaws.com/0/120358/135116ba-cd53-43fb-65ab-fd2e7f3932f4.png)

おわかりだろうか...。
日本のサービスなので、当然メールの中身は日本語で書かれているのだが、**確認用リンクを踏むと英語のページに飛ぶのだ！**

ほーん、ならこのページの文言カスタマイズしてやれば良いんでしょ...。なっ、ない！！？

ま、まぁ待て、認証後にサービスページにリダイレクトしてやるようにすればこの画面を見ずに済むじゃないか...。[未・実・装](https://github.com/aws-amplify/amplify-js/issues/612#issuecomment-400749102)！！！

という感じで手詰まりになってしまったので、どうしようか頭を抱えていたところで、救世主登場！
https://qiita.com/rioc/items/523360527d7253a50d28

Lambdaを使って確認用リンクをwrapしたURLを発行して対応しているらしいです。インシュアラー :innocent: 

### CloudFormationで確認メールのLinkが選べない...

自分はAWSリソースであれば、なんでもCloudFormationで管理したくなるCloudFormation病患者なのですが、Cognitoには、CloudFormation病の発作を起こされてしまいました...。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/120358/15009be6-e340-a068-eb39-fe42625b2a6f.png)

先程の書いたように、Cognitoのサインアップ後の確認方法は2つあります。
そう、確認コードと確認リンクです。

残念なことに**CloudFormationでは、確認コードの方しか設定することができません**。
つまり、確認リンクのメールボディやサブジェクトはCloudFormationから設定することはできないないということです...:frowning2:
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpool.html

お気づきでしょうか...。それだけではないのです...。**App integrationのDomain Nameも設定することはできない**のです！！！

設定できない部分は、手動で設定するしかなく、自動化をこよなく愛す私としては中々のツラミでした。

とはいえ、CloudFormationが対応していないAWS Resourceは沢山あるので、それに比べれば全然大したことはありません。

だいたい、CloudFormationがCognitoに対応したのも2017年の4月末あたりなので、まだ新しい方です。
これからの成長に期待することができます :smile: 
https://aws.amazon.com/jp/about-aws/whats-new/2017/04/amazon-cognito-now-supported-by-aws-cloudformation/

===== 2020.06 追記 =====

どうやら確認リンクのメッセージもCloudFormationから変更可能になっていたようです:tada:
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-userpool-verificationmessagetemplate.html

`DefaultEmailOption` というPropertyを `CONFIRM_WITH_LINK` にしてメールボディとサブジェクトを指定してやれば良さそうです。

また、App Integrationのカスタムドメイン名もCloudFormationから設定可能になっていそうでした :tada:
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpooldomain.html

予想通りに成長してくれてとても嬉しい:relaxed:

※ 実際に試していないので、本当に使えるかは不明です... :bow:

## さいごに

Cognitoについて色々書いてきましたが、結局言いたかったのは「**Cognitoはいい子なんです！**」ということ。
ここで書いたものも、そのうちAWSさんが対応してくれるでしょうし、これからどんどん隙のないサービスになっていくことでしょう:tada: