基本の14章 · 08

「ログインできる」と「操作してよい」を分ける

本人・役割・所有者・追加認証を重ねて、画面の裏側でも守る仕組みを読む。

本文の説明・図・掲載コードだけで読み進められます。出典リンクは、権限のある人向け(非公開GitHub)です。GitHubで閲覧権限がある方だけ開けます。

この記事でわかること

  • 認証は本人確認、認可はその操作を許してよいかの判断
  • RLS と関数内の確認は、別の入口に備える防御
  • TOTP は固定した振込内容とセッションに結び付けて使う
この記事の目次
01 / READ THE SYSTEM

受付で名前が分かっても、金庫は開かない

架空の利用者・山田さんがログインし、佐藤さんの口座番号を入力したとします。ログインの成功が教えるのは「いま操作しているのは山田さん」ということだけです。佐藤さんの残高を読む権利や、佐藤さんの口座から出金する権利は生まれません。本人を確かめる認証と、対象への操作を許す認可を分けることが、MiniBank の安全性を読む出発点です。

顧客 API は受け取ったトークンを、そのまま信用せず Supabase Auth に問い合わせます。中身に利用者 ID が書いてあるだけでは証明にならないからです。その後も、検証済みの利用者のトークンを DB への接続に引き継ぎます。サーバーを通ったという理由だけで、全員が強い管理権限に変わる構造にはしていません。

根拠:本人を確かめる API(非公開GitHub・要権限)

根拠:利用者権限を保つ接続(非公開GitHub・要権限)

02 / READ THE SYSTEM

入口と、届いた行の両方を守る

データベースには二つの関門があります。権限は「この表を読む操作をしてよいか」を決め、RLS は「その中のどの行に届いてよいか」を決めます。口座の基礎設定では、ログイン利用者に読取りだけを与え、本人の顧客レコードにつながる口座へ絞っています。ブラウザから口座表を直接更新する権限は与えません。

一方、送金などの業務は、決められた関数という受付を通します。強い権限で動く関数では、RLS がすべてを代わりに守るとは限らないため、関数内でも本人、所有、役割、状態を確認します。v2 の強化は、画面でボタンを隠すだけでなく、別の API 経路から来ても条件を満たさなければ断る方向でした。

1Auth誰からの要求か
2権限・RLSどのデータへ届くか
3業務関数この状態で許せるか

根拠:口座の行単位制御(非公開GitHub・要権限)

根拠:v2 の認可・整合性強化(非公開GitHub・要権限)

03 / READ THE SYSTEM

「さっきは担当者だった」を通さない

管理担当の高橋さんが口座を凍結しようとした瞬間、別の責任者が高橋さんを無効化する場面を考えます。最初に権限を調べ、その後で長く待つ処理では、実行時には失われた権限を使ってしまう恐れがあります。画面に「管理者」と表示されていても、判断の鮮度は保証できません。

管理操作の強化では、操作者の権限レコードをロックして状態を読み、処理の間その判断が変わらないようにしています。複数の記録をつかむ順序もそろえます。並行処理の自由度は下がりますが、誰の権限で変更を確定したかが曖昧になるより重要です。ロックは画面の待ち時間を減らす道具ではなく、判断と確定を一続きにする道具です。

根拠:管理操作の権限とロック(非公開GitHub・要権限)

04 / READ THE SYSTEM

認証コードを「この振込」に結び付ける

追加認証の TOTP は、認証アプリに短時間表示される番号です。しかし番号自体には「佐藤さんへ一万円」という情報は入っていません。そこで v7 の設計は、出金元、宛先、金額、通貨、期限などをサーバー側の変更できない振込意図として保存し、その意図へ新しい認証を結び付けます。

ブラウザの「認証できました」という自己申告では承認しません。認証 API は、あらかじめ結び付けたチャレンジと試行を使い、Auth が持つ確認記録、本人、同じセッション、時刻の関係を確かめます。過去に追加認証済みのセッションがあるだけでも不足です。これにより、別のタブや別の依頼で済ませた認証を使い回す隙間を小さくします。

1内容を固定金額・宛先・期限
2新しく認証意図と試行を関連付け
3DB で確認同じ本人・セッション
4一度だけ使用今回の依頼で消費する

認証の秘密の扱いにも境界があります。認証器を登録するための QR は、その本人のブラウザへ一度見せる必要がありますが、申請の証跡や画面写真へ残してよい資料ではありません。入力した番号はブラウザから Auth に送り、MiniBank の API には番号そのものではなく、意図と試行の識別子を渡します。便利なデバッグのために秘密を記録すると、認証を強くしたつもりで別の入口を開いてしまいます。また、Auth が管理する情報は、その管理者を含めた信頼の範囲にあります。「アプリの表に保存しない」と「どこにも秘密が存在しない」は同じ主張ではありません。設計を読むときは、何を、誰へ、どの瞬間だけ見せる必要があるかまで考えると、データの流れが具体的になります。

根拠:TOTP と振込意図の設計(非公開GitHub・要権限)

根拠:現行の振込認証 API(非公開GitHub・要権限)

05 / READ THE SYSTEM

認証の成功と、お金の成功は別に読む

認証後に通信が切れると、山田さんには成功画面が届かないことがあります。それでも直ちに新しい振込を作ってはいけません。認証に成功したこと、振込が確定したこと、画面に結果が届いたことは別の出来事です。元の依頼の状態と識別子を保って確認することで、再操作が二重送金へ変わるのを避けます。確定処理で金融更新が失敗した場合、その内側の更新は取り消されても、認証の消費や失敗した依頼・監査の記録は残り得ます。認証が未使用に戻ったと決めつけないことも大切です。

認証回数や交換できるチャレンジには上限と待機時間があります。使いやすさとの交換条件ですが、番号を繰り返し試す経路を無制限にしないためです。また、法人で TOTP を終えても、それは別人による業務承認を代行しません。本人が操作したことと、会社が支払を認めたことは、違う責任だからです。

実装を読む:二つの成功を混ぜない

次は流れを説明するための擬似コードです。実行用のコードではありません。

本人を検証する
固定された振込意図を読む
同じセッションの新しい認証記録を確認する
今回の認証を一度だけ消費し、金融処理へ進む
応答が不明なら、元の依頼の結果を確認する

根拠:TOTP と振込意図の設計(非公開GitHub・要権限)

根拠:認証の消費と、金融処理失敗後の記録(非公開GitHub・要権限)

06 / READ THE SYSTEM

強い説明ほど、保証の範囲を添える

TOTP はフィッシングに強い取引署名だとは説明できません。認証器をすべて失った場合に、古いデモ番号や管理者の代理送金へ戻る仕組みも、この設計の解決策にはなっていません。安全な失敗は、ときに利用者を止めることを意味します。その停止からどう復帰させるかは、別の本人確認と運用の設計が必要です。

また、管理操作の二者確認は、提出者と確認者が別人かを見る統制です。管理者の全操作に TOTP を要求する意味ではありません。v20 の受容リスクにも、この違いが記録されています。本章が説明したのは固定ソースの設計と実装であり、現在の公開環境の設定、各役割の実動作、攻撃への完全な耐性を新しく証明したものではありません。

根拠:v20 停止と監査の記録(非公開GitHub・要権限)

根拠:2026年10月3日の修復 RC 記録(非公開GitHub・要権限)

SOURCE NOTES

出典と、確認できた範囲

コードの説明と、稼働環境の検証を分けます

以下のリンクは非公開GitHubへの出典で、閲覧権限が必要です。本文はリンク先を開かなくても読める構成です。固定コード・設計資料を参照していますが、今回、この読み物のために銀行の取引やDB操作、本番試験は実行していません。実装や資料にある検査と、こちらで実施した検証を混同しないようにしています。

  1. 本人を確かめる API ↗(非公開GitHub・要権限)
    Bearer トークンを Auth で検証する境界
  2. 利用者権限を保つ接続 ↗(非公開GitHub・要権限)
    利用者のトークンを DB へ引き継ぐ設計
  3. 口座の行単位制御 ↗(非公開GitHub・要権限)
    本人の口座の読取りと直接更新の禁止
  4. v2 の認可・整合性強化 ↗(非公開GitHub・要権限)
    所有者・本人確認・口座状態を確認する歴史的な強化点
  5. 管理操作の権限とロック ↗(非公開GitHub・要権限)
    口座凍結・KYC・管理者変更の権限再確認
  6. TOTP と振込意図の設計 ↗(非公開GitHub・要権限)
    新しい認証を金額・宛先・セッションへ結び付ける契約
  7. 現行の振込認証 API ↗(非公開GitHub・要権限)
    検証済み利用者と秘密を使う限定的な認証仲介
  8. v20 停止と監査の記録 ↗(非公開GitHub・要権限)
    修正履歴・検証範囲・受容した限界
  9. 2026年10月3日の修復 RC 記録 ↗(非公開GitHub・要権限)
    追加修復と最新記録時点の検証・未実施の範囲
  10. 認証の消費と確定の失敗処理 ↗(非公開GitHub・要権限)
    認証の消費後、金融更新だけを内側で巻き戻して失敗依頼と監査を保存する境界

MiniBankは学習・検証用の銀行アプリです。架空の金額や人物は、仕組みを説明するための例です。

つながる読み物

ここまで読んだ記録を、ひとつ。

自分のペースで。あとから取り消すこともできます。

次の読み物預金・定期預金・融資を「約束」として読む
→