おはようございます、ritouです。
今回はTransactional AuthorizationとしてIETF にDraftが提出されている仕様に注目します。
draft-richer-transactional-authz-02 - Transactional Authorization
⚠これはOAuth 2.0の特定の脆弱性 を防いだりするために作られたOAuth 2.0拡張ではありません。まだドラフトなので今後も変わる可能性があります⚠
資料
少し前にプロトコル の紹介をした時の動画もあります。
VIDEO www.youtube.com
最近のIETF のお集まりでのプレゼンテーション資料も公開されています。
https://datatracker.ietf.org/meeting/105/materials/slides-105-oauth-sessa-transactional-authorization-xyz
"XYZ"と名付けられたこのプロトコル についての情報は、以下のサイトにて整理されています。
https://oauth.xyz/
英語が聞こえて読めて自分で調べる気持ちがあるならこれで十分でしょうが、理解を深めるために中身を見ていきましょう。
XYZとは?
XYZは、トランザクション モデルをベースとした認可プロトコル です。OAuth 2.0の拡張ではありません。
まずは処理の流れをざっくり説明します。ここで出てくる用語の意味はOAuth 2.0と一緒です。
トランザクション 開始要求 : クライアントはバックチャンネルでクライアント自身の情報、対象ユーザーの情報、アクセスするAPI などのリソース情報、ユーザーインタラク ションの情報、鍵情報などを認可サーバーに送信する
ユーザーインタラク ション : ユーザーインタラク ションが必要な場合、認可サーバーはリダイレクト先のURLなどをクライアントに返し、クライアントはフロントチャンネルでの処理が行われる
アクセストーク ンの発行 : ユーザーインタラク ションが不要だったり完了した後、認可サーバーはクライアントにアクセストーク ンを発行する
ここでのポイントは2点です。
OAuth 2.0で言う所のGrantTypeに関わらず、上記のトランザクション 開始からアクセストーク ン発行までの流れは共通
必要最小限のフロントチャンネルの利用
この後紹介しますが、AuthZ Code GrantとImplicit Grantの場合はAuthZ Requestを送って...Client Credentials GrantやROPC Grantの時は直接Token Endpointへ...というように最初からフローが分けて考えられているわけではなく、必ず最初にトランザクション 開始要求が送られます。
ユーザー認証やアクセス許可が必要となる場合だけブラウザでリダイレクトなどをしてフロントチャンネルを利用します。
また、いわゆるAuthZ Request/ResponseにはRFC6749で定義されているパラメータに加え、OIDC/PKCE/JARM/TokenBindingなど拡張仕様をトッピングしていくとパラメータが山盛りになり、戻ってきた後のClient側の検証も必要です。
XYZではトランザクション 要求に含まれた情報に紐づくシンプルなURLを認可サーバー側が生成してクライアントはユーザーを送ります。
ちょっと前にOAuth 2.0で決済を行いたいときなどのScopeの指定方法についてのブログ記事などもありましたが、フロントチャンネルのクエリパラメータよりもバックチャンネルのJSON データの方が柔軟な表現ができるだろうという感じです。
この辺りを意識して、OAuth 2.0の各種フローをXYZで表現したらどうなるかを見ていきましょう。
OAuth 2.0 vs XYZ
今回は次の3つがXYZでどのように表現されるかを見ていきます。
Authorization Code Flow
Device Flow
Client Credentials Flow
Resource Owner's Password Credentials / Assertion Flow
シーケンスをいくつか載せますが、その中で登場人物はOAuthとほぼ一緒です。
Resource Owner(RO)
Resource Client(RC)
Authorization Server(AS)
Resource Server(RS)
それでは見ていきましょう。
Authorization Code Flow
OAuth 2.0でAuthorization Code Flowは最も有名な認可フローだと思いますが、これをXYZで表現します。
ちょっと小さくて見えないかもしれませんが、
Transaction Request : RCはOAuth 2.0のAuthZ Requestに含まれるようなパラメータをTransaction Requestとして送信
Interaction Response : ASはRCに interaction_url
と handle
(transaction handle) を返す
User Interaction : RCはROを interaction_url
に送り、ユーザー認証、アクセス許可を行う
Callback : RCに戻る際にはCSRF 対策用 state
と interact
(interact_handle) の値がついてくる
Transaction continue request : RCは state
の検証後、 handle
(transaction handle), interact_handle
をASに送信
Access Token : ASはAccess Tokenを返す。ここで handle
として返される値を用いてRefreshも可能(Transactionは続いていくのだ...)
という感じです。
そんなにシンプルになってる感じではないですが、OAuth 2.0で肥大してしまったAuthZ Requestがバックチャンネルに閉じ込められたようにも見えます。
Device Flow
次はいわゆるDevice Flowです。
tools.ietf.org
もう少しでRFC になりそうですね。こいつをXYZで表現するとこうなります。
Transaction Request : RCは interact.type=device
な値を含む Transaction Request を送信
Interaction Response : ASはRCに user_code_url
と user_code
、 handle
(transaction handle) を返す
User Interaction : RCはROに別端末で user_code_url
にアクセスさせ、 user_code
を入力した後にユーザー認証、アクセス許可を行う
Polling request : RCは待ってる間、定期的に handle
(transaction handle) をASに送信する
Access Token : 別端末でのアクセス許可が完了したら、ASはAccess Tokenを返す。ここで handle
として返される値を用いてRefreshも可能
OAuth 2.0の拡張ではDevice AuthZ Endpointが追加されたりしてましたが、XYZなら Transaction Request を受ける Transaction Endpoint がその辺もやってくれるので、とりあえず AuthZ Code Flow相当のやつと共存できる感じになっています。
仕様的にはもう一つ "user_code" を含まない場合もありますが、Device Flowの仕様で言うところの "Remote Phishing "、OAuth 1.0で言うところの "Session Fixation Attack" あたりのリスクがあるのでTransaction Requestにはもう少し情報が追加される気がします。
ちなみにTransaction Request/Response の値とASの処理をもう少し拡張すればCIBA相当の処理も実現できますね。
Client Credentials Flow
いわゆる 2-legged なフローですが、XYZでも表現できます。
この場合は Transaction Request にuser
, interact
フィールドが含まれず、ASはRCの情報を検証してAccess Tokenを返します。
Resource Owner's Password Credentials / Assertion Flow
いわゆるROPCやある外部IdPからのAssertionを受け取ってAccess Tokenを返す Token Exchange フローについても、XYZで表現できます。
この場合は Transaction Request のuser
フィールドにクレデンシャルや外部IdPのAssertionなどを含み、ASはそれを検証してAccess Tokenを返します。
こんな感じで、OAuth 2.0でサポートされているユースケース についてはXYZでサポートされており、エンドポイントの構成なども統一したものになりそうなことがお分りいただけたかと思います。
基本的な仕様
ここまではイメージしやすいようにOAuth 2.0との比較しながら見てきましたが、細かいところの理解するために必要な基本的な仕様を整理します。
エンドポイント
Transaction Request/Response
Transaction continue Request
Polling Request
など色々出てきましたが、AS側は "Transaction Endpoint" がバックチャンネルにてリクエス トを処理し、User Interaction が必要な場合のみフロントチャンネルを使った処理が行われます。
ハンドル
XYZで扱われる情報をASが処理した時に、それらの情報と紐付けたhandle
の値を返すことでその後の処理に利用できます。
Transaction Handle : Transaction Request からAccess Tokenを返すまでの一連の処理に紐付く
Client Handle : Client情報に紐付く
User : ユーザー情報に紐付く
Interaction : 個々の User Interaction に紐付く
Resource Handle : アクセス対象となるリソースセットに紐付く
Key Handle : 鍵情報に紐付く
Access Token Handle : アクセストーク ンに紐付く
これがイメージできると理解は楽になるでしょう。
XYZの中で、Transaction Request が一番複雑になり得ます。
XYZのサイト上でここに含むパラメータを色々いじって試すことができます。
盛り盛りにした場合はこちら。
{
// Client の情報
"client": {
"name": "My Client Display Name",
"uri": "https://example.net/client"
},
// User Interaction に関する指定
"interact": {
"type": "redirect",
"callback": "https://client.example.net/return/123455",
"state": "LKLTI25DK82FX4T4QFZC"
},
// User に関する指定
"user": {
"assertion": "eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAibmFtZSI6ICJKYW5lIERvZSIsCiAiZ2l2ZW5fbmFtZSI6ICJKYW5lIiwKICJmYW1pbHlfbmFtZSI6ICJEb2UiLAogImdlbmRlciI6ICJmZW1hbGUiLAogImJpcnRoZGF0ZSI6ICIwMDAwLTEwLTMxIiwKICJlbWFpbCI6ICJqYW5lZG9lQGV4YW1wbGUuY29tIiwKICJwaWN0dXJlIjogImh0dHA6Ly9leGFtcGxlLmNvbS9qYW5lZG9lL21lLmpwZyIKfQ.rHQjEmBqn9Jre0OLykYNnspA10Qql2rvx4FsD00jwlB0Sym4NzpgvPKsDjn_wMkHxcp6CilPcoKrWHcipR2iAjzLvDNAReF97zoJqq880ZD1bwY82JDauCXELVR9O6_B0w3K-E7yM2macAAgNCUwtik6SjoSUZRcf-O5lygIyLENx882p6MtmwaL1hd6qn5RZOQ0TLrOYu0532g9Exxcm-ChymrB4xLykpDj3lUivJt63eEGGN6DH5K6o33TcxkIjNrCD4XB1CKKumZvCedgHHF3IAK4dVEDSUoGlH9z4pP_eWYNXvqQOjGs-rDaQzUHl6cQQWNiDpWOl_lxXjQEvQ",
"type": "oidc_id_token"
},
// アクセス対象のリソースについての指定
"resources": [
{
"actions": [
"read",
"write",
"dolphin"
],
"locations": [
"https://server.example.net/",
"https://resource.local/other"
],
"data": [
"metadata"
]
}
],
// Access Tokenなどにバインドする鍵情報について
"key": {
"jwks": {
"keys": [
{
"kty": "RSA",
"e": "AQAB",
"kid": "xyz-1",
"alg": "RS256",
"n": "kOB5rR4Jv0GMeLaY6_It_r3ORwdf8ci_JtffXyaSx8xYJCCNaOKNJn_Oz0YhdHbXTeWO5AoyspDWJbN5w_7bdWDxgpD-y6jnD1u9YhBOCWObNPFvpkTM8LC7SdXGRKx2k8Me2r_GssYlyRpqvpBlY5-ejCywKRBfctRcnhTTGNztbbDBUyDSWmFMVCHe5mXT4cL0BwrZC6S-uu-LAx06aKwQOPwYOGOslK8WPm1yGdkaA1uF_FpS6LS63WYPHi_Ap2B7_8Wbw4ttzbMS_doJvuDagW8A1Ip3fXFAHtRAcKw7rdI4_Xln66hJxFekpdfWdiPQddQ6Y1cK2U3obvUg7w"
}
]
}
}
}
これがハンドルを使って最もシンプルにするとこんな感じにもなり得ます。
{
"client": "VBUEOIQA82PBY2ZDJW7Q",
"interact": "JMMLJ6393FI7ST9B1SRS",
"user": "XUT2MFM1XBIKJKSDU8QM",
"resources": [
"dolphin-metadata"
],
"key": "7C7C4AZ9KHRS6X63AJAO"
}
実装を想像すると処理の分岐など若干めんどくさい気もしなくはないですが、その辺は気にせずに行きましょう。
レスポンス
いくつかレスポンスが定義されています。興味がある方は仕様を見てみてください。
Transaction Endpointから返されるAccess TokenがBearer トーク ンの場合はこんな感じで表現されます。
{
"access_token": {
"value": "OS9M2PMHKUR64TB8N6BW7OZB8CDFONP219RP1LT0",
"type": "bearer"
}
}
Sender-Constrained Token にしたい場合はこんな感じです。
{
"access_token": {
"value": "OS9M2PMHKUR64TB8N6BW7OZB8CDFONP219RP1LT0",
"jwks": {
"keys": [
{
"kty": "RSA",
"e": "AQAB",
"kid": "xyz-1",
"alg": "RS256",
"n": "kOB5rR4Jv0GMeLaY6_It_r3ORwdf8ci_JtffXyaSx8xYJCCNaOKNJn_Oz0YhdHbXTeWO5AoyspDWJbN5w_7bdWDxgpD-y6jnD1u9YhBOCWObNPFvpkTM8LC7SdXGRKx2k8Me2r_GssYlyRpqvpBlY5-ejCywKRBfctRcnhTTGNztbbDBUyDSWmFMVCHe5mXT4cL0BwrZC6S-uu-LAx06aKwQOPwYOGOslK8WPm1yGdkaA1uF_FpS6LS63WYPHi_Ap2B7_8Wbw4ttzbMS_doJvuDagW8A1Ip3fXFAHtRAcKw7rdI4_Xln66hJxFekpdfWdiPQddQ6Y1cK2U3obvUg7w"
}
]
}
}
}
Client 認証
OAuth 2.0の場合は静的/動的なClient認証が済んでいる状態を想定しており、動的な登録(Dynamic Registration)を行う場合は処理が1往復追加されます。
XYZではTransaction RequestにClient情報を含むことで動的な登録も処理を増やさずにできますし、静的な登録の仕組みも使えます。
言い換えるとClient情報を細かく制御できる仕組みとも言えそうですが、まぁ、この辺やりすぎると開発者は混乱しそうです。
まとめ
OAuth 2.0のフロートをXYZで表現するとどうなるかを整理し、現状のXYZサイトに書いてある情報を紹介しました。
OAuth 2.0に求められるユースケース 毎の要件を整理し、OAuth 1.0の時のようなバックチャンネルのリクエス ト中心のプロトコル として書き直した感じです。
そう言えば決済アプリなどのクレカ関連の処理でお馴染みの3D Secureでも同じようなフローになっています。
3Dセキュア2とは? EMVCoの3Dセキュア
3D Secure 1.0ではXYZのTransaction Request相当のリクエス トでカード情報などを送り、ワンタイムパスワード の確認を行うURLにアクセスします。
3D Secure 2.0ではより情報を増やし、リスクベースの判定をしたりします。
Transactionalと言う名前からも、この辺りは共通する部分だったり参考にできる部分はありそうですね。
今後どのような展開を見せるのかはわかりませんが、引き続きウォッチしていきたいと思います。
告知
idcon は今週末開催です。
idcon.connpass.com
ここに来る人なら今回の XYZ についてもすぐに理解できるよな!
興味があったら懇親会でお話ししましょう。
ではまた🍎