メインコンテンツまでスキップ
プレビュー版
PocketSign Link v2 は現在プレビュー版です。正式提供までに仕様が変更される可能性があります。

OIDC / OAuth2 セキュリティ

このページでは、PocketSign Link v2 と連携する RP がブラウザベースの Authorization Code Flow で最低限押さえるべきセキュリティ要点を整理します。

最初に押さえるべきこと

:::warning 必須のセキュリティ要件 ブラウザベースの RP では、少なくとも次をセットで実装してください。これらは安全性に直結する項目であり、省略すると脆弱性の原因になります。

  • state を付けてコールバック時に照合する
  • PKCE を使い、code_challenge_method=S256 を付ける
  • nonce を付けて、返ってきた id_tokennonce を照合する
  • redirect_uri を固定し、認可時とトークン交換時で完全一致させる
  • id_token の署名、issaudexp を検証する
  • トークンや認可コードをログに出さない :::

state

state は、サービスが開始した認可リクエストと、後で戻ってくるコールバックを結び付けるための値です。 主な目的は、別のリクエストに対するコールバックを誤って受け入れないようにすることです。

使い方

  • 認可開始時にランダムな値を生成する
  • サービス側のセッションや一時ストアに保存する
  • コールバックで返ってきた state と必ず一致確認する
  • 一致しなければ失敗として扱う

注意点

  • 推測しやすい値や連番を使わない
  • 1 回使った state は再利用しない

PKCE

PKCE は、認可コードを横取りされても、そのコードだけでは token 交換できないようにする仕組みです。 サービスは認可開始時に code_challenge を送り、token 交換時に元の code_verifier を送ります。

PocketSign Link v2 のブラウザフローでは、code_challenge_methodS256 のみサポートします。

流れ

  1. サービスがランダムな code_verifier を生成する
  2. サービスが S256(code_verifier) から code_challenge を作る
  3. authorizecode_challengecode_challenge_method=S256 を送る
  4. tokencode_verifier を送る
  5. PocketSign Link v2 が両者の対応を検証する

authorize の例

GET /api/oidc/v1/authorize
?client_id=7f3b41e2-a81c-4e35-b08d-2c7e60a4d073
&redirect_uri=https%3A%2F%2Frp.example.com%2Fcallback
&response_type=code
&scope=openid
&state=8f2c...
&nonce=6b11...
&code_challenge=BASE64URL(SHA256(code_verifier))
&code_challenge_method=S256

token の例

curl -X POST "https://id.mock.klon.you/api/oidc/v1/token" \
-u "7f3b41e2-a81c-4e35-b08d-2c7e60a4d073:client-secret" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=SplxlOBeZQQYbYS6WxSbIA" \
-d "redirect_uri=https://rp.example.com/callback" \
-d "code_verifier=random-verifier"

注意点

  • code_verifier は十分ランダムに生成する
  • code_verifier は認可コードごとに作り直す
  • plain ではなく S256 を使う
  • サーバー側で code_verifier を安全に保持し、使い終わったら破棄する

nonce

nonce は、id_token がその認可要求に対応するものかを確認するための値です。 特にブラウザフローで id_token を受け取る場合は、nonce を付けて検証するのが安全です。

使い方

  • 認可開始時にランダムな nonce を生成する
  • サービス側で保存しておく
  • token レスポンスの id_token に入っている nonce と照合する
  • 一致しなければ失敗として扱う

注意点

  • statenonce は目的が違うので、片方だけで済ませない
  • openid を使って id_token を受け取るなら nonce を付ける前提で実装する

redirect_uri

redirect_uri は認可結果の戻り先です。

守ること

  • クライアント設定に登録した URI を使う
  • 環境ごとに許可した URI だけを明示登録する

クライアント認証

トークエンドポイントなどでは、サーバー間通信でクライアント認証を行います。 認可コードを持っているだけの第三者が、勝手にトークン交換できないようにするためです。

代表的な方式

  • client_secret_basic
  • client_secret_post
  • private_key_jwt

注意点

  • client_secret をフロントエンドへ配布しない
  • シークレットは安全なサーバー側設定に置く

ID トークン検証

id_token は受け取っただけで信用せず、必ず検証してください。

最低限確認する項目

  • 署名が jwks_uri の鍵で検証できること
  • iss が想定した PocketSign Link v2 の Issuer であること
  • aud に自分の client_id が含まれること
  • exp が切れていないこと
  • nonce を送った場合は一致すること

追加でよく見る項目

  • auth_time: 直近認証が必要な画面で確認する
  • acr: 求めた認証強度を満たしているか確認する
  • amr: どの認証手段で認証したか確認する
  • sub: RP 内の利用者識別子として使う

アクセストークンとリフレッシュトークンの扱い

トークンは権限そのものなので、漏えい前提で扱わないことが重要です。

アクセストークン

  • HTTPS でのみ送る
  • API 呼び出し以外の目的で使わない
  • 必要に応じて introspect で失効確認する

リフレッシュトークン

  • サーバー側で安全に保管する
  • ローテーション前提で実装する
  • ログや監視イベントにそのまま出さない

PAR

authorization_details などで認可リクエストが大きくなる場合や、ブラウザ上での改変可能性を下げたい場合は PAR(Pushed Authorization Requests) を使うと安全です。

PAR の効果

  • 認可パラメータ一式をサーバー間で先に確定できる
  • ブラウザには client_idrequest_uri だけを載せられる
  • 長いクエリ文字列を避けやすい

注意点

  • request_uri は使い捨てとして扱う
  • expires_in 内に使う
  • authorizeclient_id も一致させる

関連ページ