はじめに
SanctumのSPA認証の実装をしてみたので共有します。
Laravel Sanctum:SPA認証
SanctumはWeb API用の認証機能を提供するパッケージです。
提供される認証方式はAPIトークン、SPA認証の2つがありますが、今回はSPA認証について解説します。
SPA認証
SPAのためのセッション認証サービスです。
Laravelの「web」認証ガードを利用して実現しています。
CSRF保護、XSS攻撃による情報漏洩を保護します。
SPA認証のステップ
1 : セッション管理対象のフロントエンドのオリジンを指定する。
envファイルで次のようにセッション管理対象のフロントエンドのオリジンを設定します。
SANCTUM_STATEFUL_DOMAINS="localhost:80"
上記の環境変数は以下の箇所で使用されます。
'stateful' => explode(',', env(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,127.0.0.1,127.0.0.1:8000,::1'
)),
2 : CSRFトークンの取得
CSRFとは、生成元が異なる許可されていないフロントエンドからのリクエスト送信です。
罠が仕掛けられたリンクにアクセスすることで無関係のサイトにアクセスさせられ、利用者が意図しない操作を実行させられます。
そのため、異なるオリジンのWebサイトからのアクセスをブロッキングする必要があります。
CORS設定で許可したフロントエンドのみにCSRFトークンを付与し、そのトークンを持つフロントエンドからのリクエストのみを受け付けるようにします。(CORSの設定はcors.php
で行います)
そうすることでフロントエンドの信頼性を担保しています。
Sanctumをインストールすると、自動で/sanctum/csrf-cookie
というルートが作成されます。
$ php artisan route:list
GET|HEAD sanctum/csrf-cookie ............................................ sanctum.csrf-cookie › Laravel\Sanctum › CsrfCookieController@show
こちらにアクセスすると、レスポンスのcookieにXSRF-TOKEN
が入って返ってきます。
このcookieに入ってるトークン(CSRFトークン)をフロント側でX-XSRF-TOKEN
ヘッダにセットすることでリクエストを送信することができるようになります。
3 : Sanctumのミドルウェアを使用する
Sanctumのミドルウェアをapp/Http/Kernel.php
ファイル内のapiミドルウェアグループに追加します。
protected $middlewareGroups = [
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
こうすることで、api.php
ファイル内のルートに適用したいミドルウェアを指定できます。
EnsureFrontEndRequestsAreStateful
ミドルウェアはセッションの作成、CSRFトークンが正常であるかなどを確認します。
SANCTUM_STATEFUL_DOMAINS
に設定されているドメインからのアクセスの場合にトリガーされます。
問題がない場合は新しいセッションが作成され、対応するcookieが返されます。
4 : ルートを保護する
認証済みじゃ無いとアクセスできないルートは次のように定義できます。
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
/api/user
にアクセスする際に、認証済みで無い場合はエラーになります。
Sanctumの設定は以上になります。
※ログイン成功時にセッションを作成する箇所は別途実装する必要があります。(Laravel Fortifyを利用すれば最初からセッションを作成するコードは書かれているため実装は不要です。)
まとめ
Sanctumがやってくれることは大きく分けて次のことになります。
・CSRFトークンを提供するAPI
・セッションの作成
・認証済みであることを条件とするルートの作成
新規登録、ログイン、ログアウトなどの機能は別途実装する必要があります。
参考文献
Laravel Sanctum
CSRF
CORS