背景
私は普段、マイクロサービス開発しているバックエンドエンジニアです。
この度、フロントエンドの画面ができていない状態で、バックエンド単体で認証・認可周りの動作確認をすることになりました。この記事では、AWSマネジメントコンソールと簡単なPythonスクリプトだけで、Cognito認証の動作確認を行う方法をメモいたします。
認証フローのイメージ
こちらは、Cognito認証フローの超ざっくりとしたイメージです。
- 最初にユーザーはConitoに対しEmail/Passwordでログインします
- ログインするとユーザーは、CognitoからIdTokenを発行されます
- ユーザーはトークンをBackend APIに投げます
- Backend APIは、ユーザーからもらったトークンを、Cognitoからもらった公開鍵で復号します
- Backend APIは、復号したJsonから正しいユーザーの値が取得できているか確認します
詳しく知りたい方は、下記のOpenID Connectの書籍がオススメ
手順
動作確認手順は下記の通りとなります。
- 1. AWSマネジメントコンソールでCognitoのユーザープールを生成する
- 2. ユーザープールのID/パスワードログインを有効にする
- 3. Hosted UIを利用して初回ログインする
- 4. curlコマンドを利用して認証する
- 5. Pythonのサンプルコードに認証結果のIdTokenを貼り付けて、ユーザー情報を復号できることを確認する
1. AWSマネジメントコンソールでCognitoのユーザープールを生成する
初めに、AWSマネジメントコンソールからCognitoのユーザープールを新規作成します。このあたりは要点のみ記載していますので、詳しい方法は他記事も参考にしてください。
-
Cognito ユーザープールのサインインオプション
- ユーザー名
- E メール
-
ユーザー名の要件
- ユーザーが任意のユーザー名でサインインすることを許可
- ユーザー名の大文字と小文字を区別する
-
多要素認証
- MFAなし
-
ユーザーアカウントの復旧
-
Eメール
-
ユーザープール名
- 適当な名前でOK(例:
test-user-pool
)
- 適当な名前でOK(例:
-
ホストされた認証ページ
-
最初のアプリケーションクライアント
- パブリッククライアント
- クライアントのシークレットを生成しない
- アプリケーションのクライアント名
- 適当な名前でOK(例: test-app)
これにてユーザープールの作成が完了です。
2. ユーザープールのID/パスワードログインを有効にする
作成したユーザープールの画面に移動します。今回は、test-user-pool
という名前で作成されています。
次に、ID/パスワードでログインできるように設定します。
アプリケーションクライアント: test-app の画面の右上にある、「編集」ボタンをクリックします
3. Hosted UIを利用して初回ログインする
テストユーザーを作成する
ユーザーを作成しログインまでを行います。本来はフロントで実装されるフローですが、今回は、CognitoのHosted UIを利用します。
- 作成したユーザープールの画面に移動します。ユーザータブから、ユーザーを作成ボタンをクリックします。
- ユーザー情報は下記にします
- サインインに使用されるエイリアス属性
- Eメールにチェック
- ユーザー名: test-user
- Eメールアドレス: test-user@example.com
- 仮パスワード: User1234!
- サインインに使用されるエイリアス属性
- 「ユーザーを作成」ボタンを押し、完了です。
- ユーザー情報は下記にします
Hosted UIを利用できるように設定する
- ユーザープールの画面で、「アプリケーションの統合」タブをクリックし、ドメインの「アクション」ボタンを押下、Cognitoドメインの作成を選択します
- ホストされたUIの項目で、ステータスが「使用不可」になっていますので、「編集」ボタンをクリックします。
- ホストされたUIを編集
- URL (適当でOK)
- ID プロバイダー: Cognitoユーザープール
- OAuth 2.0 許可タイプ: 認証コード付与
- OpenID Connect のスコープ: OpenID
- このように設定して、変更を保存します
- そうすると、「ホストされたUIを表示」ボタンが有効になります
Hosted UIでログインする
-
先程の、AWSマネジメントコンソールの画面で「ホストされたUIを表示」ボタンを押すと、下記のような初回ログイン画面が表示されます。
- ここにEmail, 仮パスワードを入れます(これらは、先ほどAWSマネジメントコンソールで設定した値です)
- Username: test-user@example.com
- Password: User1234!
- ここにEmail, 仮パスワードを入れます(これらは、先ほどAWSマネジメントコンソールで設定した値です)
-
するとチェンジパスワード画面が出てきますが、今回は同じパスワードを使いまわします(セキュリティ的にアレですが、動作確認なので...)
-
「このサイトにアクセスできません」と表示されれば成功です。
4. curlコマンドを利用して認証する
ログイン後、バックエンドで検証するためのトークンをもらわないといけないので、Cognito-APIにcurlでリクエストを飛ばします。
注意) Windowsユーザーは、WSLを使ってください。PowerShell,コマンドプロントだとうまくcurlできないよ
curl --location --request POST 'https://cognito-idp.ap-northeast-1.amazonaws.com/' --header 'Content-Type: application/x-amz-json-1.1' --header 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' --data-raw '
{
"ClientId": "75fcnhmtiimj0stoaso6dribsg",
"AuthFlow": "USER_PASSWORD_AUTH",
"AuthParameters":
{
"USERNAME": "test-user@example.com",
"PASSWORD": "User1234!"
}
}
'
こんな感じのJSONが返ってきたら成功です!
{
"AuthenticationResult": {
"AccessToken": "XXXXX",
"ExpiresIn": 3600,
"IdToken": "ZZZZZZZZ",
"RefreshToken": "XXXXX",
"TokenType": "Bearer"
},
"ChallengeParameters": {}
}
6. Pythonのサンプルコードに認証結果のIdTokenを貼り付けて、ユーザー情報を復号できることを確認する
最後にトークンの復号を試します。下記のサンプルコードをローカルで実行します。
- token, user_pool_id, client_id は各自値を設定してください
import jwt
# 先ほど取得したIDトークンを貼り付ける
token = 'ZZZZZZZZ'
region = 'ap-northeast-1'
user_pool_id = 'ap-northeast-1_D0Ardyf8e' # AWSマネジメントコンソールからコピー
client_id = '75fcnhmtiimj0stoaso6dribsg' # AWSマネジメントコンソールからコピー
issuer = f'https://cognito-idp.{region}.amazonaws.com/{user_pool_id}'
jwks_url = f'{issuer}/.well-known/jwks.json'
jwks_client = jwt.PyJWKClient(jwks_url)
signing_key = jwks_client.get_signing_key_from_jwt(token)
token = jwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
audience=client_id,
issuer=issuer
)
if token['token_use'] != 'id':
raise Exception('Invalid token_use')
print("復号成功!")
print(token)
(※ 上記のコードは、こちらの記事を引用しました。)
出力結果
ユーザー情報を復号できていますね (にっこり)
復号成功!
{'sub': '87246a48-80e1-7000-fc65-0dc36d3852e7', 'email_verified': True, 'iss': 'https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_D0Ardyf8e', 'cognito:username': 'test-user', 'origin_jti': 'e1b85621-1692-4dbc-9d01-a734e9f94ef5', 'aud': '75fcnhmtiimj0stoaso6dribsg', 'event_id': '08bd6dd6-e030-4be6-9c74-2b67cac0dd2c', 'token_use': 'id', 'auth_time': 1730605969, 'exp': 1730609569, 'iat': 1730605969, 'jti': '26219b34-0993-4435-917e-4b5ddc58d949', 'email': 'test-user@example.com'}
まとめ
今回はAWSマネジメントコンソールを使って、サクッとバックエンドでの認証の動作確認を行いました。FastAPIのアプリにちゃんと組み込む際は、下記の公式ドキュメントを参照すると良さそうですね。
Cognitoハンズオンとして、下記の記事も参考になりました