
だからこそ、機能一覧だけを見ていると判断を誤りやすい。
SanctumとPassportの違いは、単純な「高機能版」と「簡易版」の比較ではない。分岐点は、OAuth 2.0の認可サーバーを本当に必要としているかどうかだ。自社サービスのSPAやモバイルアプリを認証したいのか、それとも外部サービスや第三者開発者にAPI利用権限を委任したいのか。この前提によって、選ぶべきアーキテクチャはかなりはっきり変わる。
個人開発では、認証機能を増やすこと自体が成果にならない。ユーザーの痛みを解消し、登録後の利用開始率や継続利用につながって初めて意味がある。認証基盤に必要以上の仕組みを持ち込めば、実装時間だけでなく、トークン管理や失効処理、問い合わせ対応のコストまで膨らむ。
一方で、将来的な外部連携を見落としてSanctumを選ぶと、後から認証基盤を作り直すことになる。
この記事では、Laravel SanctumとPassportの違いを、機能表だけではなく、プロダクトの成長と運用の現実から比較する。結論を先に言えば、判断の軸は「どちらが優れているか」ではなく、「誰に、どの権限を、どの方法で委任するのか」だ。
最初に見るべき分岐点は「誰がAPIを使うのか」
API認証の設計で最初に決めるべきなのは、トークンの発行方法ではない。APIの利用者だ。
次の二つは、似ているようで別の問題である。
- 自社で提供するSPAやモバイルアプリから、自社ユーザーのデータにアクセスする
- 外部の開発者や他社サービスに、ユーザーの許可を得てAPIアクセスを委任する
前者では、認証対象は基本的に自分たちが管理するクライアントだ。自社のフロントエンド、自社のモバイルアプリ、自社の管理画面。サービス全体を自分たちで把握できるため、認証フローも比較的シンプルに設計できる。
後者では事情が変わる。
外部のクライアントが増えると、クライアントごとの登録、識別情報の管理、認可画面、権限の範囲、アクセストークンの有効期限、リフレッシュトークン、失効処理が必要になる。単に「ログインしたユーザーかどうか」を確認するだけでは不十分だ。
ユーザーが第三者アプリに対して、「プロフィールだけ許可する」「請求情報にはアクセスさせない」といった権限を選べなければならない。サービス側も、その許可がいつ与えられ、どのクライアントに対して、どのスコープで発行されたのかを管理しなければならない。
ここが、Laravel SanctumとPassportの大きな分岐点になる。
SanctumとPassportの選択は、機能の多さではなく、APIアクセスを誰に委任するかで決める。
Sanctumは、Laravelアプリケーションに必要な認証を比較的軽量に追加するための仕組みだ。SPA向けのステートフルなクッキー認証と、モバイルアプリやサービス向けのパーソナルアクセストークン認証を提供する。
Passportは、League OAuth2 Serverをベースにした完全なOAuth 2.0サーバー実装だ。OAuth 2.0の認可コード、クライアント登録、リフレッシュトークン、スコープ、トークン失効など、認可サーバーとして必要になる機能を扱える。
この違いを曖昧にしたまま、「将来使うかもしれないからPassport」と判断するのは危険だ。将来の可能性は大切だが、現在のプロダクトに不要な運用コストを持ち込む理由にはならない。
SanctumはSPA認証のための現実的な入口になる
自社開発のSPAをLaravelのAPIに接続するなら、まずSanctumを検討する。ここで重要なのは、SanctumのSPA認証では、必ずしもAPIトークンを発行する必要がないという点だ。
SanctumのSPA認証は、クッキーベースのセッション認証を利用する。ユーザーがログインするとセッションが作られ、ブラウザはクッキーを送信する。API側では、そのセッションをもとに認証済みユーザーを判定する。
これは、SPAからAPIへBearerトークンを毎回送る方式とは異なる。
フロントエンドのJavaScriptにアクセストークンを保持させる設計では、トークンの保存場所や漏洩時の影響が問題になる。もちろんクッキー認証でもCSRF対策やXSS対策は必要だが、トークンをブラウザ上のストレージに直接保持しない設計にできる点は大きい。
特に、同一トップレベルドメイン配下でSPAとAPIを運用する構成では、Sanctumのクッキー認証が自然にフィットする。たとえば、SPAをapp.example.com、APIをapi.example.comで提供するような構成だ。
実装時には、次のような境界を最初に決めておく必要がある。
- SPAとAPIのドメイン構成
- セッションCookieのドメイン
- CORSの許可範囲
- CSRFトークンの取得と送信
- HTTPSを前提としたCookie設定
- ログアウト時のセッション破棄
- 複数端末のセッション管理
ここを「パッケージをインストールすれば終わり」と考えると、開発環境では動くのに本番環境でログインできない、という典型的な問題にぶつかる。認証の失敗は、ユーザーから見ると機能全体の失敗だ。登録できてもログインできない。ログインできてもAPIが403を返す。こうした摩擦は、ユーザーの初回体験を一気に悪化させる。
Sanctumを使う場合、技術的な実装よりも、認証状態の境界を明確にすることが大切だ。
SPA認証でAPIトークンを使わない理由
SPAに対して、最初からパーソナルアクセストークンを発行する設計もできる。しかし、自社SPAのためだけにトークン認証を採用するなら、なぜクッキー認証ではなくトークンを選ぶのかを説明できなければならない。
パーソナルアクセストークンは、モバイルアプリや外部のサービスからAPIを呼び出す場合に扱いやすい。Authorization: Bearerヘッダーで送信でき、ブラウザのセッションとは独立して管理できるからだ。
ただし、ブラウザのSPAに対しても同じ方法を採用すると、トークンの保管、更新、漏洩時の対応をアプリケーション側で設計する必要が出てくる。認証の仕組みが自由になる一方で、実装と運用の責任も増える。
ここでの仮説はシンプルだ。
「自社SPAのログイン状態を維持したいだけなら、セッション認証のほうがユーザー体験と運用のバランスを取りやすいのではないか」
この仮説を、フロントエンドの構成、ドメイン、デプロイ方式、セキュリティ要件に照らして検証する。Sanctumを選ぶ理由は「簡単だから」ではない。目的に対して、認証の責任範囲を必要以上に広げないためだ。
モバイルアプリや個人開発の複数クライアントではSanctumのトークン認証
SanctumはSPA向けのセッション認証だけでなく、パーソナルアクセストークンにも対応している。
モバイルアプリや、別のLaravelサービス、社内用の小さなツールなど、自社で管理するクライアントからAPIを呼び出したい場合に使いやすい。ユーザーごとに複数のトークンを発行できるため、端末やアプリケーション単位で認証情報を分ける運用も可能だ。
Sanctumでは、発行したトークンをpersonal_access_tokensテーブルで管理する。APIリクエストでは、通常、Authorization: Bearerヘッダーにトークンを付けて送信する。
この方式は、個人開発のプロダクトと相性がいい。理由は、認証機能そのものよりも、プロダクトの検証に時間を使えるからだ。
ただし、「個人開発だからSanctum」という決め方は不十分だ。個人開発でも、外部開発者向けのAPIを公開するならPassportが必要になる可能性がある。反対に、企業向けのサービスであっても、自社管理のSPAとモバイルアプリだけがクライアントなら、Sanctumで十分なケースはある。
見るべきなのはチーム規模ではない。クライアントの所有関係と、認可モデルだ。
Sanctumのパーソナルアクセストークンで決めておきたいこと
Sanctumをトークン認証に使う場合、最低限、次の設計を先に決める。
- トークンの発行単位をユーザー単位にするか、端末単位にするか
- トークンに有効期限を設定するか
- 端末を紛失したときに、対象トークンだけを失効できるか
- 全端末からログアウトする機能を提供するか
- トークンに能力や権限を付与するか
- 管理画面で発行済みトークンを確認・削除できるか
- APIログからトークンそのものが漏れないようにするか
特に忘れやすいのが、トークンの表示と失効だ。
ユーザーが複数の端末を使う場合、単一のトークンだけを使い回す設計は管理しにくい。スマートフォンを買い替えたとき、古い端末だけを切断したいことがある。開発者用のCLIから接続する場合も、サービス全体のログアウトではなく、特定の接続だけを削除したい。
このような運用要件を考えると、トークンを「ログインの証明」ではなく、「特定のクライアントに与えた接続権限」として扱う必要がある。
Sanctumは軽量だが、設計まで自動化してくれるわけではない。ここを誤解しないことだ。
軽量な認証パッケージを選んでも、トークンのライフサイクルまで軽量になるわけではない。
トークンの有効期限、失効、再発行、端末管理。これらはパッケージの選定後に、プロダクト側で設計する領域になる。
Passportが必要になるのはOAuth 2.0の委任が必要なとき
Passportは、Sanctumより多機能だから選ぶものではない。OAuth 2.0の標準仕様に沿った認可サーバーが必要だから選ぶ。
たとえば、自社サービスを外部開発者に公開し、第三者アプリからユーザーのデータを利用できるようにしたいとする。このとき、外部アプリがユーザーのパスワードを直接受け取る設計は避けなければならない。
必要なのは、ユーザーが自社サービス上でログインし、外部アプリに対して許可する権限を確認し、その結果としてアクセストークンを発行する流れだ。
いわゆる「自社サービスでログイン」のような仕組みや、API連携サービスに対する認可を提供する場合、PassportのOAuth 2.0実装が候補になる。
Passportでは、次のような概念を扱う。
- OAuthクライアント
- 認可コード
- アクセストークン
- リフレッシュトークン
- スコープ
- トークンの有効期限
- トークンの失効
- クライアントごとの認証情報
Sanctumのパーソナルアクセストークンが「このユーザーに発行されたトークン」であるのに対し、Passportでは「このクライアントが、このユーザーの許可を得て、この範囲のAPIを利用する」という関係を扱える。
この差は、外部連携が増えたときに効いてくる。
Passportの導入で増えるのは実装だけではない
OAuth 2.0は標準仕様に沿っている。だから安全で、何でも解決できる。そう単純にはいかない。
OAuth 2.0を導入すると、クライアント登録の仕組みが必要になる。認可画面も必要だ。スコープの設計も必要になる。アクセストークンとリフレッシュトークンの有効期限をどうするか、ユーザーが許可を取り消すにはどうするか、クライアントの秘密情報をどう保護するかも決めなければならない。
さらに、外部開発者向けにAPIを公開するなら、ドキュメント、サンプルコード、エラー仕様、レート制限、サポート窓口まで必要になる。認証だけをPassportに置き換えても、API連携体験は完成しない。
プロダクトグロースの観点では、ここが重要だ。
外部連携は、実装した瞬間に価値が出る機能ではない。利用者が実際に接続し、必要な権限を理解し、APIを呼び出し、エラーから復旧できて初めてコンバージョンにつながる。認証基盤の高機能化だけを先に進めても、ユーザーの痛みが解消されるとは限らない。
Passportを採用するなら、次のような要件が明確に存在しているかを確認したい。
1. 外部サービスや第三者開発者がAPIを利用する予定がある
2. ユーザーが接続先ごとにアクセス許可を管理する必要がある
3. アクセストークンとリフレッシュトークンを分けて運用したい
4. APIの権限をスコープ単位で制御したい
5. OAuth 2.0準拠の認可サーバーが必要である
6. クライアントの登録や失効をサービス側で管理したい
この要件がまだ存在しないなら、Passportの導入は仮説ではなく、先行投資になる。先行投資が悪いわけではない。しかし、そのコストを受け入れるだけの成長シナリオがあるかは、別途検証すべきだ。
SanctumとPassportの違いを機能ではなく運用で比較する
SanctumとPassportを比較するとき、機能の多い少ないだけで判断すると、実際の開発負荷を見誤る。
比較すべきなのは、ユーザーがログインするまでの導線、トークンが漏洩したときの対応、外部クライアントが増えたときの管理、そして認証に関する問い合わせをどう処理するかだ。
| 比較項目 | Laravel Sanctum | Laravel Passport |
|---|---|---|
| 主な用途 | 自社SPA、モバイルアプリ、自社サービス間のAPI認証 | 外部サービスや第三者アプリへのAPI認可 |
| SPA認証 | クッキーベースのステートフル認証に対応 | OAuth 2.0フローを利用した認証・認可 |
| トークン認証 | パーソナルアクセストークンを発行 | OAuth 2.0のアクセストークンを発行 |
| OAuth 2.0 | フルスペックの認可サーバーではない | League OAuth2 Serverをベースに対応 |
| リフレッシュトークン | OAuth 2.0の仕組みとしては扱わない | 対応 |
| スコープ | アプリケーション側で設計する能力制御 | OAuth 2.0のスコープとして管理 |
| クライアント登録 | 基本的には不要 | OAuthクライアントの登録が必要 |
| 導入・運用負荷 | 比較的軽い | 設計・運用ともに重くなりやすい |
| 向いている構成 | 自社が管理するクライアント中心 | 第三者クライアントを含むエコシステム |
この表で気をつけたいのは、Passportのほうが常に上位ではないことだ。
Passportは、認可サーバーとして必要な能力を持っている。その分、サービスの責任範囲が広がる。Sanctumは、OAuth 2.0の機能をすべて持たない代わりに、自社のSPAやモバイルアプリに必要な認証へ集中できる。
機能の差は、優劣ではなく、背負う問題の差だ。
「将来Passportへ移行するかもしれない」という不安
個人開発では、将来の拡張性が常に気になる。
最初は自社SPAだけだったサービスが、成長して外部APIを公開する可能性はある。その場合、SanctumからPassportへの移行が必要になるかもしれない。
この不安から、最初からPassportを導入するケースは珍しくない。しかし、将来の可能性だけで現在の開発フローを複雑にすると、初期のコンバージョン検証が遅れる。認証の設計に時間をかけすぎて、肝心のユーザー価値が後回しになる。
私がこういう場面で置く仮説は、「将来の認証方式を完全に固定するより、現在のクライアント境界を明確にしておくほうが、移行コストを下げられる」だ。
たとえば、次のように認証周辺を分離しておく。
- APIの認証処理をコントローラーに直接書かない
- ユーザーの認証情報と、APIの権限判定を分ける
- 外部公開を想定するAPIには、最初から権限の粒度を持たせる
- トークン文字列を業務ロジックに渡さない
- 認証方式に依存したレスポンス形式を広げすぎない
- APIのバージョンや公開範囲を意識してルートを設計する
これはPassportを先に入れるという意味ではない。認証方式を変更しても、業務ロジックまで巻き込まれないようにするという意味だ。
技術的な詳細に深入りしすぎると、プロダクトの目的を見失う。逆に、目の前の画面だけを動かしていると、後から変更できない構造になる。必要なのは、過剰な抽象化ではなく、変更される可能性が高い境界を見極めることだ。
セキュリティの比較で見落としやすいポイント
SanctumとPassportの選択では、セキュリティ機能の多さだけを見るべきではない。どの認証情報を、どのクライアントに、どの期間渡すのかを整理する必要がある。
SanctumのSPA認証はクッキーベースで動作するため、XSS攻撃によるトークンの直接的な漏洩リスクを抑えやすい。もちろん、XSSそのものを防げるわけではない。入力値のエスケープ、コンテンツセキュリティポリシー、依存パッケージの管理など、アプリケーション全体の対策は必要になる。
また、クッキー認証ではCSRF対策が前提になる。CORSの設定を広くしすぎたり、許可するオリジンを曖昧にしたりすると、認証が通らないだけでなく、意図しないアクセス経路を作る可能性がある。
一方、PassportではOAuth 2.0のフローを利用できるが、OAuth 2.0を導入しただけで安全になるわけではない。リダイレクトURIの管理、クライアント情報の保護、スコープ設計、アクセストークンの有効期限、リフレッシュトークンの扱いが適切でなければ、複雑な仕組みが複雑なリスクに変わる。
認証方式を選ぶときは、次の観点で設計を確認する。
- 認証情報がブラウザ、モバイル端末、サーバーのどこに保存されるか
- 漏洩した場合に、どの範囲のAPIへアクセスできるか
- 盗難や端末紛失時に、どの単位で失効できるか
- ユーザーが許可した権限を後から取り消せるか
- 管理者が不審なトークンを特定できるか
- ログに認証情報を残さずに障害調査できるか
- 認証失敗と認可失敗を、ユーザーに適切に伝えられるか
特に「認証」と「認可」を一つの問題として扱わないことが重要だ。
認証は、そのユーザーが誰であるかを確認する処理。認可は、そのユーザーやクライアントが何をしてよいかを判断する処理だ。SanctumでもPassportでも、ログインできたユーザーがすべてのAPIを使えるわけではない。サービスの成長に合わせて権限が細かくなるなら、認証方式とは別に認可モデルを設計する必要がある。
個人開発での現実的な選び方
個人開発では、認証に割ける時間が限られている。開発、問い合わせ、障害対応、改善施策。すべてを一人で持つ以上、運用の複雑さはそのまま自分の負担になる。
そのため、私は認証パッケージを選ぶとき、機能の一覧よりも「認証に関する判断を何個増やすのか」を見る。
Sanctumを選ぶ場合、主な検討対象はSPAのセッション認証、またはパーソナルアクセストークンの管理になる。自社で管理するクライアントが中心なら、要件を絞りやすい。
Passportを選ぶ場合、OAuthクライアント、認可フロー、スコープ、リフレッシュトークン、失効、外部開発者向けのドキュメントまで視野に入る。これは必要なプロダクトにとっては不可欠だが、不要なプロダクトにとっては明確な負担になる。
判断を整理するなら、次の順番が扱いやすい。
1. APIの利用者を分類する
自社SPA、自社モバイルアプリ、自社サービス、外部サービス、第三者開発者を分ける。利用者を一括りにしない。
2. 認証と認可の要件を分ける
ログインできればよいのか、クライアントごとに権限を委任する必要があるのかを整理する。
3. トークンのライフサイクルを決める
有効期限、再発行、失効、複数端末、端末名の表示など、運用時の姿を先に考える。
4. 将来要件を確度で分類する
すでに決まっている要件、顧客から要望がある要件、いつか必要になるかもしれない要件を分ける。
5. 最初の検証に必要な範囲へ絞る
認証基盤の完成度ではなく、ユーザーがサービスの価値に到達できるかを優先する。
この手順を踏むと、「なんとなくPassport」という判断が減る。逆に、外部連携がプロダクトの価値そのものなら、Sanctumで無理に始める理由も減る。
ケース別の判断
| 想定するサービス | 推奨しやすい選択 | 判断の理由 |
|---|---|---|
| Laravelで構築したSPAのバックエンド | Sanctum | クッキーベースのセッション認証を使いやすい |
| 自社モバイルアプリのAPI | Sanctum | パーソナルアクセストークンで構成しやすい |
| 自社サービス間の限定的なAPI通信 | Sanctumを軸に検討 | クライアントを自分たちで管理できる |
| ユーザーが外部アプリと連携するサービス | Passport | OAuth 2.0による認可委任が必要になりやすい |
| 第三者開発者向けのAPIプラットフォーム | Passport | クライアント登録、スコープ、トークン管理が必要 |
| 「自社サービスでログイン」を提供するサービス | Passport | 外部クライアントへの認証・認可を扱うため |
| OAuth 2.0準拠が明確な要件になっている | Passport | 標準仕様に沿った認可サーバーが必要 |
この表は、パッケージの優劣を示すものではない。現在の要件に対して、どこまで認証基盤を担わせるかを整理するためのものだ。
API認証の選択は、ユーザー体験の設計でもある
認証はバックエンドの実装詳細として扱われがちだ。しかし、ユーザーが最初にサービスへ触れる場所でもある。
ログイン画面で何度も認証を求められる。外部アプリとの接続状態が分からない。端末を変えたら再ログインできない。権限を許可したのに、どのデータへアクセスされたのか分からない。
こうした体験は、Laravelのコードからは見えにくい。しかし、ユーザーの離脱率やアクティブユーザー数に影響するのは、最終的にはこうした細部だ。
SanctumのSPA認証を使うなら、ログイン状態が自然に維持されること、セッション切れ時に復帰できること、CSRFやCORSの失敗をユーザーに分かる形で伝えることが重要になる。
Sanctumのトークン認証を使うなら、端末ごとの接続管理やログアウト、トークン失効を用意することが信頼につながる。
Passportを使うなら、外部アプリとの接続フローを分かりやすくすることが最優先だ。権限の説明が曖昧な認可画面は、ユーザーに不安を与える。スコープを細かく作りすぎれば読みにくくなり、粗く作りすぎれば過剰な権限を与える。
認証基盤の選定は、技術スタックの問題であると同時に、コンバージョン設計の問題でもある。
認証の正しさは、ログインに成功した回数だけでは測れない。ユーザーが安心して、次の操作へ進めたかで測る。
私はプロダクトの認証を設計するとき、まずユーザーがどこで止まるかを仮説にする。ログインフォームなのか、メール確認なのか、外部サービスとの接続なのか、権限許可の画面なのか。
そのうえで、認証方式を選ぶ。パッケージを先に選び、あとからユーザー体験を合わせるのではない。ユーザーの行動を先に定義し、その行動に対して最も無理のない認証基盤を選ぶ。
迷ったら「現在のクライアント」を基準にする
Laravel SanctumとPassportの違いをまとめると、次のようになる。
Sanctumは、自社で管理するSPAやモバイルアプリに対して、クッキー認証やパーソナルアクセストークンを提供する。認証基盤を軽量に保ち、プロダクトの検証へ集中したい場合に向いている。
Passportは、外部クライアントに対してOAuth 2.0で認証・認可を委任する。クライアント登録、認可コード、リフレッシュトークン、スコープ、失効など、認可サーバーとして必要な機能を扱いたい場合に選ぶ。
つまり、次のように考えると判断しやすい。
- 自社SPAのログインが目的なら、Sanctumのクッキー認証
- 自社モバイルアプリへのAPIアクセスが目的なら、Sanctumのトークン認証
- 自社サービス間で限定的に接続するなら、要件に応じてSanctum
- 外部アプリへユーザーの権限を委任するなら、Passport
- 第三者開発者向けのAPI基盤を作るなら、Passport
- OAuth 2.0準拠が要件なら、Passport
現在の要件がSanctumで満たせるなら、まずSanctumで始める。将来Passportが必要になったときに移行できるよう、認証と業務ロジックの境界だけは丁寧に分けておく。
反対に、外部連携がサービスの中心であり、ユーザーが第三者アプリへ権限を渡す必要があるなら、最初からPassportを選ぶ。ここでSanctumに寄せると、後から認可モデルを作り直す可能性が高い。
私が次に試したいのは、認証方式ごとの実装時間を比較することではない。ユーザーがログイン後に最初の価値へ到達するまでの時間を測ることだ。SPAのセッション認証、モバイルアプリのトークン認証、外部サービス連携。それぞれの導線で、どこにユーザーの痛みが残るのかを確認したい。
認証は、完成したら終わる機能ではない。サービスのクライアントが増え、権限が細かくなり、ユーザーの期待が変わるたびに検証し直す領域だ。
Laravel SanctumとPassportの選択で迷ったら、まず「どちらが高機能か」ではなく、「誰のための認証なのか」を問い直す。その答えが、自分たちのプロダクトに必要な構成をかなり正確に示してくれる。