TA から別の TA に処理を要請する際のプロトコル。
処理に関連するアカウントの情報を、アカウントの属す IdP を間に挟み、TA 間で受け渡す。
- 関連するアカウントが属す全ての IdP について次の 1, 2 を行う。
- 連携元 TA から IdP に、関連するアカウントの中でその IdP に属すアカウントおよび連携先 TA を伝える。
- IdP から連携元 TA に、仲介コードを発行する。
- 連携元 TA から連携先 TA に、全ての仲介コードを渡す。
- 全ての仲介コードについて次の 1, 2 を行う。
- 連携先 TA から仲介コードを発行した IdP に、仲介コードを提示する。
- IdP から連携先 TA に、仲介コードに紐付くアカウントと連携元 TA の情報を渡す。
+--------+ +--------+
| | +--------+ | |
| |----(1-1) request--->| | | |
| | | IdP | | |
| |<---(1-2) code-------| | | |
| | +--------+ | |
| | ... ... | |
| | | |
| | | |
| TA |---------------------(2) codes---------------------->| TA |
| | | |
| | +--------+ | |
| | | |<---(3-1) code--------| |
| | | IdP | | |
| | | |----(3-2) userinfo--->| |
| | +--------+ | |
| | ... ... | |
| | | |
+--------+ +--------+
関連するアカウントは、処理の主体とそれ以外に分ける。
- 処理の主体
- ユーザー認証を通り、アクセストークンを連携元 TA に渡し、処理の引き金になるアクセスを行ったユーザーのアカウント。
- 処理の主体でないアカウント
- 処理の対象となるアカウント等。
例えば、連携元 TA と連携先 TA が両方グループウェアであるとする。 連携元 TA で同じグループに入っているアカウントを連携先 TA のグループへ招待する場合、招待する側のアカウントは処理の主体、招待される側のアカウントは処理の主体でないアカウントとなる。
連携元 TA は、関連するアカウント全てに対して、その処理において一意のタグをつけなければならない。
連携元 TA から IdP の連携元仲介エンドポイントにリクエストを送る。
リクエストの中身は、処理の主体が IdP に属すかどうかで変わる。 また、処理の主体が属さない IdP へのリクエストには、処理の主体が属す IdP へのリクエストの結果が必要になるため、最初に処理の主体が属す IdP へのリクエストを行う必要がある。
IdP は連携元仲介エンドポイントを TLS で提供しなければならない。
処理の主体が属す IdP への連携元仲介リクエストは、以下で指定するパラメータを最上位要素として含む JSON オブジェクトである。
response_type
- 必須。
関連するアカウントが他の IdP に属さない場合は
code_token
、属す場合はcode_token referral
でなければならない。
- 必須。
関連するアカウントが他の IdP に属さない場合は
from_client
- 必須。 連携元 TA の ID。
to_client
- 必須。 連携先 TA の ID。
grant_type
- 必須。
access_token
でなければならない。
- 必須。
access_token
- 必須。 処理の主体に対する有効なアクセストークン。
scope
- 任意。
連携先 TA に新しく発行されるアクセストークンに対して許可されるスコープの最大範囲。
形式は OAuth 2.0 Section 3.3 を参照のこと。
access_token
で指定したアクセストークンに対して許可されていないスコープを含んではならない。
- 任意。
連携先 TA に新しく発行されるアクセストークンに対して許可されるスコープの最大範囲。
形式は OAuth 2.0 Section 3.3 を参照のこと。
expires_in
- 任意。
連携先 TA に新しく発行されるアクセストークンの有効期間の上限。
access_token
で指定したアクセストークンの残り有効期間より長い場合は無視される。
- 任意。
連携先 TA に新しく発行されるアクセストークンの有効期間の上限。
user_tag
- 必須。 処理の主体に付けたアカウントタグ。
users
- 処理の主体でないアカウントが IdP に属す場合は必須。 そうでなければ無し。 IdP に属す処理の主体でないアカウント全てについて、アカウントタグからアカウント ID へのマップ。
related_users
response_type
がreferral
を含む場合は必須。 そうでなければ無し。 他の IdP に属す関連するアカウント全てについて、アカウントタグからアカウントのハッシュ値へのマップ。
hash_alg
response_type
がreferral
を含む場合は必須。 そうでなければ無し。related_users
におけるアカウントのハッシュ値計算アルゴリズム。
related_issuers
response_type
がreferral
を含む場合は必須。 そうでなければ無し。 関連するアカウントが属す他の全ての IdP の ID の配列。
リクエスト時の TA 認証は必須であり、OpenID Connect Core 1.0 Section 9 で定義されているクライアント認証方式を利用する。 その際、application/x-www-form-urlencoded フォームパラメータとして含めるはずのものは、代わりに JSON の最上位要素として含める。
related_users
におけるアカウントのハッシュ値は以下のように計算する。
アカウントが属す IdP の ID とアカウント ID をヌル文字で連結したバイト列をつくる。 それをハッシュ値計算アルゴリズムの入力にする。 出力されたバイト列の前半分を Base64URL エンコードする。 できた文字列がアカウントのハッシュ値である。
Base64URLEncode(LeftHalf(Hash(<IdP の ID> || <ヌル文字> || <アカウント ID>)))
ハッシュ値計算アルゴリズムとしては以下を認める。
SHA256
SHA384
SHA512
POST /coop/from HTTP/1.1
Host: idp.example.org
Content-Type: application/json
{
"response_type": "code_token referral",
"from_client": "https://from.example.org",
"to_client": "https://to.example.org",
"grant_type": "access_token",
"access_token": "cYcFjo0EF7FiN8Jx1NJ8Wn51gcYl84",
"user_tag": "inviter",
"users": {
"invitee": "md04LUMHnwLYodm8e55hc8UbGISJc4ZCYJK3AWF5IBk"
},
"related_users": {
"observer": "Gbr93kvtHPkuUX4YlRD4QA"
},
"hash_alg": "SHA256",
"related_issuers": [
"https://idp2.example.org"
]
}
TA 認証用データは省いている。
処理の主体が属さない IdP へのリクエストは、以下で指定するパラメータを最上位要素として含む JSON オブジェクトである。
response_type
- 必須。
code_token
でなければならない。
- 必須。
grant_type
- 必須。
referral
でなければならない。
- 必須。
referral
- 必須。
処理の主体が属す IdP が発行した
referral
。
- 必須。
処理の主体が属す IdP が発行した
users
- 必須。 IdP に属す関連するアカウント全てについて、アカウントタグからアカウント ID へのマップ。
リクエスト時の TA 認証は必須であり、OpenID Connect Core 1.0 Section 9 で定義されているクライアント認証方式を利用する。 その際、application/x-www-form-urlencoded フォームパラメータとして含めるはずのものは、代わりに JSON の最上位要素として含める。
POST /coop/from HTTP/1.1
Host: idp2.example.org
Content-Type: application/json
{
"response_type": "code_token",
"grant_type": "referral",
"referral": "eyJhbGciOiJFUzI1NiJ9.eyJhdWQiOlsiaHR0cHM6Ly9pZHAyLmV4YW1wbGUub3
JnIl0sImV4cCI6MTQyNTQ1MjgzNSwiaGFzaF9hbGciOiJTSEEyNTYiLCJpc3MiOiJodHRwcz
ovL2lkcC5leGFtcGxlLm9yZyIsImp0aSI6InlHLTh4Zm1Pb1Q3RDRERE0iLCJyZWxhdGVkX3
VzZXJzIjp7Im9ic2VydmVyIjoiR2JyOTNrdnRIUGt1VVg0WWxSRDRRQSJ9LCJzdWIiOiJodH
RwczovL2Zyb20uZXhhbXBsZS5vcmciLCJ0b19jbGllbnQiOiJodHRwczovL3RvLmV4YW1wbG
Uub3JnIn0.YjH8_n8D00qjIDtbBQW1JpkxBoDFs78Eepo0Jn1WeI8PjTdDCiwZy8ZcvOfJTi
soEFPunjWYplVE7wqUUV9mxw",
"users": {
"observer": "K30qzk6Ki1tBVOan-mte50JQrhmEfnf8hrW77zqL1jg"
}
}
referral
は処理の主体が属す IdP からの連携元仲介レスポンス例のもの。
referral
の改行とインデントは表示の都合による。
TA 認証用データは省いている。
IdP は以下のように連携元仲介リクエストを検証しなければならない。
--f--> は失敗時のエラーレスポンスの error
の値を示す。
- 連携元 TA を認証する。
- --f-->
invalid_client
- --f-->
- リクエストが必要なパラメータを含むことを確認する。
- --f-->
invalid_request
- --f-->
access_token
を含む場合、access_token
の指すアクセストークンが有効であることを確認する。- --f-->
invalid_grant
- --f-->
scope
を含む場合、scope
の値がaccess_token
の指すアクセストークンに対して許可されていないスコープを含まないことを確認する。- --f-->
invalid_scope
- --f-->
to_client
を含む場合、to_client
が指す TA が存在し、連携元 TA とは異なることを確認する。- --f-->
invalid_request
- --f-->
users
を含む場合、users
に含まれるアカウント ID が存在することを確認する。- --f-->
invalid_request
- --f-->
related_issuers
を含む場合、related_issuers
に含まれる IdP が存在することを確認する。- --f-->
invalid_request
- --f-->
- 異なるアカウントに同じアカウントタグが付けられていないことを確認する。
- --f-->
invalid_request
- --f-->
referral
を含む場合、referral
の値を署名済み JWT として検証する。- --f-->
invalid_grant
- --f-->
referral
を含む場合、referral
の値の JWT が必要なクレームを含むことを確認する。- --f-->
invalid_grant
- --f-->
referral
を含む場合、referral
の値の JWT が含むto_client
クレームが指す TA が存在し、連携元 TA とは異なることを確認する。- --f-->
invalid_grant
- --f-->
referral
を含む場合、referral
の値の JWT が含むrelated_users
クレームに、users
に含まれるアカウントタグが全て含まれており、そのハッシュ値が計算したハッシュ値と一致することを確認する。- --f-->
invalid_grant
- --f-->
リクエストに問題が無ければ、IdP から連携元 TA にレスポンスを返す。
レスポンスは以下の最上位要素を含む JSON オブジェクトである。
code_token
- リクエストの
response_type
がcode_token
を含む場合は必須。 そうでなければ無し。 以下のクレームを含む署名済み JWT。iss
- 必須。 IdP の ID。
sub
- 必須。 仲介コード。
aud
- 必須。 連携先 TA の ID。
from_client
- リクエストに
from_client
が含まれていた場合は必須。 そうでなければ無し。 リクエストのfrom_client
の値そのまま。
- リクエストに
user_tag
- リクエストに
user_tag
が含まれていた場合は必須。 そうでなければ無し。 リクエストのuser_tag
の値そのまま。
- リクエストに
user_tags
- リクエストに
users
が含まれていた場合は必須。 そうでなければ無し。 リクエストのusers
に含まれていた全てのアカウントタグの配列。
- リクエストに
ref_hash
- リクエストの
response_type
がreferral
を含む、または、リクエストのgrant_type
がreferral
の場合は必須。 そうでなければ無し。 リクエストのresponse_type
がreferral
を含む場合は発行したreferral
のハッシュ値。 リクエストのgrant_type
がreferral
の場合はリクエストのreferral
のハッシュ値。 ハッシュ値はハッシュ値計算アルゴリズムの出力バイト列の前半分を Base64URL エンコードしたものである。 ハッシュ値計算アルゴリズムはreferral
の値の JWT が含むhash_alg
クレームと同じでなければならない。
- リクエストの
- リクエストの
referral
- リクエストの
response_type
がreferral
を含む場合は必須。 そうでなければ無し。 以下のクレームを含む署名済み JWT。iss
- 必須。 IdP の ID。
sub
- 必須。 連携元 TA の ID。
aud
- 必須。
リクエストの
related_issuers
の内容そのまま。
- 必須。
リクエストの
exp
- 必須。 有効期限。 JWT Section 4.1.4 を参照のこと。
jti
- 必須。 トークン ID。 JWT Section 4.1.7 を参照のこと。
to_client
- 必須。
リクエストの
to_client
の値そのまま。
- 必須。
リクエストの
related_users
- 必須。
リクエストの
related_users
の内容そのまま。
- 必須。
リクエストの
hash_alg
- 必須。
related_users
におけるアカウントのハッシュ値計算アルゴリズム。
- 必須。
- リクエストの
HTTP/1.1 200 OK
Content-Type: application/json
{
"code_token": "eyJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL3RvLmV4YW1wbGUub3Jn
IiwiZnJvbV9jbGllbnQiOiJodHRwczovL2Zyb20uZXhhbXBsZS5vcmciLCJpc3MiOiJodHRw
czovL2lkcC5leGFtcGxlLm9yZyIsInJlZl9oYXNoIjoic1JJYWRBOExoTVNiN01VaXpiVEdY
QSIsInN1YiI6InA5LUZweFh4WEJ0NVBRck05LTZULXQzbDllU3oxbiIsInVzZXJfdGFnIjoi
aW52aXRlciIsInVzZXJfdGFncyI6WyJpbnZpdGVlIl19.jDVEXyRvEwx0CV26I5Hl2JxWgco
6col4KobOiQSbEEcmGcyMCP8GX_tW8xEctpEPuTLzUBfMnjBaJGkZzH67YA",
"referral": "eyJhbGciOiJFUzI1NiJ9.eyJhdWQiOlsiaHR0cHM6Ly9pZHAyLmV4YW1wbGUub3
JnIl0sImV4cCI6MTQyNTQ1MjgzNSwiaGFzaF9hbGciOiJTSEEyNTYiLCJpc3MiOiJodHRwcz
ovL2lkcC5leGFtcGxlLm9yZyIsImp0aSI6InlHLTh4Zm1Pb1Q3RDRERE0iLCJyZWxhdGVkX3
VzZXJzIjp7Im9ic2VydmVyIjoiR2JyOTNrdnRIUGt1VVg0WWxSRDRRQSJ9LCJzdWIiOiJodH
RwczovL2Zyb20uZXhhbXBsZS5vcmciLCJ0b19jbGllbnQiOiJodHRwczovL3RvLmV4YW1wbG
Uub3JnIn0.YjH8_n8D00qjIDtbBQW1JpkxBoDFs78Eepo0Jn1WeI8PjTdDCiwZy8ZcvOfJTi
soEFPunjWYplVE7wqUUV9mxw"
}
JWT の改行とインデントは表示の都合による。
code_token
のクレームセットの内容は、
{
"iss": "https://idp.example.org",
"sub": "p9-FpxXxXBt5PQrM9-6T-t3l9eSz1n",
"aud": "https://to.example.org",
"from_client": "https://from.example.org",
"user_tag": "inviter",
"user_tags": [
"invitee"
],
"ref_hash": "sRIadA8LhMSb7MUizbTGXA"
}
referral
のクレームセットの内容は、
{
"iss": "https://idp.example.org",
"sub": "https://from.example.org",
"aud": [
"https://idp2.example.org"
],
"exp": 1425452835,
"jti": "yG-8xfmOoT7D4DDM",
"to_client": "https://to.example.org",
"related_users": {
"observer": "Gbr93kvtHPkuUX4YlRD4QA"
},
"hash_alg": "SHA256"
}
署名には以下の鍵を用いた。
{
"kty": "EC",
"crv": "P-256",
"x": "3tfF_QYgrjnyDzRPycEyx0yZUvX2xZS8JFQb74c91Og",
"y": "uTrU4RGQ6ospbXLTKEQZnNSQavQ6IeWcm1EIqNWleOg",
"d": "8VSjWeZq44mW3GXSd9pXHcERnrB2D6FEj5Lw59QgNBo"
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"code_token": "eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJodHRwczovL3RvLmV4YW1wbGUub3Jn
IiwiaXNzIjoiaHR0cHM6Ly9pZHAyLmV4YW1wbGUub3JnIiwicmVmX2hhc2giOiJzUklhZEE4
TGhNU2I3TVVpemJUR1hBIiwic3ViIjoieG9LcE9LQ2xEM1VRTktuOHBscXd0NEVGd3VuLVZy
IiwidXNlcl90YWdzIjpbIm9ic2VydmVyIl19.s5Z_ipRg-lbbGrQnjlXq6HksZh01SpSKZeN
rL7R2MSTZ3ZCtPlXMIMVscSaP5FabatDaBAVKBhA6RFvJXvLSWVwtFX2v25-aNWMHywgmtnR
EKyrmcjNylZ4s52MEO0um35nFqXqr4BDdk0xS70jQt41Qg8tJiUm7kKjiy74t_Hp5s82Hpxy
7zJ4BOUe3laexZkU42mBf383_jqEyDL4CMndtfaCkVKv14M1hjfP8cscRGuNT_ZDpMDodV54
ubjtVc6rsNRnCTwd9DZU2UE5CkXSu930hOw8LnGlk56QN7xloI0EEWZdohZFkDLkxv84ozWm
66VuAIlSuvE8WRd3fHQ"
}
JWT の改行とインデントは表示の都合による。
code_token
のクレームセットの内容は、
{
"iss": "https://idp2.example.org",
"sub": "xoKpOKClD3UQNKn8plqwt4EFwun-Vr",
"aud": "https://to.example.org",
"user_tags": [
"observer"
],
"ref_hash": "sRIadA8LhMSb7MUizbTGXA"
}
署名には以下の鍵を用いた。
{
"kty": "RSA",
"n": "2Tv_db3EjCJYgY4USmfVd2yjMZroIV4b9VR2SgW71Rq85likqd8hvcXI6BZV6rdKpqDEzQ
1u-n3R5L2-9SCrece4HbngprXsvuYluLEtOkdrJy14ne55vawEstF9TRCcw7GT0aY-x91Uc-
3Lc-D9FirkZua4Bz-mqQfFoe37XXZr_FFxk0yws9tyzbnj9Rl4lJs9fecVTP8qNjg8UBOTaV
fb716Qud3fKepTkyhyeet3x5tAn_MTGJAbGhoFnzFvcyUFbY9eGv67wd50TxXD9RAo98IfBN
LxXukxngnFeCSRom4u1Pvh4UNqedOBOF6hU1CmRdAzksvd6zqhRCpjQQ",
"e": "AQAB",
"d": "tdVj0uFiiM4i-Wa9Ez7wzsMPovEARxXoHyVw0isUe5-i6MjgJBTSwG-y6JnxlsOP6AQAV4
dcEq6Ip4gwNC0Be7EyKyewpLr5DR3GC1-69OJdDfEg2kmIe7xmPmveD0jNf3y_t6gJOvDHxT
YRq9By6EBE6OFMvzyHO0t3IUD7u9FdWSOIZu0OE_fpoEOzvmOnNOyjocOWxJRjTPFVFLJE4m
REXxksb3HZ0g2NlvFquiGNRtWD4zdMJ49UyjEgO3eJQ-fWrsyPJPi08S91715jjgd1MoEzz2
xrFuIbO7IPhiVmjgdVPER61LMg7TiKHCklhU7MlR8H7pSnHkYqVMcLAQ",
"p": "_e_r1JP9FeqYyFeTbhZoDDUm_vaziFAuZwLDfwWttPnbsWzE_puDEeOY8PbsvJd7fmbX2t
pnSoOfuYW6b3fh3SxpHNcvDHK7qbC22DGI_wkxY01aHV_LfS9GljCqXP7bBWdoXAqc8678Jm
QQ2MJwznVkp5X1N6XvHeoJoCg8B5E",
"q": "2v_AM0foiU3_3T-Hpz9igct-OnT3tkvUuZ5nbN6ejWVBRN2ogtBLN_SVfgxMgLNTcxG0vt
dVpMZofsRobFnyA9tGH50pFGsr04Uf3gOvhbf1QB6WBxoLhoUh6xMJ1Y1Ab2XXDX6ZauAObX
QXJ_N4hgckIYAv5ODaKoRr-W2SqLE",
"dp": "ZwZY-sUT0Dl-xQFq6iYjDpjd-mFi03IccWSYpkdKg3s_m8tSXS4Azlg1q8WypI0c6FqXR
s6HS579RYqw6hqMQ2yKNM5E41sFMkJk3G-0cixrois23WYJK__rNnIGHHa1q4qZt4YCyYb7_
CNrBlZU6B6OuMNJWstyqQNT5muMd1E",
"dq": "c71uiquaTdaXPwrwWoe5O_ecArEGqaVyC5eX-YW-LeQxln-_K0OCPVRaHX_KfspHdC0LZ
UDQ1oC1gSm0Nm9i5H7ilJqut0fcpbFZojA4d2c9imGf0KkHJlT-FAq_y8kXIMil20_pLP61I
UuVYVvfepYTllD0_vWG16mclvo95EE",
"qi": "8tKplcbM5koJZEnZrjulDQNme1CQClHrEip-nPrvSQSd8yAC5MVFLl1GYq8MSNLT9eJ7W
L2n9MOj1bBy2649qYiE0G2XEULgYPyVu5gciOConXDjSfhcZWxZcOMm3KzTT6451an6reHDY
efcjdlgCQmU498Thy7XZnJhCwUFXgE"
}
連携元 TA は連携元仲介レスポンスのパラメータとその JWT に含まれるクレームを検証するべきである。
特に、user_tag
と user_tags
クレームにリクエストしたアカウントタグが含まれていることを確認すべきである。
また、JWT の署名を検証しても良い。
連携元 TA から連携先 TA の処理エンドポイントに、仲介データを付加してリクエストを送る。
処理要請エンドポイントは TLS で提供しなければならない。
仲介データは IdP から受け取った全ての code_token
値の配列である。
仲介データの付加は URL クエリ、HTTP ヘッダのどちらかで行う。
空白区切りで code_tokens
パラメータに入れる。
GET /api/invite/invitee?
code_tokens=eyJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL3RvLmV4YW1wbGUub3JnIiw
iZnJvbV9jbGllbnQiOiJodHRwczovL2Zyb20uZXhhbXBsZS5vcmciLCJpc3MiOiJodHRwczovL2l
kcC5leGFtcGxlLm9yZyIsInJlZl9oYXNoIjoic1JJYWRBOExoTVNiN01VaXpiVEdYQSIsInN1YiI
6InA5LUZweFh4WEJ0NVBRck05LTZULXQzbDllU3oxbiIsInVzZXJfdGFnIjoiaW52aXRlciIsInV
zZXJfdGFncyI6WyJpbnZpdGVlIl19.jDVEXyRvEwx0CV26I5Hl2JxWgco6col4KobOiQSbEEcmGc
yMCP8GX_tW8xEctpEPuTLzUBfMnjBaJGkZzH67YA%20
eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJodHRwczovL3RvLmV4YW1wbGUub3JnIiwiaXNzIjoiaHR
0cHM6Ly9pZHAyLmV4YW1wbGUub3JnIiwicmVmX2hhc2giOiJzUklhZEE4TGhNU2I3TVVpemJUR1h
BIiwic3ViIjoieG9LcE9LQ2xEM1VRTktuOHBscXd0NEVGd3VuLVZyIiwidXNlcl90YWdzIjpbIm9
ic2VydmVyIl19.s5Z_ipRg-lbbGrQnjlXq6HksZh01SpSKZeNrL7R2MSTZ3ZCtPlXMIMVscSaP5F
abatDaBAVKBhA6RFvJXvLSWVwtFX2v25-aNWMHywgmtnREKyrmcjNylZ4s52MEO0um35nFqXqr4B
Ddk0xS70jQt41Qg8tJiUm7kKjiy74t_Hp5s82Hpxy7zJ4BOUe3laexZkU42mBf383_jqEyDL4CMn
dtfaCkVKv14M1hjfP8cscRGuNT_ZDpMDodV54ubjtVc6rsNRnCTwd9DZU2UE5CkXSu930hOw8LnG
lk56QN7xloI0EEWZdohZFkDLkxv84ozWm66VuAIlSuvE8WRd3fHQ HTTP/1.1
Host: to.example.org
改行とインデントは表示の都合による。
カンマ区切りで X-Edo-Code-Tokens ヘッダに入れる。 複数の X-Edo-Code-Tokens ヘッダに分けて付加しても良い。
GET /api/invite/invitee HTTP/1.1
Host: to.example.org
X-Edo-Code-Tokens: eyJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL3RvLmV4YW1wbGUub3Jn
IiwiZnJvbV9jbGllbnQiOiJodHRwczovL2Zyb20uZXhhbXBsZS5vcmciLCJpc3MiOiJodHRwczov
L2lkcC5leGFtcGxlLm9yZyIsInJlZl9oYXNoIjoic1JJYWRBOExoTVNiN01VaXpiVEdYQSIsInN1
YiI6InA5LUZweFh4WEJ0NVBRck05LTZULXQzbDllU3oxbiIsInVzZXJfdGFnIjoiaW52aXRlciIs
InVzZXJfdGFncyI6WyJpbnZpdGVlIl19.jDVEXyRvEwx0CV26I5Hl2JxWgco6col4KobOiQSbEEc
mGcyMCP8GX_tW8xEctpEPuTLzUBfMnjBaJGkZzH67YA,
eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJodHRwczovL3RvLmV4YW1wbGUub3JnIiwiaXNzIjoiaHR
0cHM6Ly9pZHAyLmV4YW1wbGUub3JnIiwicmVmX2hhc2giOiJzUklhZEE4TGhNU2I3TVVpemJUR1h
BIiwic3ViIjoieG9LcE9LQ2xEM1VRTktuOHBscXd0NEVGd3VuLVZyIiwidXNlcl90YWdzIjpbIm9
ic2VydmVyIl19.s5Z_ipRg-lbbGrQnjlXq6HksZh01SpSKZeNrL7R2MSTZ3ZCtPlXMIMVscSaP5F
abatDaBAVKBhA6RFvJXvLSWVwtFX2v25-aNWMHywgmtnREKyrmcjNylZ4s52MEO0um35nFqXqr4B
Ddk0xS70jQt41Qg8tJiUm7kKjiy74t_Hp5s82Hpxy7zJ4BOUe3laexZkU42mBf383_jqEyDL4CMn
dtfaCkVKv14M1hjfP8cscRGuNT_ZDpMDodV54ubjtVc6rsNRnCTwd9DZU2UE5CkXSu930hOw8LnG
lk56QN7xloI0EEWZdohZFkDLkxv84ozWm66VuAIlSuvE8WRd3fHQ
改行とインデントは表示の都合による。
連携先 TA は以下のように処理要請リクエストを検証しなければならない。
- 仲介データが付加されていることを確認する。
- 仲介データの各 JWT を署名済み JWT として検証する。
- 仲介データの各 JWT が必要なクレームを含むことを確認する。
- 仲介データに複数の JWT が含まれる場合、
ref_hash
クレームが含まれ、値が等しいことを確認する。 - 仲介データの中に
user_tag
クレームを含む JWT がただ 1 つだけ存在することを確認する。 - 異なるアカウントに同じアカウントタグが付けられていないことを確認する。
検証に失敗したときのエラーレスポンスの形式は連携先 TA の裁量である。
error
の値を invalid_request
とした OAuth 2.0 Section 5.2 形式にすることを推奨する。
連携先 TA から IdP の連携先仲介エンドポイントにリクエストを送る。
IdP は連携先仲介エンドポイントを TLS で提供しなければならない。
連携先仲介リクエストは、以下の最上位要素を含む JSON オブジェクトである。
grant_type
- 必須。
cooperation_code
でなければならない。
- 必須。
code
- 必須。 仲介コード。
claims
- 仲介コードに
user_tag
が付いていた場合は任意。 そうでなければ無し。 処理の主体に対する OpenID Connect Core 1.0 Section 5.5 のclaims
パラメータと同じもの。
- 仲介コードに
user_claims
- 仲介コードに
user_tags
が付いていた場合は任意。 そうでなければ無し。 アカウントタグから OpenID Connect Core 1.0 Section 5.5 のclaims
パラメータのid_token
要素と同じものへのマップ。
- 仲介コードに
リクエスト時の TA 認証は必須であり、OpenID Connect Core 1.0 Section 9 で定義されているクライアント認証方式を利用する。 その際、application/x-www-form-urlencoded フォームパラメータとして含めるはずのものは、代わりに JSON の最上位要素として含める。
要求した必須クレームに対する事前同意が無ければ拒否される。
POST /coop/to HTTP/1.1
Host: idp.example.org
Content-Type: application/json
{
"grant_type": "cooperation_code",
"code": "p9-FpxXxXBt5PQrM9-6T-t3l9eSz1n",
"claims": {
"id_token": {
"pds": {
"essential": true
}
}
},
"user_claims": {
"invitee": {
"pds": {
"essential": true
}
}
}
}
TA 認証用データは省いている。
POST /coop/to HTTP/1.1
Host: idp2.example.org
Content-Type: application/json
{
"grant_type": "cooperation_code",
"code": "xoKpOKClD3UQNKn8plqwt4EFwun-Vr"
}
TA 認証用データは省いている。
IdP は以下のように連携先仲介リクエストを検証しなければならない。
--f--> は失敗時のエラーレスポンスの error
の値を示す。
- 連携先 TA を認証する。
- --f-->
invalid_client
- --f-->
- リクエストが必要なパラメータを含むことを確認する。
- --f-->
invalid_request
- --f-->
code
の指す仲介コードが有効であることを確認する。- --f-->
invalid_grant
- --f-->
code
の指す仲介コードが連携先 TA 用に発行されたものであることを確認する。- --f-->
invalid_grant
- --f-->
claims
を含むなら、code
の指す仲介コードがアクセストークンに紐付くことを確認する。- --f-->
invalid_grant
- --f-->
user_claims
を含むなら、user_claims
にはcode
の指す仲介コードに紐付くアカウントタグのみが含まれることを確認する。- --f-->
invalid_grant
- --f-->
- 要求された必須クレームに対する事前同意があることを確認する。
- --f-->
access_denied
- --f-->
リクエストに問題が無ければ、IdP から連携先 TA にレスポンスを返す。
連携先仲介レスポンスは以下の最上位要素を含む JSON オブジェクトである。
access_token
- 仲介コードがアクセストークンに紐付いていた場合は必須。 そうでなければ無し。 新しく発行した処理の主体に対するアクセストークン。
token_type
access_token
を含む場合のみ。 OAuth 2.0 Section 5.1 のtoken_type
と同じもの。
expires_in
access_token
を含む場合のみ。 OAuth 2.0 Section 5.1 のexpires_in
と同じもの。
scope
access_token
を含む場合のみ。 OAuth 2.0 Section 5.1 のscope
と同じもの。
ids_token
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "EM0VI_NbAd-ClytRWFQU3WNONsZRYr",
"expires_in": 1037,
"ids_token": "eyJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL3RvLmV4YW1wbGUub3JnI
iwiZXhwIjoxNDI1NDUzNzAyLCJpYXQiOjE0MjU0NTI2NjUsImlkcyI6eyJpbnZpdGVlIjp7I
nBkcyI6eyJ0eXBlIjoic2luZ2xlIiwidXJpIjoiaHR0cHM6Ly9wZHMuZXhhbXBsZS5vcmcvI
n0sInN1YiI6ImI3d1BOS0dEbUdTRTRjRmE2Z3Q3THlNdERwNVYzcmJJUnVOQmdfLWdlLVEif
SwiaW52aXRlciI6eyJwZHMiOnsidHlwZSI6InNpbmdsZSIsInVyaSI6Imh0dHBzOi8vcGRzL
mV4YW1wbGUub3JnLyJ9LCJzdWIiOiJESUUwUER6N1JyY29Cdmo2M2t4Z2hUMkVaT2xiUHBuQ
3BFbUlXRUNzazdVIn19LCJpc3MiOiJodHRwczovL2lkcC5leGFtcGxlLm9yZyIsInN1YiI6I
mh0dHBzOi8vZnJvbS5leGFtcGxlLm9yZyJ9.gRkwnH2utpBNykR8yeRmSJH-Y0qro-U85wm9
v8aX_4ZzGWU-AFCrvF4BhiCDWi9pgS0zSPQ_YtlFbCHT8VY7Tg"
}
JWT の改行とインデントは表示の都合による。
ids_token
のクレームセットの内容は、
{
"iss": "https://idp.example.org",
"sub": "https://from.example.org",
"aud": "https://to.example.org",
"exp": 1425453702,
"iat": 1425452665,
"ids": {
"inviter": {
"sub": "DIE0PDz7RrcoBvj63kxghT2EZOlbPpnCpEmIWECsk7U",
"pds": {
"type": "single",
"uri": "https://pds.example.org/"
}
},
"invitee": {
"sub": "b7wPNKGDmGSE4cFa6gt7LyMtDp5V3rbIRuNBg_-ge-Q",
"pds": {
"type": "single",
"uri": "https://pds.example.org/"
}
}
}
}
署名に使用した鍵は処理の主体が属す IdP からの連携元仲介レスポンス例と同じ。
HTTP/1.1 200 OK
Content-Type: application/json
{
"ids_token": "eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJodHRwczovL3RvLmV4YW1wbGUub3JnI
iwiZXhwIjoxNDI1NDUzNzA1LCJpYXQiOjE0MjU0NTI2NjgsImlkcyI6eyJvYnNlcnZlciI6e
yJzdWIiOiItdkE1Y2FTVkFFQ1daT19QTW91eVl6dlFFZUZWSXVOTXo5eEdFRUxXZGRvIn19L
CJpc3MiOiJodHRwczovL2lkcDIuZXhhbXBsZS5vcmciLCJzdWIiOiJodHRwczovL2Zyb20uZ
XhhbXBsZS5vcmcifQ.hQFSF7kZBHQI-cF9kP4WYcWoWve_YICgaUTu8FnzkYDXd7v2FOctff
3akGhQUBFjM6ZtX3BInBxVGfKxkD7aZP5E44KM8VMXYineyrEpcGeTehuIFnqjkOnzHz-yxe
SLAtpTN-SPq0cupWeOwMFo2ehp6pHViJ34BpVhnkS8eTRXeGvlidA_Zzg5u8X5zpVcz9klVq
g-wSBdfbojTgV5xdxaIS9X7pa7-jm2-2o-Y54WO1umh_EgXWYOTdj0H9wLYq7YFqN7ubQv-T
j15ddA0xFkvxRt33D04521kjnhT5qn4Erx9iQcTSm6DqcEW2LhGEhgzu01EhNZHPYQYpMzWg"
}
JWT の改行とインデントは表示の都合による。
ids_token
のクレームセットの内容は、
{
"iss": "https://idp2.example.org",
"sub": "https://from.example.org",
"aud": "https://to.example.org",
"exp": 1425453705,
"iat": 1425452668,
"ids": {
"observer": {
"sub": "-vA5caSVAECWZO_PMouyYzvQEeFVIuNMz9xGEELWddo"
}
}
}
署名に使用した鍵は処理の主体が属さない IdP からの連携元仲介レスポンス例と同じ。
連携先 TA は、以下のように連携先仲介レスポンスを検証しなければならない。
- 必要なパラメータを含むことを確認する。
ids_token
の値を署名済み JWT として検証する。ids_token
の値の JWT に含まれるids
クレームに、リクエストに対応するアカウント情報が含まれることを確認する。
以下の条件を満たす場合、セッションを確立することによって、以後の連携では上記プロトコルを省いても良い。
- 連携先仲介レスポンスで送られたアクセストークンが有効である。
- 連携先仲介レスポンスで送られた処理の主体以外のアカウントの属性が
iss
とsub
のみである。
条件を満たし、プロトコルを省略する場合、まず、連携先 TA から連携元 TA へのレスポンスにおいて、Set-Cookie ヘッダで以下のセッションを通知する。
Cookie 名 | 値 |
---|---|
Edo-Cooperation | セッション ID |
以後、連携元 TA から連携先 TA へのリクエストにおいて、このセッションを Cookie ヘッダで宣言する。 アカウントタグは最初に使われたものを暗黙に用いる。
IdP からのエラーは OAuth 2.0 Section 5.2 の形式で返す。
連携先 TA において、本プロトコルでのエラーが発生した場合、連携元 TA へのレスポンスに以下のヘッダを含めなければならない。
HTTP ヘッダ | 値 |
---|---|
X-Edo-Cooperation-Error | 適切なメッセージ |
その他の形式は連携先 TA の裁量である。 OAuth 2.0 Section 5.2 形式にすることを推奨する。