AmazonCognitoでユーザー認証するリバースプロキシサーバーをdocker-composeで構築する

## はじめに
社内で構築したWEBアプリを社外のユーザーにも使ってもらう際に、ユーザー認証部分を従来は node.js+express+passport で構築していました。
この方式の場合、ユーザーの追加変更削除を行うにはユーザーを管理するデータベースを直接触るか、または別途ユーザー管理画面を作成する必要があり手間がかかっていました。
今回この認証とユーザー管理部分をAWSのCognitoに移行したので手順を共有します。
なお、このサンプルではローカルPCにWEBアプリおよびリバースプロキシをサーバー構築するものとします。

## Amazon Cognitoの設定
### ユーザープールの作成
* AWSにログインしてサービスの一覧から Cognito をクリックし、次画面で[ユーザープールを作成]ボタンをクリックします。
![010_WS000587.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/13529682-feef-b364-92a8-714cc3b28446.jpeg)

* Cognitoユーザーのサインインオプションは「Eメール」のみ選択します。
![020_WS000588.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/961315bf-9bcd-b397-b7a5-89659765fd17.jpeg)

* セキュリティ要件では「MFAなし」を選択します。
![030_ユーザープールを作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/7beeb96e-383b-d50b-2b74-84ea20a68f97.png)

* 今回は特定のユーザーのみログインさせたいので「自己登録」は無効にします。
![040_ユーザープールを作成 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/7039d118-b213-6f80-4f8c-a1bdb8c92b2a.png)

* テスト段階ではメッセージ配信にはCognitoにメール送信してもらいます。
![050_WS000589.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/2fe2d20a-1e65-1a86-1236-eafd113e18f1.jpeg)

### アプリケーションを統合
かなり縦長の画面です。
* 適当なユーザープール名、ドメイン名を設定します。
* 認証をかけるアプリはWEBサーバーなので「パブリッククライアント」を選択し、適当なアプリケーションクライアント名を設定します。
* 「クライアントシークレットを生成する」にチェックを入れます。
* コールバックURLに認証サーバーのURLを設定します。<br>localhostの場合は<br><font color="Tomato">http</font>://localhost/oauth2/callback<br>を設定します。
* OpenIDスコープには、OpenID＋Eメール＋プロファイル、の３つを選択します。
![060_ユーザープールを作成 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/cd69b95d-53ba-7a28-0df0-d09c8c72cd60.png)

* いままで設定した項目の確認画面が表示されるので画面最下部の[ユーザープールを作成]をクリックします。
![080_WS000591.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/4c914349-a2e2-2f74-90d1-d8e79e3c42b2.jpeg)

* ユーザープールが作成されました。
![090_WS000592.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/4fda43cf-b9d2-63ac-47e1-e97f8f8b1c07.jpeg)

* 続いて、認証するユーザーを追加します
![100_sixfeets-auth2-ユーザープール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/42899eee-5871-9eef-4732-ddc762c300e8.png)

* ユーザーの情報を設定します。EメールアドレスがログインIDになります。
![110_WS000597.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/d7eccf06-c4e7-ddbc-9beb-b2d6d94423e2.jpeg)

* ユーザーが追加されました。
![120_WS000598.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/a5ae37a8-3db8-af52-9048-6387bf2e0f21.jpeg)

* ユーザーに初期パスワード通知のメールが送信されます。

### IDプールの作成
* 左ペーンのメニューから[フェデレーティッドID]をクリックします。
![120x_WS000598.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/b3c45754-defe-c48d-4ae4-0fa10019dcba.jpeg)

* [新しいIDプールの作成]をクリックします。
![130_WS000601.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/867b3fc7-5e77-b3f8-d74d-bab5ba340c60.jpeg)

* IDプールの内容を設定します
![140_新しい-ID-プール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/1f315bab-e034-414a-85e8-24a84e441374.png)

* 新しいロールが作成されることを許可してあげます。
![150_WS000602.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/bed9e4a1-b2ee-47da-01fc-dd155c8a801b.jpeg)

* IDプールが作成されました（この画面では何もすることはありません）
![160_WS000603.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80431/78acb443-5dec-f27c-5fdc-cb5c8e95ee67.jpeg)

## dockerの設定
* hogeディレクトリ以下に構築するものとします。

```shell:ディレクトリ構成
hoge
├── docker-compose.yml
├── web
    └── Dockerfile
```

```yaml:docker-compose.yml
version: "3"

services:
  web:
    build: web
    ports: 
      - 8000:80

  proxy:
    image: quay.io/oauth2-proxy/oauth2-proxy
    ports:
      - 80:4180
    dns: '192.168.XX.XX' #①
    environment:
      OAUTH2_PROXY_HTTP_ADDRESS: 0.0.0.0:4180
      OAUTH2_PROXY_COOKIE_SECRET: 01234567890123456789012345678912
      OAUTH2_PROXY_COOKIE_SECURE: "false"
      OAUTH2_PROXY_COOKIE_NAME: "oauth2_proxy"
      OAUTH2_PROXY_EMAIL_DOMAINS: "*"
      OAUTH2_PROXY_UPSTREAMS: http://web/
      OAUTH2_PROXY_PROVIDER: oidc
      OAUTH2_PROXY_OIDC_ISSUER_URL: https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_XXXXXXXXX #②
      OAUTH2_PROXY_CLIENT_ID: XXXXXXXXXXXXXXXXXXXXXXXXX #③
      OAUTH2_PROXY_CLIENT_SECRET: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #④
      OAUTH2_PROXY_REDIRECT_URL: http://localhost/oauth2/callback
      OAUTH2_PROXY_SCOPE: openid email profile
      OAUTH2_PROXY_PASS_ACCESS_TOKEN: "true"
      OAUTH2_PROXY_PASS_USER_HEADERS: "true"
      OAUTH2_PROXY_PASS_AUTHORIZATION_HEADER: "true"
      OAUTH2_PROXY_SKIP_PROVIDER_BUTTON: "true"
      OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL: "true"
      OAUTH2_PROXY_PROVIDER-DISPLAY-NAME: 'aws_cognito'
      OAUTH2_PROXY_LOGIN-URL: http://localhost/oauth2/login
      OAUTH2_PROXY_PROFILE-URL: http://localhost/oauth2/userInfo
      OAUTH2_PROXY_REDEEM-URL: http://localhost/oauth2/token
      OAUTH2_PROXY_COOKIE-DOMAIN: localhost
```
①ご自分のネットワークのDNSサーバーアドレス
②https://cognito-idp.{リージョン}.amazonaws.com/{リージョン}_{ユーザープールID}
③ユーザープール→アプリケーションクライアント→クライアントID
④ユーザープール→アプリケーションクライアント→クライアントシークレット

```shell:Dockerfile
FROM php:apache
RUN echo "<?php\nphpinfo();" > /var/www/html/index.php
```
※Dockerfileは [Docker で OAuth2 Proxy を動かすサンプル](https://qiita.com/hoto17296/items/7f78416965e4ae289de0?utm_source=pocket_saves) より引用しました


### テスト
hogeディレクトリで
<pre>docker-compose up</pre>
を実行しサーバーを起動後
http://localhost/
にアクセスし、Cognitoのログイン画面・パスワード変更画面を経てバックエンドサーバーのphpinfoの内容が見られれば完了です。

## まとめ
Cognitoの利用例ではALBと組み合わせるケースが多数で単独で利用する場合の情報が少なかったので、このドキュメントが参考になればと思います。

## 参考

https://qiita.com/hoto17296/items/7f78416965e4ae289de0?utm_source=pocket_saves

https://qiita.com/foo_72354921/items/beeecb7ac15c8b547a38?utm_source=pocket_saves