【ALB+Cognito+Flask】Webアプリ上で認証されたユーザー情報を取得する方法

記事タイトルとURLをコピーする

こんにちは。AWS CLIが好きな福島です。

はじめに

Webアプリを実装する際に、ALB+Cognitoを使って認証機能を実装しつつ、 Web上にユーザー情報を表示させたり、アプリ側でユーザー情報を基に操作を制御(認可)したいケースがあるかと思います。

そこで今回は、ALB+Cognito+Flaskの構成でユーザー情報を取得する方法をご紹介いたします。
※Flaskとは、PythonのWebフレームワークになります。

参考情報

https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/listener-authenticate-users.html

構成図

今回の検証における構成図は、以下の通りになります。

Webアプリ上でユーザー情報を取得する方法

Webアプリ上でユーザー情報を取得するには、ALBからのリクエストに含まれるヘッダーを取得します。

ざっくりとした流れは以下の通りです。

  • ①Webアプリ上でALBからのリクエストヘッダーを取得
  • ②ヘッダーの検証
  • ③ヘッダーのデコード

ユーザー情報を確認できるALBのリクエストヘッダー

ユーザー情報を確認できるALBのリクエストヘッダーは、以下の2つがあります。

x-amzn-oidc-accesstoken(Cognitoが発行)

トークンエンドポイントからのアクセストークン   

x-amzn-oidc-data(ALBが発行)

ユーザークレーム (JSON ウェブトークン (JWT) 形式)

補足

ユーザーが所属するグループ情報は、x-amzn-oidc-accesstokenからしか取得できないため、基本的にはこのデータを使うことが多いのかなと思います。

ポイント

どのサービスが発行したデータなのか(ALB or Cognito)

セキュリティの観点からWebアプリで受け取ったリクエストヘッダーは、想定している発行元から払い出されたデータなのか、検証することが多いかと思います。

そのため、どのサービスが発行したデータなのかを意識する必要があります。

ユーザーが所属するグループ情報が含まれているか

Webアプリ上で操作を制御(認可)したい場合、ユーザー名よりユーザーが所属するグループ名を使いたいケースが多いと思います。 しかし、x-amzn-oidc-dataからは、ユーザー情報しか取得できないため、 グループ情報を取得したい場合は、x-amzn-oidc-accesstokenを確認する必要があります。

検証

ここからは検証として、実際にALBからのリクエストヘッダーを覗いてみたいと思います。

前提

  • DNSを管理していること
  • ACMで証明書を発行済みであること

Git Clone

GitからソースコードをCloneします。

git clone https://github.com/kazuya9831/blog-sample.git
cd blog-sample

samconfig.tomlの更新

samconfig.tomlの更新します。

vi alb-cognito-flask/samconfig.toml
version = 0.1
[default.deploy.parameters]
stack_name = "alb-cognito-flask"
resolve_s3 = true
s3_prefix = "alb-cognito-flask"
region = "ap-northeast-1"
capabilities = "CAPABILITY_IAM"
parameter_overrides = [
    "ApplicationName=alb-cognito-flask",
    "AllowSourceIp=xxx.xxx.xxx.xxx/xx",
    "DNSNameForALB=xxxx",
    "ACMArn=xxxxx",
    "VpcCIDR=192.168.0.0/24",
    "PublicSubnet1CIDR=192.168.0.0/27",
    "PublicSubnet2CIDR=192.168.0.32/27"
]
image_repositories = []

変更する値は、以下の3点です。

  • AllowSourceIp
    ALBにアクセス可能なIPを設定します。

  • DNSNameForALB
    払い出している証明書にマッチしたFQDNを指定します。

  • ACMArn
    ACMのARNを指定します。

リソースのデプロイ

cd alb-cognito-flask
sam build
sam deploy

Cognito Userの作成

cognito_user_pool_id=$(aws cloudformation describe-stacks \
--stack-name alb-cognito-flask \
--query "Stacks[].Outputs[?OutputKey=='CognitoUserPoolId'].OutputValue" \
--output text)
python tools/setup_cognito_user_and_group.py ${cognito_user_pool_id} tools/cognito_user_and_group.csv

DNS設定

以下のコマンドの実行結果を基にDNSにレコードを設定します。

aws cloudformation describe-stacks \
--stack-name alb-cognito-flask \
--query "Stacks[].Outputs[?OutputKey=='DNSNameForALB' || OutputKey=='ALBFQDN'].OutputValue" \
--output text

DNSにレコードを登録する方法は割愛します。

動作確認

ブラウザからDNSレコードに登録したエンドポイントにアクセスします。 アクセスすると、CognitoのホストUIの画面にリダイレクトされ、以下の画面が表示されると思います。

Cognitoには以下のユーザーを作成しているので、好きなユーザーでアクセスします。

  • TestUser-1 (adminグループに所属)
  • TestUser-2 (generalグループに所属)
    ※パスワードはユーザー名と同一です。

認証が通り、以下のような画面が表示されればOKです。

上記は項目名通り、X-Amzn-Oidc-AccesstokenまたはX-Amzn-Oidc-Dataから取得したユーザー情報を表示させています。

Request Headersには、ALBから送られてきたリクエストヘッダーを全て表示させています。

X-Amzn-Oidc-Accesstokenには、デコード前のデータを表示し、 X-Amzn-Oidc-Accesstoken(decode)には、デコード後のデータを表示しています。

1番上に表示していたユーザーおよびグループ名は、赤枠の部分から取得しています。

X-Amzn-Oidc-Dataには、デコード前のデータを表示し、 X-Amzn-Oidc-Data(decode)には、デコード後のデータを表示しています。

1番上に表示していたユーザー名は、赤枠の部分から取得しています。 このデータからX-Amzn-Oidc-Data(ALBが発行)には、グループ情報が含まれていないことが分かるかと思います。

終わりに

今回は、ALB+Cognito+Flaskで認証されたユーザー情報を取得する方法をご紹介いたしました。 どなたかのお役に立てれば幸いです。

福島 和弥 (記事一覧)

2019/10 入社

AWS CLIが好きです。