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でデバイス認可フローの実装を確認する

Last updated at Posted at 2025-03-02

1. はじめに

ChatBot は、ユーザーとの対話を自動化する技術として、カスタマーサポートや社内問い合わせシステム、パーソナルアシスタントなど、さまざまな用途で利用されている。特に OpenAI の Realtime API を活用することで、より リアルタイムかつ自然な対話 を実現できるようになった。

一方で、ChatBot を運用する際に重要となるのが ユーザー認証 だ。特に スマートデバイスや IoT 端末、組み込み機器 などでは、パスワード入力が難しく、従来の認証方法が使いにくいケースがある。このような課題を解決する手段として、デバイス認可フロー(OAuth 2.0 Device Authorization Grant)が有効です。

前回の記事では Amazon ECS 上で OpenAI Realtime API を活用した ChatBot に Cognito も用いたユーザー認証を実装したが、今回はさらにデバイス認可フローを導入する方法 について確認する。これにより、ユーザーは スマートフォンやPCを使って簡単に認証を行い、ChatBot へのアクセスが可能になる ため、利便性とセキュリティの両立が実現できる。

前回の記事:

2. AWSでデバイス認可フローの実装する例を確かめる

Amazon Cognito と AWS Lambda を使って OAuth 2.0 デバイスフローを実装するのサンプルを用いてデバイス認可フローの実装方法について確認する。

(1) デバイス認可フローの概要

image.png

(2) スタックの作成

[ステップ 2: CloudFormation テンプレートを使って実装をデプロイする][Launch Stack] からスタックの作成を開始する

image.png

(3) スタックのクイック作成

スタックのクイック作成 でパラメータを設定する

パラメータ名 説明
スタック名 任意の名称
ACertificateARN ACMで作成した証明書のARN
ACognitoDomain Route53でレコードを作成したドメインで任意の名称。親ドメインのIPアドレスが設定されていなければエラーになるので、親ドメインのタイプAに 127.0.0.1 などのダミーを設定しておく
ACredsEmail 自分が受け取れる任意の email アドレス
AFullyQualifiedDomainName (FQDN) テストサービスを行うドメイン名
ResultTokenSet ID+ACCESS+REFRESH に変更すると ID_TOKEN も取得可能

image.png

AWS CloudFormationによってIAMリソースが... のチェックマークを入れて スタックの作成 を選択する。

image.png

###トラブルシューティング

Amazon Cognito カスタムドメインを作成するには、親ドメインに DNS A レコードが必要である。この設定がないと Cognito のカスタムドメインの作成に失敗する。ダミーで良いので 親ドメインに DNS A レコード を設定すれば解決する。

(4) 設定を完了させる

  • CloudFormation コンソール 内の Stacks ページで、作成したスタックをクリック
  • 出力タブを開く
  • ALBCNAMEForDNSConfiguration を確認する

image.png

キー 値 (一部マスク済み) 説明
ALBCNAMEForDNSConfiguration ***--Devic-**********.us-east-1.elb.amazonaws.com DNS を ALB のエンドポイントに向けるための CNAME
DeviceCognitoClientClientID 78n4qk************* 認可サーバーとやり取りするためにシミュレートされたデバイスが使用する App クライアント ID
DeviceCognitoClientClientSecret 15r0jp1g********************************** 認可サーバーとやり取りするためにシミュレートされたデバイスが使用する App クライアントシークレット
TestEndPointForDevice https://**********/token シミュレートされたデバイスがリクエストを行うための HTTPS エンドポイント
TestEndPointForUser https://**********/device ユーザーがリクエストを行うための HTTPS エンドポイント
UserPassword 登録されたメールアドレスに送信 テスト用 Cognito ユーザーのパスワード
UserUserName *********@**********.com テスト用 Cognito ユーザーのユーザー名

ALB の DNS を設定

スタックが構築された後、利用する FQDN に対する DNS ゾーン内の DNS CNAME エントリが Application Load Balancer (ALB) の DNS 名を指すようにして設定を完了させる

  1. ALBCNAMEForDNSConfiguration キーの値をコピー
  2. Route53でDNS ゾーン内の CNAME DNS エントリをこの値に設定する。Route 53 で DNS ゾーン内に Application Load Balancer を指す CNAME エントリを作成する

設定後に30秒ほど待つと TLS を使って作成したドメイン名でALBにアクセスできる

IDトークン を取得する設定

Lamdaのコンソールで自動作成された関数 DeviceGrant-token を選択する

[設定] タブで環境変数を 編集する

image.png

RESULT_TOKEN_SET を追加する。ID+ACCESS+REFRESH を指定することで、アクセストークンだけでなくIDトークンを同時に取得する

環境変数
RESULT_TOKEN_SET ID+ACCESS+REFRESH

3. デバイス認可フローでトークンを取得する

トークン取得の全体像を確認する。図の黄色の長方形の箇所が curl コマンドや ウェブブラウザ でサーバーにアクセスする箇所になる。

image.png

CloudFormation コンソール 内の Stacks ページの [出力] で確認できる次の2つのキー使って確認を進める

キー 値 (一部マスク済み)
DeviceCognitoClientClientID 2m5a9b*************
DeviceCognitoClientClientSecret 2m5a9b*************

json形式のアウトプットを読みやすくするために、あらかじめ jq コマンドを用意しておく

Macの場合
brew install jq

トークンの取得

(1) パラメータを設定する

CLIENT_ID=2m5a9b*************
CLIENT_SECRET_ID=2m5a9b*************
ALB=<ALBのDNA名>

(2) デバイスコードとユーザーコードを取得する

CODE=`curl  -s -X POST "https://${ALB}/token?client_id=${CLIENT_ID}" \
     -H "User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)" \
     -H "Authorization: Basic $(echo -n ${CLIENT_ID}:${CLIENT_SECRET_ID} | base64)" | jq`
echo $CODE
DEVICE_CODE=`echo $CODE | jq -r .device_code`
echo $DEVICE_CODE
出力例
{
    "device_code": "wLGgw9XnE**********",
    "user_code": "J2MVP***",
    "verification_uri": "https://**********/device",
    "verification_uri_complete": "https://**********/device?code=J2MVP***&authorize=true",
    "interval": 5,
    "expires_in": 1800
}

(3) 認証URLを開き、ユーザーコードを入力してサインインする

  1. 表示された認証URLを開く
  2. ユーザーコードを入力
  3. Amazon Cognito へのログイン

ブラウザで、 verification_uri にアクセスします。

ログインしていない場合にはユーザー名とパスワードでログイン

image.png

image.png

ここでエラーが表示される場合には今回のサイトに関連するブラウザのCookieをすべて削除してから再度アクセスしてログインし直せば良い・

再度 verification_uri にブラウザでアクセスして user_code を入力し Authorize を選択する

image.png

成功すると下記の表示がされる

image.png

(4) トークン を取得する

TOKENS=`curl -s -X POST "https://${ALB}/token?client_id=${CLIENT_ID}&device_code=${DEVICE_CODE}&grant_type=urn:ietf:params:oauth:grant-type:device_code" \
  -H "User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)" \
  -H "Host: ${ALB}" \
  -H "Authorization: Basic $(echo -n ${CLIENT_ID}:${CLIENT_SECRET_ID} | base64)" | jq`
echo $TOKENS
アウトプット例
{
  "id_token": "eyJ***************************",
  "access_token": "eyJ***************************",
  "refresh_token": "eyJ***************************",
  "expires_in": 3600
}

IDトークン、アクセストークンとリフレッシュトークンの取得を確認した。
IDトークン を取得する設定 を忘れると IDトークンは取得できないので注意

(5) id_token と access_token を環境変数に設定しておく

ID_TOKEN=`echo $TOKENS | jq -r .id_token`
ACCESS_TOKEN=`echo $TOKENS | jq -r .access_token`

4. トークンを使ってサービスにアクセスする

テスト用に Hello World アプリ を用意して、そのサービスにトークンを使ってアクセスする

(1) Hello World Lamda 関数 を作成

Lamdaのコンソールで [関数を作成] する

image.png

次の設定値で関数を作成する

設定 設定値
関数の作成 一から作成
関数名 helloworld
ランタイム Python 3.9
アーキテクチャ arm64

[関数の作成] を選択し作成する

(2) API Gateway の作成

API Gateway のコンソールからREST APIを作成する

image.png

a. オーソライザーの設定

[オーソライザー] -「[オーソライザーの作成] を選択する

image.png

次の設定値でオーソライザーを作成する

項目 設定値
オーソライザー名 任意の名称
オーソライザーのタイプ Cognito
Cognito ユーザープール 自動作成されたユーザープール
トークンのソース Authorization

image.png

b. Hello World Lamdaを割り当てる

作成したAPIの [リソース] のページで [メソッド作成] を選択する

image.png

次の設定値でメソッドを作成する

項目 設定値
メソッドタイプ ANY
統合タイプ Lambda
Lambda 関数 先ほど作成したLambda関数

image.png

c. メソッドリクエストの設定

作成したAPIの [リソース] ページで メソッドリクエストの設定[編集] する

image.png

次の設定値でメソッドリクエストの設定 を行う

項目 設定値
認可 オーソライザーの設定 で作成したオーソライザー名
リクエストバリデーター クエリ文字列パラメータ、およびヘッダーを検証

image.png

[保存] ボタンを選択し編集を保存する

d. APIのデプロイ

[APIをデプロイ] ボタンを選択してAPIをデプロイする

image.png

ステージ名は prod として デプロイ を選択する

image.png

デプロイしたAPIにアクセスするURL (URLを呼び出すのURL) を ステージprod のページで確認する

スクリーンショット 2025-03-02 12.26.23.png

(3) トークンを使ってAPIにアクセスする

先に確認したデプロイしたAPIにアクセスするURLを通してトークンを使って認証を確かめた。IDトークンで認証されるが、アクセストークンでは認証に失敗することを確認した。

トークンなし の場合

認証に失敗する

curl  -s  -X  GET  "https://example.com/prod"
出力例
{"message":"Unauthorized"}%    

アクセストークン の場合

認証に失敗する

curl  -s  -X  GET -H "Authorization: Bearer ${ACCESS_TOKEN}" "https://example.com/prod"
出力例
{"message":"Unauthorized"}%  

IDトークン の場合

認証に成功して Hello World Lamda関数が呼び出されたことが確認できる

curl  -s  -X  GET -H "Authorization: Bearer ${ID_TOKEN}" 
"https://example.com/prod"
出力例
{"statusCode": 200, "body": "\"Hello from Lambda!\""}%                                  

参考資料

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?