OP として AWS Cognito を使用してみます。
ここで言う「クライアント」は RP(Relying Party) を意味します。
■ ユーザー名 ■ Eメール
● MFA なし
追加の必須属性:name
● Cognito で Eメールを送信
ユーザープール名:example123 ■ CognitoのホストされたUIを使用 Cognitoドメイン:https://example123 ● 秘密クライアント アプリケーションクライアント名:my-app-01 認可されているコールバックURL:https://www.example.com/callback 高度なアプリケーションクライアントの設定 認証フロー:[ALLOW_USER_PASSWORD_AUTH] を追加 OpenID Connect のスコープ:[電話番号] を削除、[プロファイル] を追加
作成したユーザープール名をクリックして下記を確認します。
ユーザープールID:ap-northeast-1_nRedrVEYM
[アプリケーションの統合] をクリックして下記を確認します。
Cognito ドメイン:https://example123.auth.ap-northeast-1.amazoncognito.com
アプリケーションクライアント名をクリックして下記を確認します。
クライアントID:58mli5ubjefrok4j31glbkjovo クライアントシークレット:ajvj5nn2vl59kn2il73cis5dafgh8rc32dp1rnc9gto0jidennq
リージョン名とユーザープールIDを用いて関連情報を確認することができます。これは OpenID Connect Discovery 1.0(↗) という仕様で定義されています。
curl https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_nRedrVEYM/.well-known/openid-configuration { "issuer": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_nRedrVEYM", "authorization_endpoint": "https://example123.auth.ap-northeast-1.amazoncognito.com/oauth2/authorize", "token_endpoint": "https://example123.auth.ap-northeast-1.amazoncognito.com/oauth2/token", "revocation_endpoint": "https://example123.auth.ap-northeast-1.amazoncognito.com/oauth2/revoke", "end_session_endpoint": "https://example123.auth.ap-northeast-1.amazoncognito.com/logout", "userinfo_endpoint": "https://example123.auth.ap-northeast-1.amazoncognito.com/oauth2/userInfo", "jwks_uri": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_nRedrVEYM/.well-known/jwks.json", "response_types_supported": [ "code", "token" ], "scopes_supported": [ "openid", "email", "phone", "profile" ], "id_token_signing_alg_values_supported": [ "RS256" ], "subject_types_supported": [ "public" ], "token_endpoint_auth_methods_supported": [ "client_secret_basic", "client_secret_post" ] }
作成したユーザープールにユーザを追加します。
ユーザー名:yamada Eメールアドレス:yamada@example.com ■ Eメールアドレスを検証済みとしてマークする パスワード:***********
検証用のコンテナを作成してログインします。
docker run -dit --name oidc-test -p 443:443 almalinux:9 docker exec -it oidc-test /bin/bash
コンテナ内でアプリを作成します。
cd dnf -y update dnf -y install git python3-pip git clone https://github.com/curityio/example-python-openid-connect-client.git cd ./example-python-openid-connect-client pip3 install -r ./requirements.txt
settings.json を次のように書き換えます。
{ "issuer": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_nRedrVEYM/", "port": 443, "base_url": "https://www.example.com", "verify_ssl_server": false, "debug": true, "scope": "openid profile email", "send_parameters_via": "query", "client_id": "58mli5ubjefrok4j31glbkjovo", "client_secret": "ajvj5nn2vl59kn2il73cis5dafgh8rc32dp1rnc9gto0jidennq", "redirect_uri": "https://www.example.com/callback" }
SSL証明書を作成します。server's hostname に www.example.com などの FQDN を指定してください。
mkdir ./cert cd ./cert openssl genrsa 2048 > server.key openssl req -new -key server.key > server.csr cat server.csr | openssl x509 -req -signkey server.key > server.crt cd ..
app.py の最後の1行を書き換えます。
_app.run('0.0.0.0', debug=debug, port=port, ssl_context=('./cert/server.crt', './cert/server.key'))
app.py を起動します。
python3 -B ./app.py
https://www.example.com にアクセスし、[Sign In] ボタンを押すと Cognito のログイン画面が表示されます。ログインするとパスワードの変更を求められ、パスワード変更するとサンプル画面にログインすることができます。
OpenID Connect の認証フローでは、Authorization Code Flow や Implicit Flow などいくつかの処理フローが定義されていますが、最もよく利用される Authorization Code Flow の流れを下記に示します。下記の例では ID/パスワードによる認証の例を示していますが、認証は MFA を用いたりなど OP の実装にまかされます。
GET https://www.example.com
HTTP/1.1 302 Found Location: https://example123.auth.ap-northeast-1.amazoncognito.com/oauth2/authorize ?scope=openid+profile+email &response_type=code &client_id=58mli5ubjefrok4j31glbkjovo &state=TH25QRQHJJC16YY7AKNS &code_challenge=Zfy2DA1iCm7v1bby0a_cs2bRVF6v-DMd0HNsaHbncR4 &code_challenge_method=S256 &redirect_uri=https://www.example.com/callback &nonce=097TREH1IZ5LRZ9F5MSN
GET https://example123.auth.ap-northeast-1.amazoncognito.com/oauth2/authorize ?scope=openid+profile+email &response_type=code &client_id=58mli5ubjefrok4j31glbkjovo &state=TH25QRQHJJC16YY7AKNS &code_challenge=Zfy2DA1iCm7v1bby0a_cs2bRVF6v-DMd0HNsaHbncR4 &code_challenge_method=S256 &redirect_uri=https://www.example.com/callback &nonce=097TREH1IZ5LRZ9F5MSN
HTTP/1.1 302 Found Location: https://example123.auth.ap-northeast-1.amazoncognito.com/login ?scope=openid+profile+email &response_type=code &client_id=58mli5ubjefrok4j31glbkjovo &state=TH25QRQHJJC16YY7AKNS &code_challenge=Zfy2DA1iCm7v1bby0a_cs2bRVF6v-DMd0HNsaHbncR4 &code_challenge_method=S256 &redirect_uri=https://www.example.com/callback &nonce=097TREH1IZ5LRZ9F5MSN
User は OP のログイン画面を開きます。
GET https://example123.auth.ap-northeast-1.amazoncognito.com/login ?scope=openid+profile+email &response_type=code &client_id=58mli5ubjefrok4j31glbkjovo &state=TH25QRQHJJC16YY7AKNS &code_challenge=Zfy2DA1iCm7v1bby0a_cs2bRVF6v-DMd0HNsaHbncR4 &code_challenge_method=S256 &redirect_uri=https://www.example.com/callback &nonce=097TREH1IZ5LRZ9F5MSN
OP は User にログイン画面を返却します。
HTTP/1.1 200 OK ※ログイン画面
POST https://example123.auth.ap-northeast-1.amazoncognito.com/login ?scope=openid+profile+email &response_type=code &client_id=58mli5ubjefrok4j31glbkjovo &state=TH25QRQHJJC16YY7AKNS &code_challenge=Zfy2DA1iCm7v1bby0a_cs2bRVF6v-DMd0HNsaHbncR4 &code_challenge_method=S256 &redirect_uri=https://www.example.com/callback &nonce=097TREH1IZ5LRZ9F5MSN username=yamada password=******
HTTP/1.1 302 Found Location: https://www.example.com/callback ?code=9979d435-50a9-43e2-b17f-e3be2e36eb8a &state=TH25QRQHJJC16YY7AKNS
GET https://www.example.com/callback ?code=9979d435-50a9-43e2-b17f-e3be2e36eb8a &state=TH25QRQHJJC16YY7AKNS
POST https://example123.auth.ap-northeast-1.amazoncognito.com/oauth2/token Content-Type: application/x-www-form-urlencoded client_id=58mli5ubjefrok4j31glbkjovo client_secret=ajvj5nn2vl59kn2il73cis5dafgh8rc32dp1rnc9gto0jidennq code=9979d435-50a9-43e2-b17f-e3be2e36eb8a code_verifier=OF6NR422P3P29J4DFV8G55F4HTFAIONTAR13BEUD72YDWFL0OPRJ0L6V5ZKCY9D3DFK6FY85MDIK9ZQVIRATGUU9EC01MYK2PVQA redirect_uri=https://www.example.com/callback grant_type=authorization_code
{ "id_token": "eyJraWQiOiIzUmFBWWZKRVwvY3NveXpmVDBlN1BtdTFmVjUzckxobVRsdXJiNEU4QmkrST0iLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiZTRzUWJ6aTgtTWNBb2pDV3VmbjNmdyIsInN1YiI6IjY3ODQxYWI4LWYwZTEtNzA2My03NmJmLWExNWI0MTExODNjMCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfblJlZHJWRVlNIiwiY29nbml0bzp1c2VybmFtZSI6InlhbWFkYSIsIm5vbmNlIjoiMDk3VFJFSDFJWjVMUlo5RjVNU04iLCJvcmlnaW5fanRpIjoiMTg5MGUzMWMtODY1NS00YTQ4LTllYTMtM2MxYTE1NjBhYzFmIiwiYXVkIjoiNThtbGk1dWJqZWZyb2s0ajMxZ2xia2pvdm8iLCJldmVudF9pZCI6ImQwNDg4NWZjLWJiZmMtNDIzZC05MzU0LWQ2NDc1ODY1ODJhZiIsInRva2VuX3VzZSI6ImlkIiwiYXV0aF90aW1lIjoxNzI3NTk0NDUwLCJuYW1lIjoieWFtYWRhIiwiZXhwIjoxNzI3NTk4MDUwLCJpYXQiOjE3Mjc1OTQ0NTAsImp0aSI6ImNjZGM5M2FjLTY3YWQtNDBmYi05MDFmLTU3YTQ0NjRhYmFkYyIsImVtYWlsIjoieWFtYWRhQGV4YW1wbGUuY29tIn0.i2445XrLKkyW1drQHQXOh598-UEB6SgpRZCgJsfu1hW-UPVWZqOGskEq6CC4VY533kDhpppqJGo-ZAfE1-CzLhzdYdmi5aov46pEJHNCAahjfjffgnNRBXtXCIROWEPh3YxEuncS4kMBKCz4oo0BiAE8T6OV591gGwGqOgRIRADcMrnn7WDiZK3xRwO5F6pViBMrdu6wPykHNXvdgZ7C_46TJozEc5CFaEiucYL1d14_3qxKvJ4NIygjH-oD_IwiiVhKquMbjms35gIauVOLZEpXgy4z_FCmQI5LEEoR5tdt90TpCM2bmJcxHn9s3nRfqvrxWIEnJ1arWdp_D4gLVg", "access_token": "eyJraWQiOiJNVmRpcUcxc2Y2UmhoRnViYmg3QnB1R3pQVE1rSDhXYjJcL2JHaGRzN1V4cz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI2Nzg0MWFiOC1mMGUxLTcwNjMtNzZiZi1hMTViNDExMTgzYzAiLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfblJlZHJWRVlNIiwidmVyc2lvbiI6MiwiY2xpZW50X2lkIjoiNThtbGk1dWJqZWZyb2s0ajMxZ2xia2pvdm8iLCJvcmlnaW5fanRpIjoiMTg5MGUzMWMtODY1NS00YTQ4LTllYTMtM2MxYTE1NjBhYzFmIiwiZXZlbnRfaWQiOiJkMDQ4ODVmYy1iYmZjLTQyM2QtOTM1NC1kNjQ3NTg2NTgyYWYiLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwiYXV0aF90aW1lIjoxNzI3NTk0NDUwLCJleHAiOjE3Mjc1OTgwNTAsImlhdCI6MTcyNzU5NDQ1MCwianRpIjoiMzg3YjQ2NDQtMGNhZC00OGVmLThmNGUtZWRhNThmYTg0M2M3IiwidXNlcm5hbWUiOiJ5YW1hZGEifQ.FsguU26nOyaGFQGf_2Fbb8WBFAfAZ8l1PMpR6avVQ5pCO0fU35VIYCaVoild3s9BBaPRz2xjF06xHPzUHIlZZ9y1_7t7Bsb407eTFUaMCO-ojOT_VEYfOzfAWD5cT4BuRqMUM-oTIr1oOFo_plDhI4RgPDjUUZiYHwcqOv9Aji1Gqh5KIOFM9uWWpSPFWqhVCzfALNw4Cj-bbAojEdEIIxTuAvpoxacCldPMsyZf6M0JeCXzdqkfYUSsGkwYMMmPNI0oQC4ykqdSXdE55voK10WWE85w0bQJ5MRrOwjYRsUi4NR3CK4BIU9zWNFz-5CRmd6QtKJ_77vpR3I5Ht1PbQ", "refresh_token": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.XLLiIZEJwk-EnoGT_Z-8j7QIPuHNPZoyerMqX1xOm3-IoYO6HZFKNIi6Icu4Pfr57rxewUyN2e56t9QlQG4-FdQucCecP7CbK3uxYU9sTQgJBnqGKNKSKritKYFKkG7YmI5azOjZe7Vaofiq20vraormt3x9T2g5_YyeikVz8IB0AX5xwKehtRH7Z1AnhkbaQATkwSFzU6SqIlZtzJ0YqaECPRGj7QMLnLtsQbamS9OD4Fph2Y5O0n9fa3gSYxPWtCdjXblUr4cbW13oOWzWJUcwLNrN3FBcyr4VNo1J7rCsxVXBTKicumbcVMo5HdMOCDReE-f_pI31nfcThKAR2g.3BKnbw0sCSvJ2uf9.tEx1VEntxVMFn7oXP2f7TcXGdSJImIov5vzqfRUOdty-ghVLtNKwSjSOc4eKoljxmrx9Bol0ArwiZxFoCLjWSviiPUueZMcOLYYlSOQ7BjAbdg7rEMPW1-GmijpPPWj9Xv7Lrc0iL7gBRWYV-heENqcBvyj7OdECak89dxNpocOlh0Y_WkyEwgn7nS8WwI6VuTgY8vpW4rF-eemA1rFQ9evjFGXDL554hFshNh5MIy25cJW8LWA-jA267IqVKVE4q8_JW9fgAkjSV5RoZfCvdeinOj5wLUnplxpjYACbJi8RdT184F_LtoFIUSWiZ2QU8XE-Is1Cdzw6qmzZoqwc4q3hp6Rhjc9EoyX0MKD6OqLji5ThWmSoTDQaqA7mwi3pXn2C9nRK5D4eQAEc6dbxiGIRvrqHLcmgx_P-u6ASznMsmdEEKzVTx3Dd1cACpVPTrX7hFBu-1YgxEAtdd_DVQl2FQqprlhol7jUZYq_RwTW1fiXG4lTqAvUUPE1WJB7_9IvGUhTWJS75nus5jVJ8OBjFAbXvVEZjmfv9Lwruu6j1e5Rcm8BZ38i5d7beKFcIt7p5pt2Zp93gHvGzzrcbktxcdPYLbqO2ZIs95Oo9ewdGMS2SUzH_x38caNnMlp6gSbZjCP8WCJspkIx7fPc-flMKGFD-PMRnd_LtGZgcC7gyeKGp54UT3Ly0_UcbK7FLB9dV4imanaonoYUtAjuQngZ1nAu1n6yV3-Nv7GJGfHVHi7Ia3KMLL6tEricaHwchO50cqedrDFzstx_d1tRgCw775qEPE_s1YdEGN6I6jYkTxhGJu9K7aP_EEsVMg-TjSz8VYtgNfYopDF7iGX6rioarh8qSSuc4cpfmJWjq_7mSHC2v9SE82v41qtADXKaiUHX3KEKiSCgQlPIHH4uvjYY50i8L3W9HixWu5oSctVgMyLlTAScdQbIfDIUX9dFv_0EFUFd9yNymkTpjeDOjAsWCmwLZiQ45HIqXrMQzV8yu4f-umjv_hHoNV_aS5MQPUFQqPD7ABYBzOgyrWU_MQnzkYVPAqZ9fWqn5AKcsjtaDfyp77V1INJUizkbmrQYyoBMj-NVGnfRNDVZ6dl_hDrCwJCv515dU8-2_Xxdaa9LmJHHn36qsHApmM5WMZyxUQGc7thKKtOwUwg6oeP0oKNnB8PE5dAEumVdfN28Ge7ATytbPhP_nM6UOVIXOcTC2jUxSezq6eKgfabnwxZqu9vlr87UcH0Ium-WXwmIxWMnYnO5xaIKOuEa2Bz6rgnexGKFZyJGixVQt7qssHQGwQj8taZkB.wHzd2G0DKpn6p3Kwv1WbCQ", "expires_in": 3600, "token_type": "Bearer" }
GET https://example123.auth.ap-northeast-1.amazoncognito.com/oauth2/userInfo Authorization: Bearer eyJraWQiOiJNVmRpcUcxc2Y2UmhoRnViYmg3QnB1R3pQVE1rSDhXYjJcL2JHaGRzN1V4cz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI2Nzg0MWFiOC1mMGUxLTcwNjMtNzZiZi1hMTViNDExMTgzYzAiLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfblJlZHJWRVlNIiwidmVyc2lvbiI6MiwiY2xpZW50X2lkIjoiNThtbGk1dWJqZWZyb2s0ajMxZ2xia2pvdm8iLCJvcmlnaW5fanRpIjoiMTg5MGUzMWMtODY1NS00YTQ4LTllYTMtM2MxYTE1NjBhYzFmIiwiZXZlbnRfaWQiOiJkMDQ4ODVmYy1iYmZjLTQyM2QtOTM1NC1kNjQ3NTg2NTgyYWYiLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwiYXV0aF90aW1lIjoxNzI3NTk0NDUwLCJleHAiOjE3Mjc1OTgwNTAsImlhdCI6MTcyNzU5NDQ1MCwianRpIjoiMzg3YjQ2NDQtMGNhZC00OGVmLThmNGUtZWRhNThmYTg0M2M3IiwidXNlcm5hbWUiOiJ5YW1hZGEifQ.FsguU26nOyaGFQGf_2Fbb8WBFAfAZ8l1PMpR6avVQ5pCO0fU35VIYCaVoild3s9BBaPRz2xjF06xHPzUHIlZZ9y1_7t7Bsb407eTFUaMCO-ojOT_VEYfOzfAWD5cT4BuRqMUM-oTIr1oOFo_plDhI4RgPDjUUZiYHwcqOv9Aji1Gqh5KIOFM9uWWpSPFWqhVCzfALNw4Cj-bbAojEdEIIxTuAvpoxacCldPMsyZf6M0JeCXzdqkfYUSsGkwYMMmPNI0oQC4ykqdSXdE55voK10WWE85w0bQJ5MRrOwjYRsUi4NR3CK4BIU9zWNFz-5CRmd6QtKJ_77vpR3I5Ht1PbQ
HTTP/1.1 200 OK { "sub":"67841ab8-f0e1-7063-76bf-a15b411183c0", "email_verified":"true", "name":"yamada", "email":"yamada@example.com", "username":"yamada" }
HTTP/1.1 200 OK ※ログイン後画面
IDトークンやアクセストークンは有効期限(3600秒)などを迎える前にリフレッシュする必要があります。RP は OP にリフレッシュ要求を行います。
GET https://example123.auth.ap-northeast-1.amazoncognito.com/oauth2/token grant_type=refresh_token client_id=58mli5ubjefrok4j31glbkjovo client_secret=ajvj5nn2vl59kn2il73cis5dafgh8rc32dp1rnc9gto0jidennq refresh_token=eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.PcvU5dLZDOrAuQQ3F9Zk5mHCEOVwejf7WYpGFm3Ml1-nMCcsuu-elAtmO6M6ipfpdsrUp4FlCnTNX9niT0rujsTf5nVgCIYpJEHkd4U0DQViA0r3KJAOzzZx9Z2w47IpyoBrVctxIVi1RDwyY8YYyn7E0TY5e7qrbKpM3Kn63t8FmRo8Lg9AGj890BRaqepfCc5PPOEmiaIJx_VAMaH4JSReEGsDENb1iSLkTr5fIGfWPVx48oTxchjCr1eArHwEOLcxav1VhkyxUc77VdaansHLVJERqq4WE_Kd_UMTjo7Vb0QPVfwtfErhcm4qoDik9p8Nz9wQV7Vn7-p7H0KtxA.Yhrx4pEMDCp8AuOj.nFtv_2_AhYQ8I737bS2jTUVI2_E1ohNnZZjumxpsFiFlCaVik2jYHrVSmfIzVf0XKYSbnq0RdDsSkNs2wSG-Xa9mpTbwR058xQaY9EGAKMtYQp1zWzJwhsV0UD8oCnO4JqDDbh2D8dcx0WjH32szY3h8mL5sQ_39WBCmumnYzXTZta5Dno5LyOmhqVzZhVi7-EePG6OQLMuLG9wma8EjB-vRAKGkuxoaqdS8aY0mnaTJPncMKTZJq4D63psXG3cAfmgKRZz8IhxemLINI6epB7p830CBFyRFpzeV7Zz9GNxgMLIKfk_sQKLWGPhQ4C9XdW4K8rQF0E8EDDp3mKoXA3rZJ45pEDs8U7kMeXxhqsU-F7I3MU6RZEMbPHujKwM5KLT5ozS1miUQbwNDMamapjKMFdCcGJcTVamCiszQ-n5Sq32w9m_0UnsBkJtGRHmWCrmrXNTG96uA59yFAywwgmTe0KyIidgo5sWsUYwYErK1KHmIzkQBw6AuScnG2dqKWfjFEB5EEXn52BN-xjSHsUdLBNW_Pu-acBm-p6WD_Y8YM9ffG4_h34IsG1kWCZhm0MeaDWO9y1s1wp9_GYFUnkFU7h_7t02QtKYQ-aDxtMbfOMQ79Cpkt9i_xWBIOK2YkqAUfxXXRzthF5cJKDlFfT_HlEkDmY8sa6ejNyIWLIh9FbmVraco-vGxQsYgXq4wYgwCjKKN0zkEKA6Uy2ws8Pucq0QD6cTz1x_SG5GdDxpwlcHiHdNZC7BWGoG8VGgxMQ5oS0yT_lXFltIqTuCp97d3ZtORM8uw-ngAEbUNxBzAr_TGWam9FOSZnPTMBGunYx014Lpxkj1DesAqtYNh4bMSLYg1dQKi68hfxs7NASLnlmvCLbSeJShx9ZuqBikLEFCLQqT2w2HhxfxXgJEqOH5_6Bkg88enOJTBAsA1CP9KKLedZOw15mSxcif9uWlSIGATQexJLmi65i4UP6zmkqjnYIQL8S8eNwtxV2uP8YhWNiAe-B4jYnjKpWHovUxikdnJkhgTICBSQuT6l8k6WCJFzkMcT4l0bVKcalPV2TqM_mnbdjLAtxA9hLQUlrY8GOpLbl4B3AeWymY0aWCZhNd2q7RfalIps9oKgMbTCeWg5axse6o-JEPg6qncQaoCk_6YwxBAQZmYFJaWPze9skapoc8sq2K1UazpMQwek0z10E0UvSBzn1ESxOFhSaqU2siXNz5TcuZiRnT0YGFcawFwAmvkG0tf6mm7miMVVK9h_AKNt89t0E3IkiFqAq2fO0txhTiSg4H3LWevMNHHmbAStmzr.75xRWGA6hbWmi0gn0BPB9w
OP は RP にリフレッシュしたトークンを返却します。
HTTP/1.1 200 OK { "id_token": "eyJraWQiOiIzUmFBWWZKRVwvY3NveXpmVDBlN1BtdTFmVjUzckxobVRsdXJiNEU4QmkrST0iLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiSGJicUhFSUhCSDloWDdQT0N0Z0Y4ZyIsInN1YiI6IjY3ODQxYWI4LWYwZTEtNzA2My03NmJmLWExNWI0MTExODNjMCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfblJlZHJWRVlNIiwiY29nbml0bzp1c2VybmFtZSI6InlhbWFkYSIsIm9yaWdpbl9qdGkiOiI0MDI0Mzk4NC03NmFmLTQ3ODUtOGYwMi05YjY1NTIwYmM0YTkiLCJhdWQiOiI1OG1saTV1YmplZnJvazRqMzFnbGJram92byIsImV2ZW50X2lkIjoiOTExNTEwOGItODAxYi00YTEzLTg2YjctNmI2NDYxNWMwNjJiIiwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE3Mjc2MDA3OTMsIm5hbWUiOiJ5YW1hZGEiLCJleHAiOjE3Mjc2MDQ0NzYsImlhdCI6MTcyNzYwMDg3NiwianRpIjoiNzJhNjkyYzktYjdkYS00MTVjLWJlYTQtMDk5NWVmMTNiY2EzIiwiZW1haWwiOiJ5YW1hZGFAZXhhbXBsZS5jb20ifQ.STr6anfpTYOFEd1CfWlLnQWxSbWdVstagNr_S5gmy7qrXVuwpncP9RA5PpieW6fwrZh3IswE7SMvTTICWexb7VG-e67RDL21CerAk0SIO4cVMsKJDviYu6HP4Lkqik4H6RyIeHKKXrb11tUnWaEuR8qHLjkjidDYXMILEhEM_YM3p_dQJWnWHb33USYaRiDlJ3V9BXll66A7M0vh3im5WzDasZn1-32f8MYNc25BTcSxFx-uxOoB3KDRJA9tbbuBpwcZtXpJnOpoKuhUvzZtAoGheS9cMrZNRxW7NgRTAA4F_juvxtFhFU0ndu-Wlw4gjocQY5YLaDsW_lWvpRFZgw", "access_token": "eyJraWQiOiJNVmRpcUcxc2Y2UmhoRnViYmg3QnB1R3pQVE1rSDhXYjJcL2JHaGRzN1V4cz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI2Nzg0MWFiOC1mMGUxLTcwNjMtNzZiZi1hMTViNDExMTgzYzAiLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfblJlZHJWRVlNIiwidmVyc2lvbiI6MiwiY2xpZW50X2lkIjoiNThtbGk1dWJqZWZyb2s0ajMxZ2xia2pvdm8iLCJvcmlnaW5fanRpIjoiNDAyNDM5ODQtNzZhZi00Nzg1LThmMDItOWI2NTUyMGJjNGE5IiwiZXZlbnRfaWQiOiI5MTE1MTA4Yi04MDFiLTRhMTMtODZiNy02YjY0NjE1YzA2MmIiLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwiYXV0aF90aW1lIjoxNzI3NjAwNzkzLCJleHAiOjE3Mjc2MDQ0NzYsImlhdCI6MTcyNzYwMDg3NiwianRpIjoiNDk3ODFkOWEtZWIwZi00MDY4LTg2ODktY2E3Nzk4YmFiMzJhIiwidXNlcm5hbWUiOiJ5YW1hZGEifQ.qNR1fErYug-KTiOzsSBQcLocw8rCU0VNxPfqcKO3yA9VYwwMscQN2UlSK88UzmRcUNr2Z9EXLWOnNkfEo85IZL9IRsvOfEfZFerj6iRVESxwa0gOP7zRIOD8YueViamvS5gFC5QQPF_-KCPhG_Oph98qBMRzHCHcn5UnJvrGOsIH1CiQ8IU2wNlgvsgrgFCJQTGFePx3pSyx20p4jxHUd6h4y2ywed39T0FYVVyh_VA-cFD_xIKUa58xEwcokminESBEloLET3QN52vvGbyZ2xIBTtt9wBK_HaaCjqj4tJRDR26Ea0JK-3N1XZDvLMYc8hJz4j_xE8GH2xyuGA0n9g", "expires_in": 3600, "token_type": "Bearer" }
不要となったアクセストークンやリフレッシュトークンは失効(revoke)させます。
POST https://example123.auth.ap-northeast-1.amazoncognito.com/oauth2/revoke Authorization: Basic {BASE64(client_id ":" client_secret)} Content-Type: application/x-www-form-urlencoded client_id=58mli5ubjefrok4j31glbkjovo token=eyJraWQiOiJNV...
GET https://www.example.com/logout
HTTP/1.1 302 Found Location: https://example123.auth.ap-northeast-1.amazoncognito.com/logout ?client_id=58mli5ubjefrok4j31glbkjovo &post_logout_redirect_uri=https://www.example.com
AWS Cognito の場合は post_logout_redirect_uri ではなく logout_uri を送るようです。
HTTP/1.1 302 Found Location: https://example123.auth.ap-northeast-1.amazoncognito.com/logout ?client_id=58mli5ubjefrok4j31glbkjovo &logout_uri=https://www.example.com
GET https://example123.auth.ap-northeast-1.amazoncognito.com/logout ?client_id=58mli5ubjefrok4j31glbkjovo &post_logout_redirect_uri=https://www.example.com
HTTP/1.1 302 Found Location: https://www.example.com
GET https://www.example.com
HTTP/1.1 200 OK ※ログアウト後画面
IDトークンは下記の様なものです。
eyJraWQiOiIzUmFBWWZKRVwvY3NveXpmVDBlN1BtdTFmVjUzckxobVRsdXJiNEU4QmkrST0iLCJhbGciOiJSUzI1N iJ9.eyJhdF9oYXNoIjoiZTRzUWJ6aTgtTWNBb2pDV3VmbjNmdyIsInN1YiI6IjY3ODQxYWI4LWYwZTEtNzA2My03N mJmLWExNWI0MTExODNjMCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZH AuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfblJlZHJWRVlNIiwiY29nbml0bzp 1c2VybmFtZSI6InlhbWFkYSIsIm5vbmNlIjoiMDk3VFJFSDFJWjVMUlo5RjVNU04iLCJvcmlnaW5fanRpIjoiMTg5 MGUzMWMtODY1NS00YTQ4LTllYTMtM2MxYTE1NjBhYzFmIiwiYXVkIjoiNThtbGk1dWJqZWZyb2s0ajMxZ2xia2pvd m8iLCJldmVudF9pZCI6ImQwNDg4NWZjLWJiZmMtNDIzZC05MzU0LWQ2NDc1ODY1ODJhZiIsInRva2VuX3VzZSI6Im lkIiwiYXV0aF90aW1lIjoxNzI3NTk0NDUwLCJuYW1lIjoieWFtYWRhIiwiZXhwIjoxNzI3NTk4MDUwLCJpYXQiOjE 3Mjc1OTQ0NTAsImp0aSI6ImNjZGM5M2FjLTY3YWQtNDBmYi05MDFmLTU3YTQ0NjRhYmFkYyIsImVtYWlsIjoieWFt YWRhQGV4YW1wbGUuY29tIn0.i2445XrLKkyW1drQHQXOh598-UEB6SgpRZCgJsfu1hW-UPVWZqOGskEq6CC4VY533 kDhpppqJGo-ZAfE1-CzLhzdYdmi5aov46pEJHNCAahjfjffgnNRBXtXCIROWEPh3YxEuncS4kMBKCz4oo0BiAE8T6 OV591gGwGqOgRIRADcMrnn7WDiZK3xRwO5F6pViBMrdu6wPykHNXvdgZ7C_46TJozEc5CFaEiucYL1d14_3qxKvJ4 NIygjH-oD_IwiiVhKquMbjms35gIauVOLZEpXgy4z_FCmQI5LEEoR5tdt90TpCM2bmJcxHn9s3nRfqvrxWIEnJ1ar Wdp_D4gLVg
途中にピリオド(.)が2カ所あり、ピリオドをデリミタとして3つのパートに分解できます。一つ目がヘッダー、二つ目はペイロード、三つ目は署名です。
--- ヘッダー --- eyJraWQiOiIzUmFBWWZKRVwvY3NveXpmVDBlN1BtdTFmVjUzckxobVRsdXJiNEU4QmkrST0iLCJhbGciOiJSUzI1N iJ9 --- ペイロード --- eyJhdF9oYXNoIjoiZTRzUWJ6aTgtTWNBb2pDV3VmbjNmdyIsInN1YiI6IjY3ODQxYWI4LWYwZTEtNzA2My03N mJmLWExNWI0MTExODNjMCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZH AuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfblJlZHJWRVlNIiwiY29nbml0bzp 1c2VybmFtZSI6InlhbWFkYSIsIm5vbmNlIjoiMDk3VFJFSDFJWjVMUlo5RjVNU04iLCJvcmlnaW5fanRpIjoiMTg5 MGUzMWMtODY1NS00YTQ4LTllYTMtM2MxYTE1NjBhYzFmIiwiYXVkIjoiNThtbGk1dWJqZWZyb2s0ajMxZ2xia2pvd m8iLCJldmVudF9pZCI6ImQwNDg4NWZjLWJiZmMtNDIzZC05MzU0LWQ2NDc1ODY1ODJhZiIsInRva2VuX3VzZSI6Im lkIiwiYXV0aF90aW1lIjoxNzI3NTk0NDUwLCJuYW1lIjoieWFtYWRhIiwiZXhwIjoxNzI3NTk4MDUwLCJpYXQiOjE 3Mjc1OTQ0NTAsImp0aSI6ImNjZGM5M2FjLTY3YWQtNDBmYi05MDFmLTU3YTQ0NjRhYmFkYyIsImVtYWlsIjoieWFt YWRhQGV4YW1wbGUuY29tIn0 --- 署名 --- i2445XrLKkyW1drQHQXOh598-UEB6SgpRZCgJsfu1hW-UPVWZqOGskEq6CC4VY533 kDhpppqJGo-ZAfE1-CzLhzdYdmi5aov46pEJHNCAahjfjffgnNRBXtXCIROWEPh3YxEuncS4kMBKCz4oo0BiAE8T6 OV591gGwGqOgRIRADcMrnn7WDiZK3xRwO5F6pViBMrdu6wPykHNXvdgZ7C_46TJozEc5CFaEiucYL1d14_3qxKvJ4 NIygjH-oD_IwiiVhKquMbjms35gIauVOLZEpXgy4z_FCmQI5LEEoR5tdt90TpCM2bmJcxHn9s3nRfqvrxWIEnJ1ar Wdp_D4gLVg
ヘッダを BASE64 デコード(末尾に=が不足していれば追加)すると下記になります。kid はキーID、alg は署名アルゴリズムを意味します。
{ "kid":"3RaAYfJE\/csoyzfT0e7Pmu1fV53rLhmTlurb4E8Bi+I=", "alg":"RS256" }
ペイロードを BASE64 デコード(末尾に=が不足していれば追加)すると下記になります。
{ "at_hash": "e4sQbzi8-McAojCWufn3fw", "sub": "67841ab8-f0e1-7063-76bf-a15b411183c0", "email_verified": true, "iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_nRedrVEYM", "cognito:username": "yamada", "nonce": "097TREH1IZ5LRZ9F5MSN", "origin_jti": "1890e31c-8655-4a48-9ea3-3c1a1560ac1f", "aud": "58mli5ubjefrok4j31glbkjovo", "event_id": "d04885fc-bbfc-423d-9354-d647586582af", "token_use": "id", "auth_time": 1727594450, "name": "yamada", "exp": 1727598050, "iat": 1727594450, "jti": "ccdc93ac-67ad-40fb-901f-57a4464abadc", "email": "yamada@example.com" }
署名情報は BASE64 デコードしてもバイナリデータとなります。この署名情報を用いてヘッダやペイロードが改竄されていないかを検証します。署名アルゴリズム(alg)の RS256 は RSASSA-PKCS1-v1_5 using SHA-256 を意味し、公開鍵暗号を意味します。検証には OP の公開鍵が必要ですが、JWK Set URI(jwks_uri) から取得することができます。
curl https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_nRedrVEYM/.well-known/jwks.json { "keys": [ { "alg": "RS256", "e": "AQAB", "kid": "3RaAYfJE/csoyzfT0e7Pmu1fV53rLhmTlurb4E8Bi+I=", "kty": "RSA", "n": "smcMiQ_J8uVhRCdR5-HYXvvWMJ_9gniAHcJ8RAcPaIEeErKxOLeQUZ8nN0oTerUZXB_DjwGnkrg1Atk7ZT6k4wFMUh9hnbcCgqtvBULS2kH6UiFlDNKEkcjuo1MHA4C-Hp7ixKbvfiOQZoV4GI05Pwjfy7Uq2AzjZFN7s8pu7YRb4TuhdzNdUVOM7woJW_na52KUPMaQpQoZdaedEJjwVw9ggVaUrGrm84HHN0KlviFHOWHzBfGuJvbDal19CNMQxSm9z6mIhtfM_0sea7hG-D-djyRSfERjHataBSo41FYLiP1C3AthRJH_ENLCZBmh-t6iYSUT5Eha55Wx4BDyEQ", "use": "sig" }, { "alg": "RS256", "e": "AQAB", "kid": "MVdiqG1sf6RhhFubbh7BpuGzPTMkH8Wb2/bGhds7Uxs=", "kty": "RSA", "n": "7TKROn_BbfESd_6KDC-m9ihou-PmFbHLboS6Og1Ksix3dMU1CDSdXeAqFYEtHo0vNiwmBkmLKW2Z--9hVM2voosjA8m62n7ljynPW6pHvbwoBPzo0axcj6zv5El84A7lVpnJ8gl3SjATI9E_zZnsvXB3kRJudEWcCgmAclnawN5CXtVamj9LHLomyhsGrF_LqvibYfMI_DjtxYy-LQH7rcuLX8VI4CJfyq36R05kimEDT9B6nHFXQBylCQM_0Tkk8yuH36Ns9oxlq1N49ELFR0yWJjJaAvRM2CaVJO7W747L-TnOnv_uMEiPyIh5x5nKzro5izA95hDsx_NVk7KT7w", "use": "sig" } ] }
Python で AWS Cognito を IP(IdP) として動作する RP(Client) のサンプルコードを下記に示します。テストのため www.example.com の FQDN を使用します。
必要なパッケージをインストールします。
# -- RHEL9/AlmaLinux 9/Rocky Linux 9 $ sudo dnf -y install python3 python3-pip openssl $ sudo pip3 install flask requests pyjwkest # -- Ubuntu 24.04 $ sudo apt install -y python3-venv $ sudo python3 -m venv /opt/oidc $ source /opt/oidc/bin/activate $ sudo pip3 install flask requests pyjwkest
HTTPS 通信を行う必要があるため、SSLの鍵と証明書を作成します。server's hostname には www.example.com を指定してください。他は空でも構いません。
$ openssl genrsa 2048 > server.key $ openssl req -new -key server.key > server.csr : Common Name (eg, your name or your server's hostname) []:www.example.com : $ cat server.csr | openssl x509 -req -signkey server.key > server.crt
ブラウザを実行する Windows 端末に、管理者モードで \Windows\System32\drivers\etc\hosts を開き、ブラウザから www.example.com にアクセスする際のアドレスを www.example.com に書き込みます。下記に例を示しますが IPアドレスは適切に変更してください。
192.168.1.100 www.example.com
プログラムの config 情報を環境に合わせて設定します。最低限 XXXXXXXXXX の箇所の修正は必要です。
$ vi ./openid-connect-sample.py
準備ができたら下記を実行し、ブラウザから https://www.example.com にアクセスします。
$ python3 -B ./openid-connect-sample.py