mcpField
A
auth0-laravel-api

auth0-laravel-api

github.com/auth0セキュリティ55210 回インストール1 日前に更新
リポジトリ

auth0-laravel-api について

auth0/login を使って Auth0 のアクセストークンを検証し、Laravel API のエンドポイントを保護するエージェント向けスキルです。ステートレスな API ガードの設定や、JWT クレーム、スコープ、権限の確認を案内します。

主な機能

  1. 01Auth0 API ガードの設定
  2. 02JWT アクセストークンの検証
  3. 03スコープと権限の確認
  4. 04Laravel でのトークンクレーム参照
  5. 05保護対象 API ルートの設定

活用シーン

  1. 01Auth0 による Laravel API エンドポイントの保護
  2. 02トークンのスコープによるルート制限
  3. 03API リクエストの権限確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/auth0/agent-skills --skill auth0-laravel-api

インストール後、Claude Code で/auth0-laravel-apiを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api.md
integration.md
setup.md

詳細

Auth0 Laravel API 統合

auth0/login と AuthorizationGuard を使用して JWT アクセストークンを検証し、Laravel API エンドポイントを保護します。


前提条件

  • Laravel 11 以降のアプリケーション
  • PHP 8.2 以降と拡張機能:mbstring、openssl、json
  • Composer がインストールされていること
  • Auth0 API リソースが設定されていること(Application ではなく、API である必要があります)
  • Auth0 をまだ設定していない場合は、まず auth0-quickstart スキルを使用してください

使用しないケース

シナリオ代わりに使用
ログイン/ログアウト UI を備えた Laravel Web アプリauth0-laravel(セッションベースの AuthenticationGuard)
プレーンな PHP API(フレームワークなし)auth0-php-api
プレーンな PHP Web アプリauth0-php
シングルページアプリケーションauth0-react、auth0-vue、または auth0-angular
FastAPI/Python APIauth0-fastapi-api
Express/Node.js APIexpress-oauth2-jwt-bearer
トークンの発行このスキルはアクセストークンの検証用であり、発行用ではありません

クイックスタートのワークフロー

1. SDK をインストールする
composer require auth0/login

auth0/login パッケージには auth0/auth0-php(v8.19 以降)が必要で、自動的にインストールされます。また、PSR-18 HTTP クライアントも必要です。まだインストールしていない場合は、次を実行してください。

composer require guzzlehttp/guzzle guzzlehttp/psr7
2. 設定を公開する
php artisan vendor:publish --tag=auth0

これにより、ガード、ミドルウェア、ルートの設定を含む config/auth0.php が作成されます。

3. Auth0 API を作成する

Auth0 で必要なのは API(Application ではありません)です。

停止して、先にユーザーに確認してください。

次の質問をそのまま尋ね、ほかの作業に進む前に回答を待ってください。

「Auth0 API リソースをどのように作成しますか?

  1. 自動 — リソースを作成し、正確な値を .env に自動で書き込む Auth0 CLI スクリプトを実行します。
  2. 手動 — Auth0 Dashboard(または auth0 apis create)で API を作成し、Domain と Audience を教えてください。

どちらにしますか?(1 = 自動/2 = 手動)」

ユーザーが回答するまでは、セットアップ手順に進まないでください。手動を既定の選択肢にしないでください。

ユーザーが「自動」を選んだ場合は、CLI スクリプトの全手順についてセットアップガイドに従ってください。自動手順で .env が書き込まれるため、以下のステップ 4 はスキップし、ステップ 5 に進んでください。

ユーザーが「手動」を選んだ場合は、詳細な手順についてセットアップガイドの「手動セットアップ」セクションに従ってください。その後、以下のステップ 4 に進みます。

API を手動で作成する場合のクイックリファレンス:

auth0 apis create \
  --name "My Laravel API" \
  --identifier https://my-api.example.com \
  --json

または、Auth0 Dashboard の Applications -> APIs から手動で作成します。

4. 環境を設定する

.env に以下を追加します。

AUTH0_DOMAIN=your-tenant.us.auth0.com
AUTH0_AUDIENCE=https://your-api.example.com

AUTH0_DOMAIN は Auth0 テナントのドメイン(https:// を除く)です。AUTH0_AUDIENCE は、Auth0 で API リソースを作成するときに設定した API 識別子です。

5. 認証ガードを設定する

config/auth.php を更新して、API ガードを追加します。

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'auth0-api' => [
        'driver' => 'auth0.authorizer',
        'provider' => 'auth0-provider',
        'configuration' => 'api',
    ],
],

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
    'auth0-provider' => [
        'driver' => 'auth0.provider',
        'repository' => 'auth0.repository',
    ],
],

重要なポイント:

  • driver は auth0.authorizer にする必要があります(Web アプリ用の auth0.authenticator ではありません)。
  • configuration は 'api' にする必要があります。これは config/auth0.php の api ガードに対応します。
  • SDK はこの設定で auth0-api ガードを自動登録しますが、明示的に定義したほうが分かりやすくなります。
6. Auth0 の設定を確認する

設定の公開後、config/auth0.php に strategy が SdkConfiguration::STRATEGY_API(値:'api')に設定された guards.api キーが含まれていることを確認してください。これは公開済みの設定にすでに含まれているため、手動編集は不要です。

公開されたファイルでは、キーにクラス定数(例:Configuration::CONFIG_STRATEGY)が使われています。実行時には、これらは同じ文字列値に解決されます。

'guards' => [
    'api' => [
        'strategy' => SdkConfiguration::STRATEGY_API,  // value: 'api'
    ],
],

公開された設定には default と web のガードセクションも含まれていますが、API のみを使用する場合は無視できます。STRATEGY_API 戦略では、すべてのセッション/Cookie の機能が無効になり、ステートレスな Bearer トークン検証が有効になります。

7. 保護された API ルートを追加する

Laravel 11+ には、デフォルトで routes/api.php が含まれていません。ファイルが存在しない場合は、スキャフォールドしてください。

php artisan install:api

これにより routes/api.php が作成され、/api プレフィックス付きで bootstrap/app.php に登録されます。また、Laravel Sanctum もインストールされますが、Auth0 と併用しても問題はなく、使用されません。

routes/api.php で:

use Illuminate\Support\Facades\Route;

Route::get('/public', function () {
    return response()->json(['message' => 'Public endpoint - no authentication required']);
});

Route::middleware('auth:auth0-api')->group(function () {
    Route::get('/private', function () {
        $user = auth('auth0-api')->user();
        return response()->json([
            'message' => 'Private endpoint',
            'sub' => $user->getAuthIdentifier(),
        ]);
    });
});

auth:auth0-api ミドルウェアは Bearer トークンを検証し、JWKS エンドポイントに対して署名を確認し、issuer と audience のクレームをチェックします。有効なトークンがないリクエストには 401 レスポンスが返されます。

8. スコープと権限のチェック

ガードの hasScope() メソッドと hasPermission() メソッドを使用します。

Route::middleware('auth:auth0-api')->group(function () {
    Route::get('/messages', function () {
        $guard = auth('auth0-api');

        if (!$guard->hasScope('read:messages')) {
            return response()->json(['error' => 'insufficient_scope'], 403);
        }

        return response()->json(['messages' => []]);
    });

    Route::delete('/users/{id}', function (string $id) {
        $guard = auth('auth0-api');

        if (!$guard->hasPermission('delete:users')) {
            return response()->json(['error' => 'insufficient_permissions'], 403);
        }

        return response()->json(['deleted' => $id]);
    });
});
  • hasScope() は scope クレーム(JWT 内のスペース区切り文字列)をチェックします
  • hasPermission() は permissions クレーム(配列。Auth0 Dashboard で API の RBAC を有効にする必要があります)をチェックします
9. アクセストークンのクレーム

認証済みユーザーは、動的にクレームへアクセスできる StatelessUser インスタンスです。

Route::middleware('auth:auth0-api')->get('/profile', function () {
    $user = auth('auth0-api')->user();

    return response()->json([
        'sub' => $user->getAuthIdentifier(),
        'email' => $user->email,
        'permissions' => $user->permissions ?? [],
        'all_claims' => $user->jsonSerialize(),
    ]);
});

クレームには次の方法でアクセスします:

  • $user->getAuthIdentifier() - sub クレームを返します
  • $user->claim_name - __get による動的なプロパティアクセス
  • $user->getAttribute('claim_name') - 明示的なアクセス
  • $user->jsonSerialize() - すべてのクレームを配列で取得します
10. API をテストする

エージェントへの指示: Laravel の開発サーバーを起動し、認証情報なしで基本的なエンドポイントが動作することを確認してください:

php artisan serve &
sleep 2
curl -s -H "Accept: application/json" http://localhost:8000/api/public
curl -s -o /dev/null -w "%{http_code}" -H "Accept: application/json" http://localhost:8000/api/private
  • /api/public は {"message":"Public endpoint - no authentication required"} を返すはずです
  • /api/private は HTTP 401 を返すはずです

重要: -H "Accept: application/json" ヘッダーは必須です。これがない場合、Laravel の Authenticate ミドルウェアは 401 ではなく 302 リダイレクトを返します。

両方のテストに合格した場合、ガードは動作しています。完了したらバックグラウンドサーバーを終了してください:

kill %1 2>/dev/null

失敗時の確認: サーバーの起動に失敗した場合、または予期しないレスポンスが返る場合は、config/auth0.php が存在し、.env に AUTH0_DOMAIN と AUTH0_AUDIENCE が設定されていることを確認してください。5~6 回試しても失敗する場合は、AskUserQuestion を使用してください。

エージェントへの指示:停止 - 基本テスト合格後に確認してください。

public/401 テストに合格したら、ユーザーに尋ねてください:

"API がセットアップされ、ガードが動作しています(トークンなしの場合、public は 200 を返し、private は 401 を返します)。実際のアクセストークンを使ったテストのセットアップをお手伝いしましょうか?

  1. はい - テストトークンを取得するための M2M アプリケーションの設定をお手伝いします。
  2. いいえ - 今回はここまでにします。

どちらをご希望ですか?"

ユーザーが「はい」と答えない限り、M2M/トークンのセットアップに進まないでください。

エージェントへの指示(M2M アプリのセットアップ - ユーザーがテストを希望する場合のみ):

ユーザーがテストのセットアップを選択した場合は、次のように尋ねてください:

"保護されたエンドポイントをテストするには、この API のトークンをリクエストする権限を持つ Machine-to-Machine(M2M)アプリケーションが必要です。

  1. 新規作成 - 新しい M2M アプリケーションを作成し、この API へのアクセスを許可します。
  2. 既存のものを使用 - すでに M2M アプリケーションをお持ちです。Client ID をお知らせいただければ、この API へのアクセスを許可します。

どちらをご希望ですか?(1 = 新規作成 / 2 = 既存のものを使用)"

ユーザーが回答するまで先に進まないでください。

ユーザーが「新規作成」を選択した場合:

auth0 apps create \
  --name "${PWD##*/} (Test App)" \
  --type m2m \
  --no-input --json

jq を使用して JSON を解析し、client_id を抽出してください。--reveal-secrets は使用しないでください。 次に、クライアントグラントを作成してください:

auth0 api post "client-grants" --data '{
  "client_id": "<CLIENT_ID>",
  "audience": "<API_IDENTIFIER>",
  "scope": ["<SCOPES>"]
}'

ユーザーが「既存のものを使用」を選択した場合: Client ID を尋ねてください。クライアントグラントを作成してください(409 conflict はすでに許可済みであることを示すため、問題ありません)。 エージェントへの指示(トークンの分離 — 重大):

エージェントはアクセストークンの値を直接見たり、表示したりしてはなりません。

  • auth0 test token を単独で実行しないでください
  • ユーザーにトークンを貼り付けるよう求めないでください
  • トークンの値を出力したり、保存したりしないでください

安全なテスト(単一コマンドチェーン):

php artisan serve &
sleep 2
TEST_TOKEN=$(auth0 test token <M2M_CLIENT_ID> --audience <AUDIENCE> --scopes <SCOPE1,SCOPE2> 2>/dev/null | grep -o 'ey[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*') && \
[ -n "$TEST_TOKEN" ] && echo "Token acquired (${#TEST_TOKEN} chars)" && \
curl -s -H "Accept: application/json" -H "Authorization: Bearer $TEST_TOKEN" http://localhost:8000/api/private
kill %1 2>/dev/null

ユーザーがテストを依頼していない場合は、手動で実行するコマンドを提示してください:

auth0 test token <CLIENT_ID> --audience <AUDIENCE> --scopes <SCOPE1,SCOPE2>
curl -H "Accept: application/json" -H "Authorization: Bearer <PASTE_TOKEN_HERE>" http://localhost:8000/api/private

サーバーを起動します:

php artisan serve

パブリックエンドポイントをテストします(トークンは不要です):

curl -H "Accept: application/json" http://localhost:8000/api/public

トークンなしで保護されたエンドポイントをテストします(401 が返されるはずです):

curl -H "Accept: application/json" http://localhost:8000/api/private

注:Accept: application/json ヘッダーは必須です。これがない場合、Laravel は 401 ではなくリダイレクト(302)を返します。

トークンを使って保護されたエンドポイントをテストします:

curl http://localhost:8000/api/private \
  -H "Accept: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Auth0 Dashboard -> APIs -> Test タブ、または上記で説明した M2M フローを使って、テスト用トークンを取得してください。


よくある間違い

間違い修正方法
API ルートに auth0.authenticator ドライバーを使用するAPI ガードには auth0.authorizer を使用する必要があります。auth0.authenticator はセッションベースの Web アプリ用です
API ルートに auth:web ミドルウェアを使用するAPI ガードを指定するには auth:auth0-api を使用します
Auth0 で API ではなく Application を作成したAPI リソースを作成する必要があります(Dashboard -> Applications -> APIs)
https:// プレフィックス付きで domain を渡すhttps://tenant.us.auth0.com ではなく、tenant.us.auth0.com のようにドメインのみを指定します
auth0/auth0-php を直接使用するSDK を Laravel のガードおよびミドルウェアでラップする auth0/login を使用します
設定を公開していない設定の前に php artisan vendor:publish --tag=auth0 を実行します
.env に AUTH0_AUDIENCE がないトークンの検証に必須です。設定しないと、正しいオーディエンスに対してトークンを検証できません
ガード名を指定せずに $request->user() を使用するデフォルトでは web ガードが使用されます。auth('auth0-api')->user() または $request->user('auth0-api') を使用します
$user->scope を文字列として確認するJWT の scope クレームはスペース区切りです。文字列比較ではなく hasScope() を使用します
RBAC を有効にせず hasPermission() を呼び出すAuth0 Dashboard -> APIs -> Settings で「Add Permissions in the Access Token」を有効にする必要があります
API 認証に ID トークンを使用するアクセストークンを使用する必要があります。ID トークンはクライアントアプリ用です
API ガードに configuration => 'web' を設定するconfig/auth0.php の STRATEGY_API 設定に対応する 'api' を指定する必要があります
Accept: application/json ヘッダーを付けずに curl でテストするLaravel は 401 ではなくリダイレクト(302)を返します。API リクエストには必ず Accept: application/json を送信してください
API で定義されていないスコープに対して hasScope() が false を返すAuth0 Dashboard の API リソースでスコープを定義する必要があります。トークンリクエストでスコープを要求しても、定義されていなければ付与されません
M2M トークンで hasPermission() が false を返すRBAC の権限がトークンに埋め込まれるのは、ユーザーベースのフロー(Authorization Code)から発行されたトークンのみです。クライアントクレデンシャルのグラントでは埋め込まれません
Laravel 11 以降で routes/api.php がないphp artisan install:api を実行して API ルーティングを生成します。Laravel 11 ではデフォルトで含まれていません

主要な SDK メソッド

メソッド戻り値目的
auth('auth0-api')->user()?StatelessUser認証済みユーザーを返します。該当するユーザーがいない場合は null を返します
auth('auth0-api')->check()boolリクエストに有効なトークンがあるかどうかを返します
auth('auth0-api')->hasScope($scope)boolトークンに特定のスコープがあるかどうかを確認します
auth('auth0-api')->hasPermission($perm)boolトークンに特定の RBAC 権限があるかどうかを確認します
auth('auth0-api')->id()?stringsub クレームを直接返します
$user->getAuthIdentifier()int|string|nullsub クレームを返します
$user->getAttribute('key')mixed任意のクレーム値を返します
$user->jsonSerialize()arrayすべてのクレームを配列として返します
auth('auth0-api')->getCredential()?CredentialEntityデコード済みトークンデータを含む完全なクレデンシャル

関連スキル

  • auth0-laravel - セッションベース認証でログイン/ログアウトする Laravel Web アプリ向け
  • auth0-php-api - Laravel を使わないプレーンな PHP API 向け
  • auth0-quickstart - Auth0 の初期設定
  • auth0-mfa - 多要素認証を追加
  • auth0-cli - ターミナルから Auth0 リソースを管理

クイックリファレンス

ガード設定(config/auth.php):

'guards' => [
    'auth0-api' => [
        'driver' => 'auth0.authorizer',
        'provider' => 'auth0-provider',
        'configuration' => 'api',
    ],
],
'providers' => [
    'auth0-provider' => [
        'driver' => 'auth0.provider',
        'repository' => 'auth0.repository',
    ],
],

ルートの保護:

Route::middleware('auth:auth0-api')->group(function () {
    Route::get('/resource', fn() => response()->json([...]));
});

スコープ/権限の確認:

$guard = auth('auth0-api');
$guard->hasScope('read:messages');       // checks scope claim
$guard->hasPermission('delete:users');   // checks permissions claim (RBAC)

ユーザーのクレーム:

$user = auth('auth0-api')->user();
$user->getAuthIdentifier();   // sub
$user->email;                 // any claim via __get
$user->getAttribute('iss');   // explicit claim access

環境変数:

  • AUTH0_DOMAIN - Auth0 テナントのドメイン(例:tenant.us.auth0.com)
  • AUTH0_AUDIENCE - API 識別子(例:https://api.example.com)

一般的なユースケース:

  • ルートの保護 -> auth:auth0-api ミドルウェア(ステップ 7 を参照)
  • スコープの適用 -> hasScope()(ステップ 8 を参照)
  • 権限の適用 -> hasPermission()(ステップ 8 を参照)
  • 高度な設定 -> API リファレンス

詳細ドキュメント

  • セットアップガイド - Auth0 CLI のセットアップ、環境設定、テストトークンの取得
  • 統合ガイド - スコープ、権限、CORS、カスタムユーザーリポジトリ、エラー処理、複数ガード
  • API リファレンス - AuthorizationGuard API、StatelessUser、CredentialEntity、設定オプションの完全な説明

参考資料

コメント