🐙

Amplify で Cognito の Hosted UI を利用した認証を最低限の実装で動かすのを Windows 11 で実施してみた

2024/05/05に公開

「サクッと動く認証画面を作りたいが、ネット上に落ちているサンプルが全部 Unix 向けで全然手元の Windows 端末で動かないよ!」となりました。Windows 11 に Node.js をインストールし VScode で頑張ったので記録しておきます。

もとになる記事

https://dev.classmethod.jp/articles/learn-authentication-using-cognitos-hosted-ui-with-amplify/

このブログの

を実施し、Windows 11 のブラウザ(Google Chrome)で認証画面が動くのを確認しました。

コードの解説 以降は元になる記事を参照。

Windows 11 で実施してみる

前提

  • 端末は Windows 11
  • Git for Windows インストール済
  • AWS CLI インストール済
  • Visual Studio Code(以降 VSCode と省略)インストール済
  • VSCode で git コマンド、AWS CLI コマンドが利用できる状態になっている
  • VSCode のターミナルは PowerShell
    • この後のコマンドは VSCode のターミナルの PowerShell で実行する

Node.js と npm のインストール

Node.js 公式ウェブサイトにアクセスし、Windows 向けのインストーラをダウンロードしてください。LTS 版が一般的に推奨されています。

https://nodejs.org/en

ダウンロードリンクをクリック

ダウンロードしたインストーラを実行し、画面の指示に従ってインストールを完了してください。このプロセス中に、npmも一緒にインストールされます。

このチェックボックスを選択すると、ネイティブモジュールのコンパイルに必要な Python や Visual Studio Build Tools などのツールが自動的にインストールされます。開発にこれらのツールが必要な場合、または将来的に必要になる可能性がある場合は、ここでチェックを入れると便利です。必要ないと思われる場合は、チェックを入れなくてもインストールを続行できます。

以下の画面が自動で開きました。Enter キーを押下しました。

PowerShell が開いてプロセスが進行します。

10 分程度待っていると、以下の画面で動かなくなりました。開いているウィンドウを閉じて、Windows 11 を再起動します。

再起動後、VScode を起動して node --versionnpm --version を実行して、正しくインストールされているか確認します。事前にインストール済ですが AWS CLI のバージョンも aws --version で確認しておきます。

▼インストール結果

PS C:\Users\kitani.emi> node --version
v20.12.2
PS C:\Users\kitani.emi> npm --version
10.5.0
PS C:\Users\kitani.emi> aws --version
aws-cli/2.15.38 Python/3.11.8 Windows/10 exe/AMD64 prompt/off
PS C:\Users\kitani.emi>

一応使えるようにはなっていました。

Cognito環境の構築

ホームディレクトリはログイン中のユーザーのホームディレクトリになっていますが、好みでディレクトリ移動します。

PS C:\Users\kitani.emi> cd .\Documents\

git clone して環境一式を GitHub から取ってきます。
実行コマンド

git clone https://github.com/rednes/cognito-simple-example-for-external-idp.git

▼実行結果

PS C:\Users\kitani.emi\Documents> git clone https://github.com/rednes/cognito-simple-example-for-external-idp.git
Cloning into 'cognito-simple-example-for-external-idp'...
remote: Enumerating objects: 34, done.
remote: Counting objects: 100% (34/34), done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 34 (delta 10), reused 22 (delta 3), pack-reused 0
Receiving objects: 100% (34/34), 250.55 KiB | 8.95 MiB/s, done.
Resolving deltas: 100% (10/10), done.
PS C:\Users\kitani.emi\Documents> 

持ってきたディレクトリに移動します。

cd cognito-simple-example-for-external-idp

▼実行結果

PS C:\Users\kitani.emi\Documents> cd cognito-simple-example-for-external-idp
PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp>

VScode でフォルダを開くと以下のようになります。

AWS CLI で使用する profile を環境変数に設定します。

$env:AWS_PROFILE="kitani.emi"

▼実行結果

PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> $env:AWS_PROFILE="kitani.emi"
PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> 

aws sts get-caller-identity で意図したプロファイルが設定できたか確認します。

▼実行結果(途中 MFA コード入力)

PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> aws sts get-caller-identity
Enter MFA code for arn:aws:iam::スイッチ元AWSアカウントID:mfa/kitani.emi: # ここで MFA コード入力
{
    "UserId": "AROA45YZHQXxxxxxxxxxx:botocore-session-xxxxxxxxxx",
    "Account": "スイッチ先AWSアカウントID",
    "Arn": "arn:aws:sts::スイッチ先AWSアカウントID:assumed-role/kitani.emi/botocore-session-xxxxxxxxxx"
}

PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp>

スイッチ先 AWS アカウントの権限が表示されていれば OK です。

もとになる記事の手順に沿って以下コマンドを実行し、CloudFormation を実行します。これで、Cognito のリソースを作成します。

npm run cfn-deploy

▼実行結果

PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> npm run cfn-deploy

> cognito-simple-example-for-external-idp@1.0.0 cfn-deploy
> aws cloudformation deploy --template-file ./cloudformation/template.yaml --stack-name CognitoSimpleExample --capabilities CAPABILITY_IAM


Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - CognitoSimpleExample
PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> 

CloudFormation で Cognito の環境構築が完了しました。

npm run cfn-describe で CFn 結果確認しようとしたところエラーになります。

PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> npm run cfn-describe

> cognito-simple-example-for-external-idp@1.0.0 cfn-describe
> aws cloudformation describe-stacks --query 'Stacks[0].[Outputs[].[OutputKey,OutputValue]]|[]' --output table --stack-name CognitoSimpleExample

'[]'' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp>

PowerShellでは、クエリ文字列の内部でダブルクォートをエスケープするためにバッククォート(`)を使用するか、シングルクォート全体をダブルクォートで囲む必要があります。
プロジェクトの package.json ファイル内の cfn-describe スクリプトの行を見つけて修正します。16 行目でした。

"cfn-describe": "aws cloudformation describe-stacks --query 'Stacks[0].[Outputs[].[OutputKey,OutputValue]]|[]' --output table --stack-name CognitoSimpleExample",

↓↓以下のように編集↓↓

"cfn-describe": "aws cloudformation describe-stacks --query \"Stacks[0].[Outputs[].[OutputKey,OutputValue]]|[]\" --output table --stack-name CognitoSimpleExample",

エスケープに注意です。

再度 npm run cfn-describe を実行します。

▼実行結果

PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> npm run cfn-describe

> cognito-simple-example-for-external-idp@1.0.0 cfn-describe
> aws cloudformation describe-stacks --query "Stacks[0].[Outputs[].[OutputKey,OutputValue]]|[]" --output table --stack-name CognitoSimpleExample

---------------------------------------------------------
|                    DescribeStacks                     |
+------------------------+------------------------------+
|  CognitoUserPool       |  ap-northeast-1_xxxxxxxxx    |
|  CognitoUserPoolClient |  13lmsuxxxxxxxxxxxxxxxxxxxx  |
|  CognitoRegion         |  ap-northeast-1              |
+------------------------+------------------------------+

PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> 

この結果は後で使うのでメモしておいてください。

続いてもとの記事に沿ってマネジメントコンソールで作業します。
Cognito ユーザープールのマネジメントコンソール画面を開くと、CognitoSimpleExampleUsers という名前のユーザープールができているので開きます。

[アプリケーションの統合]タブ - [アクション] - [Cognito ドメインの作成] をクリック

任意のドメインプレフィックスを入力します。小文字、英数字、ハイフンのみ使用でき、
awsamazoncognito という文字列を含むことはできないので注意してください。

ドメインプレフィックスは後で使うのでメモしておいてください。

/public/js/amplifyConfig.js.example ファイルをコピーして /public/js/amplifyConfig.js にリネームします。

メモしておいた CognitoUserPoolCognitoUserPoolClientCognitoDomainPrefix
を入力してください。

/public/js/amplifyConfig.js
let CognitoRegion = 'ap-northeast-1';
let CognitoUserPool = 'ap-northeast-1_xxxxxxxxx';
let CognitoUserPoolClient = '13lmsuxxxxxxxxxxxxxxxxxxxx';

let CognitoDomainPrefix = 'emiki-test';

let amplifyConfig = {
    Auth: {
        region: CognitoRegion,
        userPoolId: CognitoUserPool,
        userPoolWebClientId : CognitoUserPoolClient,
        oauth: {
            domain: `${CognitoDomainPrefix}.auth.${CognitoRegion}.amazoncognito.com`,
            scope: ['openid'],
            redirectSignIn: 'http://localhost:3000',
            redirectSignOut: 'http://localhost:3000',
            responseType: 'code'
        }
    }
};

次に、ローカルで express サーバーを動かすために、次のコマンドを実行して node パッケージをインストールしてください。

npm install --production

▼実行結果(42秒程度)

PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> npm install --production
npm WARN config production Use `--omit=dev` instead.
npm WARN old lockfile
npm WARN old lockfile The package-lock.json file was created with an old version of npm,
npm WARN old lockfile so supplemental metadata must be fetched from the registry.
npm WARN old lockfile
npm WARN old lockfile This is a one-time fix-up, please be patient...
npm WARN old lockfile

added 65 packages, and audited 66 packages in 42s

found 0 vulnerabilities
PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> 

次のコマンドを実行して、待機状態になれば成功です。

npm start

▼実行結果

PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> npm start

> cognito-simple-example-for-external-idp@1.0.0 start
> node server.js

Node.js is listening to PORT:3000

http://localhost:3000 でアクセスできるローカルサーバーができました。
Google Chrome のブラウザバーで、http://localhost:3000 と入力してアクセスすると、以下のような画面になります。

「Sign In / Sigh Up」をクリックすると、以下認証画面になります。「Sigh Up」をクリックして サインインユーザーを作成します。

受信可能なメールアドレスとパスワードを入力します。

以下「Confirm your account」画面になり、メールアドレス宛に認証コードが送付されます。この画面は開いたままにしておきます。

別タブでメールを確認すると、認証コードが届いています。

「Confirm your account」画面に戻り、認証コードを入力して「Confirm account」をクリックします。

ユーザー認証が完了し、Cognito の発行したトークンがベロっと画面に表示されるというアプリケーションです。

「Sign Out」をクリックすると戻ります。

VScode はターミナルで「Ctr + C」を押下すると バッチ ジョブを終了しますか (Y/N)? と表示されるので、Y を押下して待ち受けを終了します。

PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> npm start

> cognito-simple-example-for-external-idp@1.0.0 start
> node server.js

Node.js is listening to PORT:3000
バッチ ジョブを終了しますか (Y/N)? Y
PS C:\Users\kitani.emi\Documents\cognito-simple-example-for-external-idp> 

余談:AWS WAF マネージドルール「AWS WAF 不正防止アカウント乗っ取り防止 (ATP)」では Cognito が利用できない

実は、AWS WAF マネージドルール「AWS WAF 不正防止アカウント乗っ取り防止 (ATP)」で CAPTCHA アクションができるか検証したくて GUI で動くテスト用認証機能がほしいな、と思い、Cognito で試したところ、「AWS WAF 不正防止アカウント乗っ取り防止 (ATP)」では Cognito が利用できなかった…というオチです。

ドキュメントを読むべきですね。
https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/waf-atp.html

終わり。

Discussion