Laravel Passportは、OAuth2サーバーを迅速に構築できる公式パッケージです。「トークンを使ったAPI認証を実装したいが、Sanctumとどちらを使えばいいのかわからない」「昔の記事の通りにPassport::routes()を書いたらエラーになった」という声も多く、パッケージのバージョンによって手順が変わりやすい分野でもあります。この記事では、実際にLaravel 13 + Passport 13系の環境でインストールから動作確認まで検証したうえで、最新の実装手順を解説します。
Laravel Passportとは?
Laravel Passportは、OAuth2の仕様に準拠した認証サーバーをLaravelアプリケーションに組み込むための公式パッケージです。アクセストークンの発行・失効・スコープ管理、認可コードグラントやクライアントクレデンシャルグラントといった複数の認可フローを、自前で実装することなく利用できます。
主に次のようなケースで選ばれます。
- 自社のAPIを第三者の外部アプリケーションに公開し、OAuth2の「認可」フローで連携させたい
- スマートフォンアプリやIoTデバイスなど、複数のクライアント種別ごとに異なる認可フローを使い分けたい
- アクセストークンにスコープ(権限範囲)を持たせて、細かくアクセス制御したい
Laravel SanctumとPassportの使い分け
Laravelには軽量なAPIトークン認証パッケージ「Laravel Sanctum」も用意されており、どちらを使うべきか迷いやすいポイントです。判断基準は次の通りです。
| 要件 | 選ぶべきパッケージ |
|---|---|
| 自社SPA・モバイルアプリ向けのシンプルなトークン認証だけでよい | Sanctum |
| OAuth2の認可コードグラント・PKCE・スコープなど、フル機能のOAuth2サーバーが必要 | Passport |
| 第三者の外部サービスに自社APIへのアクセスを許可したい(サードパーティ連携) | Passport |
| 導入・運用をできるだけシンプルにしたい | Sanctum |
公式ドキュメントでも「OAuth2への完全準拠が必要な場合のみPassportを選び、それ以外はSanctumで十分」と案内されています。まずは要件を整理し、単純なトークン認証で足りるならSanctumを検討してください。
動作要件
- PHP 8.2以上
- Laravel 11以上
- Composerが利用できる環境
本記事の検証は、composer create-project laravel/laravelで作成したLaravel 13.20.0(PHP 8.3)+ Laravel Passport 13.7.5の組み合わせで行っています。
Laravel Passportのインストール
まずComposerでパッケージを追加します。
composer require laravel/passport
インストール後、Artisanコマンドを実行してAPI認証のスキャフォールディングを行います。以前のバージョンではphp artisan passport:installを直接叩く手順が主流でしたが、現行版ではinstall:apiコマンドに--passportオプションを付けて実行するのが推奨手順です(install:apiコマンドの詳細はこちら)。
php artisan install:api --passport
このコマンドを実行すると、実機検証では次の処理が自動的に行われました。
- OAuth関連のマイグレーションファイル(
oauth_clients、oauth_access_tokensなど5テーブル)が生成され、その場でmigrateまで自動実行される(別途php artisan migrateを打つ必要はありません) - 暗号化キーが生成される
- 「Laravel」という名前のパーソナルアクセストークン用クライアントが自動作成される
routes/api.phpに、auth:apiミドルウェアで保護された/userエンドポイントが追加される
実行後、次のような案内が表示されます。
INFO Published API routes file.
INFO API scaffolding installed. Please add the [Laravel\Passport\HasApiTokens] trait to your User model.
Userモデルの設定
案内の通り、App\Models\UserにHasApiTokensトレイトを追加します。あわせて、現行版ではLaravel\Passport\Contracts\OAuthenticatableインターフェイスの実装も必要です。
use Laravel\Passport\Contracts\OAuthenticatable;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable implements OAuthenticatable
{
use HasApiTokens, Notifiable;
// ...
}
認証ガードの設定
install:api --passportを実行しただけでは、config/auth.phpにapiガードは追加されません。この状態で保護ルートにアクセスすると、実機検証で次のエラーが発生しました。
{
"message": "Auth guard [api] is not defined.",
"exception": "InvalidArgumentException"
}
config/auth.phpのguardsに、ドライバをpassportとしたapiガードを追加してください。
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
なお、Laravel 10以前の記事でよく見かけるAuthServiceProviderでのPassport::routes()の呼び出しは、現行のPassportには存在しないメソッドです。OAuth関連のルート(/oauth/tokenなど)はPassportのサービスプロバイダによって自動登録されるため、記述すると呼び出しエラーになります。古い記事を参考にする際は注意してください。
トークンの発行と保護ルートへのアクセス
ここまでの設定で、認証済みユーザーはアクセストークンを発行できます。createTokenメソッドでパーソナルアクセストークンを発行するコード例です。
$user = User::find(1);
$token = $user->createToken('MyApp')->accessToken;
発行したトークンを使って、実際に保護ルート(GET /api/user)へアクセスできることを検証しました。
curl -H "Accept: application/json" \
-H "Authorization: Bearer {発行したトークン}" \
http://localhost:8000/api/user
{
"id": 1,
"name": "Ms. Icie Adams",
"email": "test@example.com",
"email_verified_at": "2026-07-21T02:54:34.000000Z",
"created_at": "2026-07-21T02:54:35.000000Z",
"updated_at": "2026-07-21T02:54:35.000000Z"
}
トークンを付けずにAccept: application/jsonヘッダーのみでアクセスすると、次の401レスポンスが返ることも確認済みです。
{"message":"Unauthenticated."}
OAuth2のグラントタイプ一覧
Passportは複数の認可フロー(グラントタイプ)に対応しています。用途に応じて使い分けます。
| グラントタイプ | 用途 | 既定で有効か |
|---|---|---|
| パーソナルアクセストークン | 自社サーバーからAPIを叩く、テスト用トークン発行 | 有効 |
| 認可コードグラント(PKCE対応) | 第三者アプリにユーザーの許可を得てAPIアクセスを許可する、標準的なOAuth2フロー | 有効 |
| クライアントクレデンシャルグラント | ユーザーを介さないマシン間通信(バッチ処理・スケジュールジョブなど) | 有効 |
| デバイス認証グラント | スマートTVやCLIツールなど、ブラウザを直接操作できない機器の認証 | 有効 |
| パスワードグラント | ファーストパーティのモバイルアプリでメールアドレスとパスワードから直接トークン発行 | 無効(要オプトイン) |
| 暗黙的グラント | JavaScriptクライアントへの直接トークン発行(非推奨のレガシー方式) | 無効(要オプトイン) |
実機検証では、パスワードグラントと暗黙的グラントはセキュリティ上の理由から既定で無効になっていることを確認しました。利用する場合はAppServiceProviderのbootメソッドで明示的に有効化します。
use Laravel\Passport\Passport;
public function boot(): void
{
Passport::enablePasswordGrant();
}
クライアントクレデンシャルグラント用のクライアントは、次のコマンドで作成できます。
php artisan passport:client --client --name="Client Credentials Client"
INFO New client created successfully.
Client ID ..... 019f8299-1dbc-7353-8ec2-e5977f6734b8
Client Secret . 33p0l5Glve6bryjtF0JYRL17OtAkm8TQZTma7cIf
WARN The client secret will not be shown again, so don't lose it!
トークンの有効期限を設定する
Passportの既定では、アクセストークン・リフレッシュトークン・パーソナルアクセストークンのいずれも有効期限は1年です。セキュリティを高めるため、AppServiceProviderのbootメソッドで短めに設定することを推奨します。
use Carbon\Carbon;
use Laravel\Passport\Passport;
public function boot(): void
{
Passport::tokensExpireIn(Carbon::now()->addDays(15));
Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));
Passport::personalAccessTokensExpireIn(Carbon::now()->addMonths(6));
}
よくあるエラーと対処法
| エラー・症状 | 原因 | 対処法 |
|---|---|---|
Auth guard [api] is not defined. |
config/auth.phpにapiガードが未定義 |
本記事の「認証ガードの設定」の通り、driver: passportのapiガードを追加する |
Route [login] not defined. |
APIリクエストなのにAccept: application/jsonヘッダーが無く、未認証時にログイン画面へリダイレクトしようとしている |
APIクライアント側で必ずAccept: application/jsonを付ける |
Call to undefined method Passport::routes() |
現行のPassportに存在しない古い記述をそのまま使っている | Passport::routes()の呼び出しを削除する(現行版は自動登録のため不要) |
| ユーザーモデルでエラーになる | HasApiTokensトレイトまたはOAuthenticatableインターフェイスの実装漏れ |
Userモデルに両方を追加する |
まとめ
Laravel Passportは、OAuth2に完全準拠したAPI認証をLaravelアプリケーションに組み込める公式パッケージです。現行版のポイントは、php artisan install:api --passportでマイグレーションまで一括実行される一方、apiガードの追加とUserモデルへのトレイト・インターフェイス実装は手動で行う必要がある点、そして旧バージョンで必須だったPassport::routes()の呼び出しがすでに廃止されている点です。単純なトークン認証で十分な場合は、より軽量なLaravel Sanctumの利用も検討してください。APIエンドポイント全般の設計についてはLaravel API開発の基礎から応用までもあわせて参考にしてください。
よくある質問
Q. Laravel PassportとLaravel Sanctumはどちらを使うべきですか?
A. 自社SPAやモバイルアプリ向けのシンプルなトークン認証であればSanctum、第三者アプリへのAPI公開やOAuth2の認可コードグラント・スコープ管理が必要な場合はPassportを選びます。
Q. 古い記事にあるphp artisan passport:installやPassport::routes()は使えますか?
A. passport:installコマンド自体は現行版にも残っていますが、現行のLaravelではphp artisan install:api --passportを使うのが公式の推奨手順です。またPassport::routes()は現行のPassportクラスから削除されており、記述するとエラーになります。
Q. パスワードグラントが使えないのですが?
A. パスワードグラントと暗黙的グラントはセキュリティ上の理由から既定で無効化されています。AppServiceProviderのbootメソッドでPassport::enablePasswordGrant()を呼び出すことで有効化できます。

コメント