銀行エンジニアリング 29:第三者アプリに口座を見せる(OAuth・PKCE・同意)
家計簿アプリのような第三者に、パスワードを渡さずに口座の情報を見せる仕組みです。顧客の同意、使い捨ての認可コード、短命のトークンで、範囲と期間を限ります。MiniBankの閉じたSandboxで確かめます。
v8以降に実装した台帳・記帳エンジンなどを実際に動かし、正常時と異常時の両方から銀行システムの構造を学ぶ。
Prerequisite: BANKING SYSTEMLEARNING GOALS
このページで学ぶこと
- パスワードを渡さない委任(OAuthの認可コード方式)
- PKCEとは何を防ぐのか
- 同意の範囲・期間・失効
PLAIN LANGUAGE
まず、ここだけつかむ
第三者のアプリにパスワードを渡さず、顧客の同意にもとづく短命の入館証(トークン)で、範囲と期間を限って情報を見せます。
認可コードは60秒・1回限りで、PKCEにより盗んでも使えません。トークンは15分で、DBにはハッシュだけを保存します。
顧客は同意をいつでも取り消せて、取り消した瞬間から使えなくなります。
DIFFICULT PARTS, STEP BY STEP
難しいポイントを、順番にほどく
専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。
OAuth(認可コード方式)
パスワードを渡さずに、範囲と期間を限って権限を委ねる仕組みです。
第三者にパスワードを預けると、やめさせにくく、何でもされてしまうためです。
openbanking.authorize_decide と public.ob_token。
PKCE
認可コードを盗まれても、トークンに交換できないようにする追加の証明です。
アプリが秘密の鍵を安全に持てない場合に、コードの盗用を防ぐためです。
S256のみ。検証子のSHA-256がチャレンジと一致しなければ拒否。
同意(consent)
顧客が、どの範囲を、いつまで許すかを決めた記録です。
許可の証拠を残し、いつでも取り消せるようにするためです。
openbanking.consents。30日間、取消しは次の呼び出しから即時。
Level 1 基礎:合鍵ではなく、期限つきの入館証を渡す
家計簿アプリに口座の残高を見せたいとき、銀行のパスワードを渡すのは危険です。パスワードがあれば、そのアプリは何でもできてしまい、やめさせるにはパスワードを変えるしかありません。
OAuthは、パスワードの代わりに『この範囲だけ、この期間だけ』を示す入館証(トークン)を、顧客の同意にもとづいて渡す仕組みです。顧客はいつでも取り消せます。
- 01アプリが顧客を銀行の同意画面へ送る
- 02顧客が範囲を確認して許可
- 03銀行がアプリの戻り先へ認可コードを返す
- 04アプリがコードをトークンに交換
- 05トークンで決められた範囲だけ読む
Level 2 銀行業務:MiniBankの登場人物と決まり
これは学習用の簡易な仕組みで、実在の認可サーバーの認証や準拠を示すものではありません。外部への通信もしません。
| 項目 | 決まり | 理由 |
|---|---|---|
| クライアント | 管理責任者が登録。名前・戻り先URI(完全一致)・許可できる範囲を持つ | 未登録のアプリや戻り先には何も渡さない |
| 範囲(scope) | accounts.read/balances.read/transactions.read/transfers.write | 必要な情報だけを許可する |
| 同意 | 顧客が範囲を確認して許可。30日間有効。いつでも取消し | 許可は期限つきで、取り消せる |
| 認可コード | 60秒・1回限り。戻り先とPKCEに束縛 | 盗まれても使えないようにする |
| アクセストークン | 15分。DBにはハッシュだけを保存 | 漏れても短時間で、DBからは復元できない |
Level 3 システム:MiniBankでの実装
- openbanking.check_authorization が、クライアントの存在と状態、redirect_uri の完全一致、PKCE(S256のみ)、state(8文字以上)、範囲がクライアントの許可内かを確かめる。違反は OB001〜OB004
- 戻り先が未登録なら、エラーを画面に表示して、リダイレクトしない。攻撃者のURIへ認可コードを送らないため
- openbanking.authorize_decide が同意と認可コードを作る。同じ顧客・同じアプリの再許可は、古い同意を失効させて新しい同意を作る
- public.ob_token(openbanking.exchange_code)が、コードとPKCEの検証子を交換する。検証子のSHA-256がコード発行時のチャレンジと一致しなければ拒否。検証子・戻り先・期限・同意の検査に失敗した試行でも、コードはその場で使用済みになり、推測を許さない(クライアントの不一致や形式の不正では使用済みにならない)
- 使用済みのコードが再び提示されたら、そのコードから出たトークンと同意を失効させる(盗用の疑い)
- トークンの平文は交換の応答で一度だけ返し、DBにはSHA-256のハッシュだけを保存する。テストで全表を検索して、平文が残らないことを確かめている
異常時:コードが2回使われた
| 段階 | 内容 |
|---|---|
| 症状 | 同じ認可コードでトークンの交換が2回来た。2回目は invalid_grant |
| 原因の候補 | アプリの再送、または誰かがコードを盗んで先に使った |
| MiniBankの動き | 1回目で出たトークンと同意を、その場で失効させる(どちらが正規か区別できないため) |
| 対応 | 顧客は同意画面でやり直す。利用状況は『外部アプリ連携』の履歴(取消の理由:認可コードの再使用)で確認できる |
Level 4 アーキテクチャ:なぜPKCEか
スマートフォンのアプリのように、秘密の鍵を安全に持てないアプリでは、認可コードが途中で盗まれる危険があります。PKCEは、アプリが毎回ランダムな検証子を作り、そのハッシュだけを最初に銀行へ渡します。コードを盗んだ人は検証子を知らないので、トークンに交換できません。MiniBankは平文のplain方式を受け付けず、S256のみです。
どこを確認すればよいか
- 顧客画面「外部アプリ連携」(/app/consents):許可の一覧、取消
- 管理画面「Open Banking」:アプリの登録・停止、同意、イベント
CHECK YOUR UNDERSTANDING
3問で理解チェック
答えを頭の中で考えてから、各項目を開いて確認してください。
Q1戻り先が登録と1文字でも違うとどうなりますか?
同意画面はエラーを表示し、認可コードを送りません(OB001)。
Q2認可コードを2回使うとどうなりますか?
2回目は拒否され、1回目で出たトークンと同意も失効します。
Q3顧客が同意を取り消すと、トークンはいつまで使えますか?
次の呼び出しから使えません。トークンは毎回、同意の状態を確認します。
完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。
SOURCE TRAIL
根拠と関連教材
CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。
確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。
Implementation Status: IMPLEMENTED IN MINIBANK(この教材が扱うコードの範囲)
- RELATED LESSON/docs/be-openbanking-api-transferトークンで何ができるか(資源APIと振込の依頼)
- RELATED LESSON/docs/security認証と認可の基本
- CURRENT IMPLEMENTATION
supabase/migrations/20260930120000_v16_open_banking.sqlopenbanking.check_authorization / openbanking.authorize_decide認可リクエストの完全一致の検査(登録済みの戻り先・PKCE・state・scope)と、同意・認可コードの発行 - CURRENT IMPLEMENTATION
supabase/migrations/20260930120000_v16_open_banking.sqlopenbanking.exchange_code / public.ob_token認可コードとPKCE検証子の交換、再使用の検知(トークンと同意の失効)、トークンはハッシュだけ保存 - CURRENT IMPLEMENTATION
supabase/migrations/20260930120000_v16_open_banking.sqlopenbanking.revoke_consent / openbanking.suspend_client同意の失効とクライアントの停止(トークンは次の呼び出しから使えない) - CURRENT IMPLEMENTATION
src/app/app/authorize/page.tsxAuthorizePage()同意画面(表示は AuthorizeConsent)。不正なクライアント・戻り先はエラー表示でリダイレクトしない - CURRENT IMPLEMENTATION
scripts/banking/v16-openbanking.test.mjs登録・認可・PKCE・コード再使用・スコープ・所有者検査・同意の失効・振込の依頼と確認・イベント/Webhook・秘密の非保存のDBテスト