Skip to content

Instantly share code, notes, and snippets.

@ritou
Last active June 14, 2019 08:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ritou/f05d51b57893da8cc50445ffb9f62a17 to your computer and use it in GitHub Desktop.
Save ritou/f05d51b57893da8cc50445ffb9f62a17 to your computer and use it in GitHub Desktop.

OIDCIBADEMO 使い方

関連仕様

Authentication Device の準備

ユーザーが利用するAuthentication Deviceとして、PC/AndroidのChromeあたりで動くWebアプリをADとして利用します。

URL

URL : https://oidc-ciba-demo.gigalixirapp.com/

OIDCIBADEMO_URL

ただの OIDC + CIBA + DEMO だと思った?

OIDC
   CIBA
      AD
       DEMO

ADも隠れていました。

続けます。

ログインとプッシュ通知の設定

Firebase Cloud Messaging を利用します。サポートされていない環境では動きません。サポートされていても動かない場合があります...。

ログインにはGoogleアカウントを利用します。 Firebase Authentication 使おうかとも思いましたが、普通に Google の OIDC を利用しています。

このデモではユーザー識別子とメールアドレスを利用します。

次にプッシュ通知の設定を行います。Firebaseはここでしか使っていません。

ここでプッシュ通知許可のお願いです。 世の中のニュースサイトが突然プッシュ通知を要求してしまうせいで拒否するのが体に染み付いていらっしゃる方も多いでしょう。 今回だけはどうかお願いいたします。

これで最低限の準備ができました。

WebAuthnのAuthenticatorを登録

OpenID Connect と FIDO は補完関係です。

ということで、以下の手順でAuthenticatorを設定し、下記のリクエストにて acr_values という値が指定されるとWebAuthnによる確認を求められるようにしました。

WebAuthnの登録フローに入ります。

準備ができました。

このデモをGoogleのOIDCのRPと捉えると、OIDC RP = FIDO RP のパターンとしても捉えられますね。 一方で、CIBAのプロトコルのOPと捉えると OIDC OP = FIDO RP というパターンとも捉えられます。

ということで両方の意味での組み合わせの例として利用できそうです。

話を戻して、CIBAの認証フロー、やっていきましょう。

ログアウト

デモなので、ログアウトしたらメアド、WebAuthnの公開鍵はDBから削除され、プッシュ通知も来なくなります。

使い方

Client Registration

Dynamic Client Registrationに対応しています。

(openid-configurationからのメタデータの提供は後で対応します)

$ # curl -X GET "https://oidc-ciba-demo.gigalixirapp.com/.well-known/openid-configuration"
# TODO: Configuration Response
# "registration_endpoint":"https://oidc-ciba-demo.gigalixirapp.com/api/client"

(メタデータを参照できたつもりで)上記のClient登録用エンドポイントに name を指定すると Client Credentials を取得できます。

$ curl -X POST "https://oidc-ciba-demo.gigalixirapp.com/api/client" \
-H 'Content-Type: application/json' \
-d '{"name":"SECURE DEMO CLIENT"}'

{"client_id":"01DCXP0ZMT(masked)","client_secret":"01DCXP0ZPP(masked)","name":"SECURE DEMO CLIENT"}

認証フロー : WebAuthn/FIDO 利用なし

Client が何らかの方法で取得した login_hint を使って認証要求を送ります。

$ curl -X POST "https://oidc-ciba-demo.gigalixirapp.com/api/backchannel" \
-u "01DCXP0ZMT(masked):01DCXP0ZPP(masked)" \
-H 'Content-Type: application/json' \
-d '{"scope":"openid", "login_hint":"(メールアドレス)"}'

{"auth_req_id":"01DD4M18NJKDA17GQ1NP53VWQS","expires_in":3600}

この時、うまくいっていれば Chrome の通知が送られるはずです。

こんな通知が来て、同意画面が出て来ます。

許可するとユーザーの処理はおしまいです。

ここまで終わったら、ClientはToken Endpoint に各種トークンを要求します。 実際は定期的に問い合わせ(ポーリング)をして結果が来たら処理するという感じです。 (とここまで書いてて、許可しないフローを実装するのを忘れてました。)

$  curl -X POST "https://oidc-ciba-demo.gigalixirapp.com/api/token" \
-u "01DCXP0ZMT(masked):01DCXP0ZPP(masked)" \
-H 'Content-Type: application/json' \
-d '{"grant_type":"urn:openid:params:grant-type:ciba", "auth_req_id":"01DD4M18NJKDA17GQ1NP53VWQS"}'
{
 "access_token":"THISISDUMMYACCESSTOKEN",
 "expires_in":3600,
 "id_token":"(ID Token)",
 "refresh_token":"THISISDUMMYREFRESHTOKEN",
 "token_type":"Bearer"
}

ID Tokenをデコードして見ると中身はこんな感じです。

// Header
{
  "alg": "RS256",
  "kid": "rs256_201906",
  "typ": "JWT"
}

// Payload
{
  "acr": "",
  "at_hash": "nT5n6bpBrdiOZaBp6IqwkQ",
  "aud": "01DCXP0ZMT(masked)",
  "email": "(メールアドレス)",
  "exp": 1560305756,
  "iat": 1560302156,
  "iss": "https://oidc-ciba-demo.gigalixirapp.com",
  "sub": "(ユーザーID)",
  "urn:openid:params:jwt:claim:auth_req_id": "01DD4M18NJKDA17GQ1NP53VWQS",
  "urn:openid:params:jwt:claim:rt_hash": "EsQ8Syr4u5hXmKxJ9mmiHQ"
}

acr の値は空です。

認証フロー : WebAuthn/FIDO 利用、binding messageあり

オプションパラメータとして、

  • binding_message : Client側とADで共に表示してトランザクションなどを識別できるようにする文字列
  • acr_values : 認証コンテキストの指定

をサポートしてみました。

$ curl -X POST "https://oidc-ciba-demo.gigalixirapp.com/api/backchannel" \
-u "01DCXP0ZMT(masked):01DCXP0ZPP(masked)" \
-H 'Content-Type: application/json' \
-d '{"scope":"openid", "binding_message":"W4SCT", "acr_values":"phrh", "login_hint":"ritou.06@gmail.com"}'
{"auth_req_id":"01DD7JY5JJ47T2Q51K7FPC9CZF","expires_in":3600}

通知を受け取ったら、最初にWebAuthnの確認が求められます。

同意画面には、binding_message で指定された値が表示されます。

違いはこんなところです。

$ curl -X POST "https://oidc-ciba-demo.gigalixirapp.com/api/token" \
-u "01DCXP0ZMT(masked):01DCXP0ZPP(masked)" \
-H 'Content-Type: application/json' \
-d '{"grant_type":"urn:openid:params:grant-type:ciba", "auth_req_id":"01DD7JY5JJ47T2Q51K7FPC9CZF"}'

{
  "access_token":"THISISDUMMYACCESSTOKEN",
  "expires_in":3600,
  "id_token":"(ID Tokenの値)",
  "refresh_token":"THISISDUMMYREFRESHTOKEN",
  "token_type":"Bearer"
}

ID Tokenの中身を見ると、acr の値が phrh になっています。

// Header
{
  "alg": "RS256",
  "kid": "rs256_201906",
  "typ": "JWT"
}

// Payload
{
  "acr": "phrh",
  "at_hash": "nT5n6bpBrdiOZaBp6IqwkQ",
  "aud": "01DCXP0ZMT(masked)",
  "email": "(メールアドレス)",
  "exp": 1560405260,
  "iat": 1560401660,
  "iss": "https://oidc-ciba-demo.gigalixirapp.com",
  "sub": "(ユーザーID)",
  "urn:openid:params:jwt:claim:auth_req_id": "01DD7JY5JJ47T2Q51K7FPC9CZF",
  "urn:openid:params:jwt:claim:rt_hash": "EsQ8Syr4u5hXmKxJ9mmiHQ"
}

Client側からの認証コンテキスト指定を利用すれば WebAuthn/FIDO と組み合わせられるよーという感じが伝わると嬉しいです。

以上です。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment