mcpField
A
auth0-laravel-api

auth0-laravel-api

github.com/auth0安全55210 次安装1 天前更新
代码仓库

关于 auth0-laravel-api

使用 auth0/login 验证 Auth0 访问令牌、保护 Laravel API 端点的 Agent 技能。它指导配置无状态 API 守卫,并检查 JWT 声明、权限范围和权限。

主要功能

  1. 01配置 Auth0 API 守卫
  2. 02验证 JWT 访问令牌
  3. 03检查权限范围与权限
  4. 04在 Laravel 中读取令牌声明
  5. 05设置受保护的 API 路由

适用场景

  1. 01使用 Auth0 保护 Laravel API 端点
  2. 02按令牌权限范围限制路由
  3. 03检查 API 请求中的权限

安装

复制下面的命令,在终端中运行。

$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 资源(必须是 API,而非 Application)
  • 如果尚未设置 Auth0,请先使用 auth0-quickstart skill

不适用场景

场景请改用
带有登录/注销界面的 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
签发令牌此 skill 用于验证访问令牌,而非签发令牌

快速入门工作流

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,其中包含 guard、中间件和路由配置。

3. 创建 Auth0 API

你需要在 Auth0 中创建一个 API(而非 Application)。

停止——继续之前先询问用户。

确切地询问以下问题,并等待用户回答后再进行任何其他操作:

"你希望如何创建 Auth0 API 资源?

  1. 自动创建——我将运行 Auth0 CLI 脚本来创建资源,并自动将确切的值写入你的 .env。
  2. 手动创建——你在 Auth0 Dashboard 中自行创建 API(或通过 auth0 apis create 创建),并向我提供 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. 配置 Auth Guard

更新 config/auth.php,添加 API guard:

'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 guard
  • SDK 会使用此配置自动注册 auth0-api guard,但显式定义会更加清晰
6. 验证 Auth0 配置

发布配置后,验证 config/auth0.php 包含 guards.api 键,且其 strategy 设置为 SdkConfiguration::STRATEGY_API(值为 'api')。已发布的配置中已经包含此项,无需手动编辑。

已发布的文件使用类常量作为键(例如 Configuration::CONFIG_STRATEGY),这些常量在运行时会解析为相同的字符串值:

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

已发布的配置还包含 default 和 web guard 部分——仅用于 API 的场景可以忽略它们。STRATEGY_API 策略会禁用所有会话/ Cookie 机制,并启用无状态 Bearer 令牌验证。

7. 添加受保护的 API 路由

Laravel 11+ 默认不包含 routes/api.php。如果该文件不存在,请创建它:

php artisan install:api

此操作会创建 routes/api.php,并在 bootstrap/app.php 中为其注册 /api 前缀。它还会安装 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 端点验证签名,并检查颁发者和受众声明。没有有效令牌的请求会收到 401 响应。

8. 作用域和权限检查

使用 guard 的 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

**Agent 指令:**启动 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 中间件会返回 302 重定向,而不是 401。

如果两项测试都通过,则 guard 正常工作。完成后关闭后台服务器:

kill %1 2>/dev/null

**故障检查:**如果服务器启动失败或响应不符合预期,请检查 config/auth0.php 是否存在,以及 .env 中是否设置了 AUTH0_DOMAIN 和 AUTH0_AUDIENCE。失败迭代 5-6 次后,请使用 AskUserQuestion。

Agent 指令:停止——基本测试通过后询问用户。

/api/public 和 401 测试通过后,询问用户:

“你的 API 已设置完成,guard 也正常工作(无令牌时,public 返回 200,private 返回 401)。你希望我帮你设置使用真实访问令牌进行测试吗?

  1. 是——我会帮你配置 M2M 应用以获取测试令牌。
  2. 否——我暂时就到这里。

你更倾向哪种?”

除非用户同意,否则不要继续设置 M2M/令牌。

Agent 指令(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。 然后创建 client grant:

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

如果用户选择“使用现有应用”: 询问 Client ID。创建 client grant(409 冲突表示已获授权,可忽略)。 Agent 指令(令牌隔离 - 至关重要):

Agent 绝不能直接查看或显示访问令牌值。

  • 不要单独运行 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 会重定向(302),而不是返回 401。

使用令牌测试受保护端点:

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 中间件使用 auth:auth0-api 指定 API 守卫
在 Auth0 中创建了 Application,而不是 API必须创建 API 资源(Dashboard -> Applications -> APIs)
使用带 https:// 前缀的 domain使用不带前缀的域名:tenant.us.auth0.com,而不是 https://tenant.us.auth0.com
直接使用 auth0/auth0-php使用 auth0/login,它通过 Laravel 守卫和中间件封装了 SDK
未发布配置配置前运行 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”
使用 ID 令牌进行 API 身份验证必须使用 访问令牌——ID 令牌供客户端应用使用
在 API 守卫上设置 configuration => 'web'必须设为 'api',它映射到 config/auth0.php 中的 STRATEGY_API 配置
使用 curl 测试时未提供 Accept: application/json 标头Laravel 会返回 302 重定向,而不是 401——API 请求始终发送 Accept: application/json
对 API 中未定义的作用域调用 hasScope() 时返回 false必须在 Auth0 Dashboard 中的 API 资源上定义作用域——在令牌请求中请求某个作用域并不会授予该作用域,除非已定义
对 M2M 令牌调用 hasPermission() 时返回 falseRBAC 权限仅嵌入基于用户的流程(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()?string直接返回 sub 声明
$user->getAuthIdentifier()int|string|null返回 sub 声明
$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 资源

快速参考

Guard 配置(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、自定义用户存储库、错误处理、多 Guard
  • API 参考 - 完整的 AuthorizationGuard API、StatelessUser、CredentialEntity、配置选项

参考资料

评论

支持 Markdown