AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Auth0 Laravel Api

skill-auth0-agent-skills-auth0-laravel-api · by auth0

>

No reviews yet
0 installs
15 views
0.0% view→install

Install

$ agentstack add skill-auth0-agent-skills-auth0-laravel-api

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-auth0-agent-skills-auth0-laravel-api)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Auth0 Laravel Api? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Auth0 Laravel API Integration

Protect Laravel API endpoints with JWT access token validation using auth0/login and the AuthorizationGuard.


Prerequisites

  • Laravel 11+ application
  • PHP 8.2+ with extensions: mbstring, openssl, json
  • Composer installed
  • Auth0 API resource configured (not an Application - must be an API)
  • If you don't have Auth0 set up yet, use the auth0-quickstart skill first

When NOT to Use

| Scenario | Use Instead | |----------|-------------| | Laravel web app with login/logout UI | auth0-laravel (session-based AuthenticationGuard) | | Plain PHP API (no framework) | auth0-php-api | | Plain PHP web app | auth0-php | | Single Page Applications | auth0-react, auth0-vue, or auth0-angular | | FastAPI / Python APIs | auth0-fastapi-api | | Express / Node.js APIs | express-oauth2-jwt-bearer | | Issuing tokens | This skill is for validating access tokens, not issuing them |


Quick Start Workflow

1. Install SDK

composer require auth0/login

The auth0/login package requires auth0/auth0-php (v8.19+) and installs it automatically. It also requires a PSR-18 HTTP client - if you don't already have one:

composer require guzzlehttp/guzzle guzzlehttp/psr7

2. Publish Configuration

php artisan vendor:publish --tag=auth0

This creates config/auth0.php with guard, middleware, and route configuration.

3. Create Auth0 API

You need an API (not Application) in Auth0.

> STOP - ask the user before proceeding. > > Ask exactly this question and wait for their answer before doing anything else: > > > "How would you like to create the Auth0 API resource? > > 1. Automated - I'll run Auth0 CLI scripts that create the resource and write the exact values to your .env automatically. > > 2. Manual - You create the API yourself in the Auth0 Dashboard (or via auth0 apis create) and provide me the Domain and Audience. > > > > Which do you prefer? (1 = Automated / 2 = Manual)" > > Do NOT proceed to any setup steps until the user has answered. Do NOT default to manual.

If the user chose Automated, follow the [Setup Guide](references/setup.md) for complete CLI scripts. The automated path writes .env for you - skip Step 4 below and proceed directly to Step 5.

If the user chose Manual, follow the [Setup Guide](references/setup.md) (Manual Setup section) for full instructions. Then continue with Step 4 below.

Quick reference for manual API creation:

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

Or create manually in Auth0 Dashboard -> Applications -> APIs

4. Configure Environment

Add to your .env:

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

AUTH0_DOMAIN is your Auth0 tenant domain (without https://). AUTH0_AUDIENCE is the API identifier you set when creating the API resource in Auth0.

5. Configure Auth Guard

Update config/auth.php to add the 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',
    ],
],

Key points:

  • driver must be auth0.authorizer (not auth0.authenticator which is for web apps)
  • configuration must be 'api' which maps to the api guard in config/auth0.php
  • The SDK auto-registers an auth0-api guard with this config, but defining it explicitly is clearer

6. Verify Auth0 Config

After publishing, verify that config/auth0.php contains a guards.api key with strategy set to SdkConfiguration::STRATEGY_API (value: 'api'). This is already present in the published config — no manual editing needed.

The published file uses class constants for keys (e.g., Configuration::CONFIG_STRATEGY), which resolve to the same string values at runtime:

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

The published config also includes default and web guard sections — these can be ignored for API-only usage. The STRATEGY_API strategy disables all session/cookie machinery and enables stateless Bearer token validation.

7. Add Protected API Routes

Laravel 11+ does not include routes/api.php by default. If the file does not exist, scaffold it:

php artisan install:api

This creates routes/api.php and registers it in bootstrap/app.php with the /api prefix. It also installs Laravel Sanctum, which is unused but harmless alongside Auth0.

In 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(),
        ]);
    });
});

The auth:auth0-api middleware validates the Bearer token, verifies the signature against the JWKS endpoint, and checks issuer and audience claims. Requests without a valid token receive a 401 response.

8. Scope and Permission Checks

Use the guard's hasScope() and hasPermission() methods:

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() checks the scope claim (space-separated string in the JWT)
  • hasPermission() checks the permissions claim (array, requires RBAC enabled on the API in Auth0 Dashboard)

9. Access Token Claims

The authenticated user is a StatelessUser instance with dynamic claim access:

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(),
    ]);
});

Claims are accessed via:

  • $user->getAuthIdentifier() - Returns sub claim
  • $user->claim_name - Dynamic property access via __get
  • $user->getAttribute('claim_name') - Explicit access
  • $user->jsonSerialize() - All claims as array

10. Test the API

> Agent instruction: Start the Laravel dev server and verify the basic endpoints work without credentials: > ``bash > 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 should return {"message":"Public endpoint - no authentication required"} > - /api/private should return HTTP 401 > > **Important:** The -H "Accept: application/json" header is required. Without it, Laravel's Authenticate middleware returns a 302 redirect instead of 401. > > If both pass, the guard is working. Kill the background server when done: > `bash > kill %1 2>/dev/null > ` > > **Failcheck:** If the server fails to start or responses are unexpected, check that config/auth0.php exists and .env has AUTH0DOMAIN and AUTH0AUDIENCE set. After 5-6 failed iterations, use AskUserQuestion`.

> Agent instruction: STOP - ask after basic tests pass. > > Once public/401 tests pass, ask the user: > > > "Your API is set up and the guard is working (public returns 200, private returns 401 without a token). Would you like me to help you set up testing with a real access token? > > 1. Yes - I'll help you configure an M2M application to get test tokens. > > 2. No - I'm done for now. > > > > Which do you prefer?" > > Do NOT proceed with M2M/token setup unless the user says yes.

> Agent instruction (M2M app setup - only if user wants testing): > > If the user chose to set up testing, ask: > > > "To test your protected endpoints, you need a Machine-to-Machine (M2M) application authorized to request tokens for this API. > > 1. Create new - I'll create a new M2M application and authorize it for this API. > > 2. Use existing - You already have an M2M application. Provide the Client ID and I'll authorize it for this API. > > > > Which do you prefer? (1 = Create new / 2 = Use existing)" > > Do NOT proceed until the user answers. > > If the user chose "Create new": > ``bash > auth0 apps create \ > --name "${PWD##*/} (Test App)" \ > --type m2m \ > --no-input --json > ` > Parse JSON with jq to extract client_id. Do NOT use --reveal-secrets. > Then create a client grant: > `bash > auth0 api post "client-grants" --data '{ > "client_id": "", > "audience": "", > "scope": [""] > }' > `` > > If the user chose "Use existing": > Ask for Client ID. Create a client grant (409 conflict = already authorized, fine).

> Agent instruction (TOKEN ISOLATION - CRITICAL): > > The agent MUST NEVER directly see or display access token values. > - Do NOT run auth0 test token on its own > - Do NOT ask the user to paste their token > - Do NOT echo or store the token value > > Secure testing (single-command chain): > ``bash > php artisan serve & > sleep 2 > TEST_TOKEN=$(auth0 test token --audience --scopes 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 > ` > > **If the user does NOT ask to test**, provide commands for them to run manually: > `bash > auth0 test token --audience --scopes > curl -H "Accept: application/json" -H "Authorization: Bearer " http://localhost:8000/api/private > ``

Start the server:

php artisan serve

Test public endpoint (no token needed):

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

Test protected endpoint without token (should return 401):

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

Note: The Accept: application/json header is required. Without it, Laravel redirects (302) instead of returning 401.

Test protected endpoint with token:

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

Get a test token via Auth0 Dashboard -> APIs -> Test tab, or via the M2M flow described above.


Common Mistakes

| Mistake | Fix | |---------|-----| | Using auth0.authenticator driver for API routes | API guard must use auth0.authorizer - auth0.authenticator is for session-based web apps | | Using auth:web middleware for API routes | Use auth:auth0-api to specify the API guard | | Created an Application instead of an API in Auth0 | Must create an API resource (Dashboard -> Applications -> APIs) | | Passing domain with https:// prefix | Use bare domain: tenant.us.auth0.com not https://tenant.us.auth0.com | | Using auth0/auth0-php directly | Use auth0/login which wraps the SDK with Laravel guards and middleware | | Not publishing config | Run php artisan vendor:publish --tag=auth0 before configuring | | Missing AUTH0_AUDIENCE in .env | Required for token validation - without it, tokens can't be verified against the correct audience | | Using $request->user() without guard name | Defaults to the web guard - use auth('auth0-api')->user() or $request->user('auth0-api') | | Checking $user->scope as a string | The scope claim in JWTs is space-separated - use hasScope() instead of string comparison | | Calling hasPermission() without enabling RBAC | Must enable "Add Permissions in the Access Token" in Auth0 Dashboard -> APIs -> Settings | | Using ID tokens for API auth | Must use access tokens - ID tokens are for the client app | | Setting configuration => 'web' on the API guard | Must be 'api' which maps to the STRATEGY_API config in config/auth0.php | | Testing with curl without Accept: application/json header | Laravel returns 302 redirect instead of 401 - always send Accept: application/json for API requests | | hasScope() returns false for scopes not defined on the API | Scopes must be defined on the API resource in Auth0 Dashboard - requesting a scope in the token request does not grant it unless defined | | hasPermission() returns false with M2M tokens | RBAC permissions are only embedded in tokens from user-based flows (Authorization Code), not client-credentials grants | | routes/api.php missing in Laravel 11+ | Run php artisan install:api to scaffold API routing - Laravel 11 does not include it by default |


Key SDK Methods

| Method | Returns | Purpose | |--------|---------|---------| | auth('auth0-api')->user() | ?StatelessUser | Returns authenticated user or null | | auth('auth0-api')->check() | bool | Whether request has a valid token | | auth('auth0-api')->hasScope($scope) | bool | Check if token has a specific scope | | auth('auth0-api')->hasPermission($perm) | bool | Check if token has a specific RBAC permission | | auth('auth0-api')->id() | ?string | Returns the sub claim directly | | $user->getAuthIdentifier() | int\|string\|null | Returns sub claim | | $user->getAttribute('key') | mixed | Returns any claim value | | $user->jsonSerialize() | array | Returns all claims as array | | auth('auth0-api')->getCredential() | ?CredentialEntity | Full credential with decoded token data |


Related Skills

  • auth0-laravel - For Laravel web apps with login/logout using session-based auth
  • auth0-php-api - For plain PHP APIs without Laravel
  • auth0-quickstart - Initial Auth0 setup
  • auth0-mfa - Add Multi-Factor Authentication
  • auth0-cli - Manage Auth0 resources from the terminal

Quick Reference

Guard configuration (config/auth.php):

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

Route protection:

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

Scope/permission checks:

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

User claims:

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

Environment variables:

  • AUTH0_DOMAIN - Auth0 tenant domain (e.g. tenant.us.auth0.com)
  • AUTH0_AUDIENCE - API identifier (e.g. `https://api.example.com

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.