おはようございます。ritouです。
今日はこれを読んでみます。
Self-Issued OpenID Connect Provider DID Profile v0.1
何のための仕様か
This specification defines the "SIOP DID Profile" (SIOP DID) that is a DID AuthN flavor to use OpenID Connect (OIDC) together with the strong decentralization, privacy and security guarantees of Decentralized Identifiers (DID) for everyone who wants to have a generic way to integrate Identity Wallets into their web applications.
- WebアプリケーションにIdentity Walletを統合するために
- DIDとOpenID Connectの組み合わせるための
- SIOP DID Profileじゃ!
と言うことです。
SIOPについてはもう大丈夫でしょうか?七年前の記事で良ければどうぞ。
Qiitaにもいくつか記事があります。
- OpenID Providerとして特定のWebアプリケーション(Googleとか)ではなく、モバイル端末内で動作するアプリケーションなどを利用する
openid://
と言うカスタムURIスキームを用いた認可リクエストにより呼び出され、鍵ペアを生成/管理してIDToken を返す- ユーザーの同意のもとで端末単位で保存している情報のやりとりや、使い方次第では端末の識別やリクエストが同端末から送られたことの検証などにも使おうと思えば使える
と言うものであり、仕様としてはモバイルアプリ、ブラウザのプラグイン、デバイスの機能など特定のURI呼び出しを検知して起動できる仕組みで使えるように汎用的に作られています。
この仕様では、特定のサービスではなく端末自体をOPにすると言うSIOPをDID/SSIのIdentity Walletとして使うために必要な差分なりが定義されています。
Protocol Flow
RPはWebアプリ/ブラウザベース(SPAなど)のアプリであり、モバイルもしくはデスクトップブラウザからIdentityWalletアプリを立ち上げて使う想定です。 公式の図を見てみましょう。
流れをざっくりまとめると、
- RPは "Sign-in with SSI" ボタンみたいなのを用意し、ユーザーが押すと SIOP Request を生成
openid://?<SIOP Request>
として何やかんやで Identity Walletアプリが起動する- Identity Walletアプリは OIDC/DID AuthN に従って SIOP Request を検証する
- 必要なら認証をして、その後に SIOP Response を作成する
response_mode
の指定にしたがってRPにSIOP Responseが渡される- RPはOIDC/DID AuthN に従って SIOP Response を検証する
となります。
基本的にこのSIOPの流れに、DID用の処理が追加されるイメージです。
- SIOP Request : RPは自身のDIDを含み、DIDドキュメントから検証可能な秘密鍵で署名を生成
- SIOP Response : SIOPは自身のDIDを含み、DIDドキュメントから検証可能な秘密鍵で署名を生成
それでは見ていきましょう。
Generate SIOP Request
SIOP Request は次のように定義されています。
- 互換性のため、
response_type
,scope
,client_id
を文字列で指定する - それ以外のパラメータは
request
もしくはrequest_uri
として指定する。RPのDIDもこっちで指定。
例を引用します。
openid://?response_type=id_token &client_id=https%3A%2F%2Frp.example.com%2Fcb &scope=openid%20did_authn &request=<JWT>
openid://?response_type=id_token &client_id=https%3A%2F%2Frp.example.com%2Fcb &scope=openid%20did_authn &request_uri=https%3A%2F%2Frp.example.com%2F90ce0b8a-a910-4dd0
いわゆるリクエストオブジェクトを指定、なんてのはFAPIなどのProfileでも使われているので驚きはないでしょう。
SIOPのフローでは、registration
パラメータによってRPのメタデータを登録できます。
- アルゴリズムは
RS256
に加えてES256K
、EdDSA
をサポートしなければならない - Request ObjectはDIDドキュメントに記載されている検証方法で直接/間接的に検証可能であり、RPのJWKSにより直接検証可能である必要がある
- JWKSは
jwks_uri
もしくはjwks
パラメータで指定され、jwks
の場合はkid
が一致する必要がある。jwks_uriの場合はHTTP(S) DID Resolution Bindingが必要とか... - RPはSIOP Responseを暗号化して受信することもできる
リクエストオブジェクトについても細かく書いてありますが、眠いので例示に留めます。
#header { "alg": "ES256K", "typ": "JWT", "kid": "did:example:0xab#veri-key1" } # payload { "iss": "did:example:0xab", # RP's DIID "response_type": "id_token", "client_id": "https://my.rp.com/cb", "scope": "openid did_authn", # did_authn を指定 "state": "af0ifjsldkj", "nonce": "n-0S6_WzA2Mj", "response_mode" : "form_post", "registration" : { "jwks_uri" : "https://uniresolver.io/1.0/identifiers/did:example:0xab;transform-keys=jwks", "id_token_signed_response_alg" : "ES256K" } }
SIOP Request Validation
SIOPは scope
に did_authn
が指定されていたら、OIDCで定義されている検証に加え次のような検証を行います。
iss
クレームで指定されたRPのDIDからDIDドキュメントを取得jwks_uri
が存在する場合、iss
とDIDが一致することを検証- RPのDIDドキュメントから、
kid
と一致する検証方法を取得 - SIOP Requestの検証
Generate SIOP Response
SIOPは以下のような SIOP Response を作成してRPに戻します。
sub_jwk
はkid
を含むkid
はSIOPのDIDドキュメントの検証方法を参照する DID URL
- SIOPのDIDを含む :
did
クレーム
# Header { "alg": "ES256K", "typ": "JWT", "kid": "did:example:0xab#key-1" } # Payload { "iss": "https://self-issued.me", "nonce": "n-0S6_WzA2Mj", "exp": 1311281970, "iat": 1311280970, "sub_jwk" : { "crv":"secp256k1", "kid":"did:example:0xcd#verikey-1", "kty":"EC", "x":"7KEKZa5xJPh7WVqHJyUpb2MgEe3nA8Rk7eUlXsmBl-M", "y":"3zIgl_ml4RhapyEm5J7lvU-4f5jiBvZr4KgxUjEhl9o" }, "sub": "9-aYUQ7mgL2SWQ_LNTeVN2rtw7xFP-3Y2EO9WV22cF0", "did": "did:example:0xcd" # SIOPのDID }
(ちょっと追記)通常のSIOPは鍵を生成して端末なりに保存しておくだけのイメージですが、ここではDIDを含みDIDドキュメントから検証できるようにする必要があるわけなのでこれまでのSIOPの感覚で言うと鍵の登録処理も発生しそうです。もう少し細かく追記してもらうのが良いのかなと思ったりします。
SIOP Response Validation
OIDCのSIOP Responseの検証としては
id_token
を取得id_token
がsub_jwk
の鍵で署名されたことを検証
さらに DID AuthNとして
id_token
の SIOP DID(did
) から DIDドキュメントを取得id_token
のDIDドキュメントからsub_jwk
のkid
と一致する検証方法を取得- その検証方法で
id_token
を検証
SIOP Discovery
省略します。
UX Considerations
カスタムURLスキームの扱いについて。 モバイルブラウザの場合はアプリ立ち上げるけどAndroid/iOSそれぞれで今までもいろいろ言われてきたよねと。 デスクトップブラウザの場合、もしかしたらブラウザ拡張/プラグインでサポートされるかもしれないけどうまくいかなそうならIdentity Walletのアプリを開かせてQR読み込ませるとかが必要かも。
この辺りが改善されるにはもう少し時間がかかるかもしれませんね。
Security Considerations
まずはSIOP ResponseのIDToken漏れるかも問題
- Interception of the Redirect URI : SIOP Responseを取られたらIDToken持っていかれるよ -> RP頑張れ(オープンリダイレクト作るな)
- Identity Token Leak in Browser History : ブラウザの履歴からSIOP ResponseのIDToken漏れるよ -> IDTokenの有効期限短くしたりキャッシュされないようにしたりしよう。完全な対策は難しいかも。
- Identity Token Leak to Third Party Scripts : SIOP Responseをを受ける時に3rd PartyのJSとかでIDToken持っていかれるよ -> RP頑張れ(信頼できるやつだけ使え)
対策として response_mode=form_post
使えるならう。無理な場合もあるけど。とあります。
次に Session Fixation in Cross-Device Flow として、異なるデバイス間の転送を含む場合の脅威が記載されています。 RPがQRコードからIdentity Walletを呼び出す仕様の場合、攻撃者は自らのセッションに紐付いたQRを読ませることで第3者の認証を攻撃者のセッションでできるかも。 対策としては同一セッションであることの確認、もしくは異なるデバイスでも同一ユーザーであることを別の認証方式などで確認することが必要。
Github
何かあったらここでやってるよと。
(追記)SIOP側の公開鍵登録についてもう少し説明必要では?みたいなことを書いてみました。
まとめ
- SIOPの流れにDIDの検証処理を追加するProfile
- RPが作るリクエストオブジェクトの部分がモリモリしてるがSIOPのフローは変わらない
- カスタムURIスキームやQRコード使う部分はもうちょい改善されないとUXキツそう
と言うあたりでしょうか。引き続きウォッチしていきましょう。 ではまた!