0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS Cognito認証をサクッとPythonのみで動作確認する(Backend)

Last updated at Posted at 2024-11-03

背景

私は普段、マイクロサービス開発しているバックエンドエンジニアです。
この度、フロントエンドの画面ができていない状態で、バックエンド単体で認証・認可周りの動作確認をすることになりました。この記事では、AWSマネジメントコンソールと簡単なPythonスクリプトだけで、Cognito認証の動作確認を行う方法をメモいたします。

認証フローのイメージ

こちらは、Cognito認証フローの超ざっくりとしたイメージです。

  • 最初にユーザーはConitoに対しEmail/Passwordでログインします
  • ログインするとユーザーは、CognitoからIdTokenを発行されます
  • ユーザーはトークンをBackend APIに投げます
  • Backend APIは、ユーザーからもらったトークンを、Cognitoからもらった公開鍵で復号します
  • Backend APIは、復号したJsonから正しいユーザーの値が取得できているか確認します

image.png

詳しく知りたい方は、下記のOpenID Connectの書籍がオススメ

手順

動作確認手順は下記の通りとなります。

  • 1. AWSマネジメントコンソールでCognitoのユーザープールを生成する
  • 2. ユーザープールのID/パスワードログインを有効にする
  • 3. Hosted UIを利用して初回ログインする
  • 4. curlコマンドを利用して認証する
  • 5. Pythonのサンプルコードに認証結果のIdTokenを貼り付けて、ユーザー情報を復号できることを確認する

1. AWSマネジメントコンソールでCognitoのユーザープールを生成する

初めに、AWSマネジメントコンソールからCognitoのユーザープールを新規作成します。このあたりは要点のみ記載していますので、詳しい方法は他記事も参考にしてください。

  • Cognito ユーザープールのサインインオプション

    • ユーザー名
    • E メール
  • ユーザー名の要件

    • ユーザーが任意のユーザー名でサインインすることを許可
    • ユーザー名の大文字と小文字を区別する
  • 多要素認証

    • MFAなし
  • ユーザーアカウントの復旧

    • セルフサービスのアカウントの復旧は無効にしてください
    • (今回はテスト検証なので、EmailやSMSの設定が面倒なため)
      多要素認証の設定..png
  • Eメール

    • CognitoでEメールを送信を選択
      Eメールの設定.png
  • ユーザープール名

    • 適当な名前でOK(例: test-user-pool)
  • ホストされた認証ページ

    • Cognito のホストされた UI を使用にチェック
      ホストされたUI.png
  • 最初のアプリケーションクライアント

    • パブリッククライアント
    • クライアントのシークレットを生成しない
    • アプリケーションのクライアント名
      • 適当な名前でOK(例: test-app)

これにてユーザープールの作成が完了です。

2. ユーザープールのID/パスワードログインを有効にする

作成したユーザープールの画面に移動します。今回は、test-user-poolという名前で作成されています。
次に、ID/パスワードでログインできるように設定します。

  • ユーザープールの画面で、「アプリケーションの統合」タブをクリックし、一番下までスクロールします。
    image.png

  • すると、アプリケーションクライアントのリストに先ほど作成したtest-appという名前があるのでクリックします。
    ユーザープールアプリケーションクライアントのリスト.png

アプリケーションクライアント: test-app の画面の右上にある、「編集」ボタンをクリックします

  • 認証フローの「ALLOW_UESR_PASSWORD_AUTH」をクリックして有効化します。
    ユーザープール_認証方法の設定..png
  • 「変更を保存」ボタンを押して完了です

3. Hosted UIを利用して初回ログインする

テストユーザーを作成する

ユーザーを作成しログインまでを行います。本来はフロントで実装されるフローですが、今回は、CognitoのHosted UIを利用します。

  • 作成したユーザープールの画面に移動します。ユーザータブから、ユーザーを作成ボタンをクリックします。
    image.png
    • ユーザー情報は下記にします
      • サインインに使用されるエイリアス属性
        • Eメールにチェック
      • ユーザー名: test-user
      • Eメールアドレス: test-user@example.com
      • 仮パスワード: User1234!
        image.png
    • 「ユーザーを作成」ボタンを押し、完了です。

Hosted UIを利用できるように設定する

  • ユーザープールの画面で、「アプリケーションの統合」タブをクリックし、ドメインの「アクション」ボタンを押下、Cognitoドメインの作成を選択します
    image.png
    • ドメイン名は適当な名前でOKです(今回は、backend-testという名前にしました)
    • 再度、アプリケーションクライアントのリストに移動し、test-appをクリックします。
      ユーザープールアプリケーションクライアントのリスト.png
  • ホストされたUIの項目で、ステータスが「使用不可」になっていますので、「編集」ボタンをクリックします。
    image.png
  • ホストされたUIを編集
    • URL (適当でOK)
    • ID プロバイダー: Cognitoユーザープール
    • OAuth 2.0 許可タイプ: 認証コード付与
    • OpenID Connect のスコープ: OpenID
  • このように設定して、変更を保存します
    image.png
  • そうすると、「ホストされたUIを表示」ボタンが有効になります

Hosted UIでログインする

  • 先程の、AWSマネジメントコンソールの画面で「ホストされたUIを表示」ボタンを押すと、下記のような初回ログイン画面が表示されます。

    • ここにEmail, 仮パスワードを入れます(これらは、先ほどAWSマネジメントコンソールで設定した値です)
  • するとチェンジパスワード画面が出てきますが、今回は同じパスワードを使いまわします(セキュリティ的にアレですが、動作確認なので...)

  • 「このサイトにアクセスできません」と表示されれば成功です。

    • localhost:8000に飛んでいますが、フロントの画面は無いので大丈夫。
      image.png
      これで、test-userにログインした状態となりました!

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!"
    }
}
'
  • 備考
    • USERNAME, PASSWORDはさっき設定したものを入力
    • クライアントIDはAWSマネジメントコンソールから拝借します
      • 添付画像のクライアントIDは使用できませんので悪しからず
      • image.png

こんな感じの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)

(※ 上記のコードは、こちらの記事を引用しました。)

出力結果

ユーザー情報を復号できていますね :smile: (にっこり)

復号成功!
{'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ハンズオンとして、下記の記事も参考になりました

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?