AIで認証・DB・APIの接続順を設計する方法

認証・データベース・APIを組み合わせる前に、「誰がどのデータを何の目的で操作できるか」を決めます。その権限条件をデータ構造、ログイン確認、サーバー側の認可、APIへ順につなぎ、拒否すべきケースを先に確かめます。

AIものさし編集部

認証・DB・APIをAIと一緒に実装するとき、サービスの接続手順から考えるより「誰が、どのDataへ、どのActionを許可されるか」を先に決める方が安全です。Authenticationは本人確認、Authorizationは操作権限で、ログイン済みだから全Dataへアクセスできるわけではありません。

この記事では、架空のProject管理アプリを例に、Access Contract、DB構造、Auth、Server側Authorization、API、Deny Case、Loggingまでの順序を整理します。最終的には、成功ケースだけでなく「拒否すべきアクセスが拒否される」ことを検証できる状態を目指します。

最初にAccess Contractを書く

コードを書く前にRole / Resource / Action / Allow Condition / Deny Caseを表にします。

表は横にスクロールできます

RoleResourceActionAllow ConditionDeny Case
User自分のProjectRead / Updateowner_id一致他人のProject
MemberTeam ProjectReadmembershipあり未所属Team
Admin管理対象Manageadmin roleroleなし
AnonymousPublic ProjectReadis_public=trueprivate Project

この表がBackend実装の契約になります。UIの表示・非表示とは別に、Server側で同じ条件を守ります。

AuthenticationとAuthorizationを分ける

Authenticationは「このRequestを送った人は誰か」を確認する処理です。Authorizationは「その人がこのResourceへこのActionをしてよいか」を決める処理です。

ログイン済みUserがURLのIDを書き換えて他人のProjectへアクセスできるなら、Authenticationは成功していてもAuthorizationが失敗しています。この区別をAIへの実装指示でも明示します。

DBはAccess Contractを表現できる形にする

Project tableならid、owner_id、team_id、is_publicなど、Access判定に必要なFieldを持たせます。Team membershipがあるならUserとTeamのRelationも必要です。

権限を後から文字列だけで判定するより、DB上の所有関係やmembershipを明示できる方が、API側で一貫したRuleを書きやすくなります。

架空Schemaで考える

例:

users(id)

projects(id, owner_id, team_id, is_public, title)

team_members(team_id, user_id, role)

project_items(id, project_id, content)

この構造なら、Project owner、Team member、Public accessを別々に判定できます。

実際のSchemaはProduct要件で変わりますが、「Authorizationに必要なRelationをDBが持っているか」を先に確認します。

DB制約も最初に考える

Authorizationとは別に、Data Integrityを守る制約も必要です。Required Field、Foreign Key、Unique制約、StatusのAllowed Valueなどです。

AIが生成したAPI codeだけで不正Dataを防ぐのではなく、DB側でも守れる条件は守ります。どの層で何を保証するかを分けると、実装漏れを減らせます。

Authを接続したらUser IDをServerで確定する

Browserから送られたuser_idをそのまま信用しません。認証済みSessionやTokenからServer側でUserを確定し、そのIDをAccess判定に使います。

Clientから「owner_id=自分」と送られてきても、Server側で認証Identityと一致するか確認します。

最初のAPIはRead 1本だけ通す

複数Endpointを一気に作るより、まず「自分のProjectを1件読む」など最小Flowを通します。

成功ケース:Login済みUserが自分のProjectをGETして200。

Denyケース:他人のProject IDを指定して403または設計上適切な拒否。

Not Found:存在しないIDで404。

Anonymous:Private ResourceへAccessして拒否。

この4ケースを確認してからUpdateやDeleteへ進みます。

Write APIはValidation→Authorization→Writeの順で考える

Update APIでは、入力が正しいか、UserがResourceを変更できるかを確認し、その後Writeします。

どの順が適切かはFrameworkやThreat Modelで変わる部分がありますが、少なくとも「Clientが送った値だけを根拠に権限判定しない」「権限確認なしにWriteしない」を守ります。

外部APIは内部Access Controlの後に追加する

外部AI API、メール、決済、Storageなどを先につなぐと、権限設計が曖昧なまま副作用が増えます。

まずAuth→Authorization→DB Read/Writeの最小Flowを安定させ、その後に外部APIを追加します。外部処理の前にも「このUserがこのActionを実行できるか」を確認します。

秘密情報をBrowserへ置かない

Service KeyやSecret API Keyなど、公開してはいけないCredentialはServer側で扱います。Frontend bundleやpublic environment variableへ置かないようにします。

AIに実装させるときも、環境変数名と利用場所を明示し、Client ComponentからSecretを参照しないことをTestします。

Row Level Securityを使う場合もRuleを設計する

DB側のRow Level Securityなどを使える場合、Access ContractをPolicyへ落とせます。ただしPolicyを有効にしただけでは十分ではありません。

owner一致、membership、public readなど、必要なConditionをPolicyとして確認し、Server APIのAuthorizationと責務が重複・矛盾しないよう整理します。利用中のDB製品の現行仕様に従ってください。

Deny CaseをSuccessより先に一覧化する

Security上は「通るべきものが通る」だけでなく、「通ってはいけないものが通らない」が重要です。

最低限:

  • 未ログイン

  • 他人のResource ID

  • role不足

  • Team未所属

  • private resource

  • invalid input

  • retired/deleted resource

  • expired session

  • forged client field

各CaseでHTTP status、Response body、DB変更有無、Logを確認します。

Updateの途中失敗を考える

複数のWriteや外部API呼び出しがある処理では、途中で失敗するとDataが中途半端になる場合があります。

DB transaction、idempotency、retry方針など、処理内容に応じたFailure設計を入れます。たとえば同じRequestをRetryして二重作成されないかを確認します。

Error Responseに内部情報を出しすぎない

Clientへ返すErrorとServer logへ残す情報を分けます。

DB内部構造、Secret、Stack TraceなどをUser向けResponseへ出さないようにします。一方、運用側ではrequest_idやerror codeで原因を追えるようにします。

Loggingは誰が何をしたか追える粒度にする

重要なWriteでは、user_id、action、resource_id、result、timestamp、request_idなどを必要に応じて記録します。

ただしPasswordやSecret、不要な個人情報をLogへ残しません。Logの保存範囲もProductのSecurity / Privacy方針に合わせます。

AIへの実装依頼はContractを先に渡す

依頼例:

以下のAccess ContractをSource of Truthとして、最小のGET /projects/:idを実装してください。

要件:

  • Server側で認証Userを確定

  • owner_id一致または許可されたmembershipのみRead

  • Clientから送られたuser_idを信用しない

  • Anonymous / other user / not foundのTestを追加

  • SecretをClientへ露出しない

  • 既存Architectureを維持

実装前に必要なDB FieldとUnknownを列挙してください。

最初から認証・全CRUD・外部APIまで頼まず、Access Contractごとに小さく通します。

接続順の一例

  1. User / Role / Resource / Actionを定義。

  2. DB Relationと制約を設計。

  3. Authenticationを接続。

  4. Read APIでServer側Authorization。

  5. Deny Testを通す。

  6. Write APIとIntegrity確認。

  7. RLS等のDB Policyを確認。

  8. 外部APIを追加。

  9. Failure / Retry / Loggingを追加。

  10. End-to-Endで再検証。

これは特定Stackの絶対順ではなく、権限条件を先に固定するための実務順です。

MVPでも省かないもの

小さなアプリでも、認証Userの確定、Resource ownership、Server側Authorization、Secret管理、Deny Testは省かない方がよい領域です。

Admin画面、細かなRole、Audit UIなどはLaterにできる場合がありますが、他人のDataへアクセスできないことはMVPでもCoreです。

実装後Checklist

  • Access Contractがある

  • AuthenticationとAuthorizationを分けた

  • DBがOwnership / Membershipを表現できる

  • SecretがServer側

  • Read / Write双方で権限確認

  • 他User IDでDeny Test済み

  • Invalid InputでDataが壊れない

  • Retryで二重処理しない

  • Errorに内部情報を出しすぎない

  • 必要なLogからRequestを追える

AIものさしの判断

認証・DB・APIの接続順で最初に固定すべきなのは、技術サービスの順番ではなくAccess Contractです。「誰が何をできるか」が決まれば、DB Relation、Auth Identity、Server Authorization、API Testへ落とせます。

まずRead 1本で、自分のDataは読める・他人のDataは拒否される状態を作ってください。その後Write、外部API、Automationへ広げる。Success CaseとDeny Caseを同時に通す進め方なら、AIが生成したコードを使っても権限漏れを見つけやすくなります。

引用・データ出典

公式情報を編集部が見た内容です。Hands-on未実施の記述は本文かここに分けています。

確認日:2026-10-07

Supabase Docs:Auth

Supabase Docs:Row Level Security

Supabase Docs:Securing your data

Supabase Docs:Data REST API

次に読む・使う

この記事の次に必要な情報へ進めます。