plugins/auth0/skills/auth0-laravel/SKILL.md
Use when adding login, logout, and user profile to a Laravel web application using session-based authentication - integrates auth0/login (laravel-auth0) for guard-based auth with auto-registered routes.
npx skillsauth add auth0/agent-skills auth0-laravelInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Add login, logout, and user profile to a Laravel web application using auth0/login (Laravel Auth0 SDK).
mbstring, openssl, jsonauth0-quickstart skill first| Scenario | Use Instead |
|----------|-------------|
| Laravel API with JWT Bearer validation | auth0-laravel-api (stateless token guard) |
| Plain PHP (no framework) web app | auth0-php |
| Plain PHP API | auth0-php-api |
| Single Page Applications | auth0-react, auth0-vue, or auth0-angular |
| Next.js applications | auth0-nextjs |
| Node.js web apps | auth0-express or auth0-fastify |
| Flask web apps | auth0-flask |
composer require auth0/login
The auth0/login package requires auth0/auth0-php (v8.19+) and will install it automatically. It also requires a PSR-18 HTTP client - if you don't already have one, install Guzzle:
composer require guzzlehttp/guzzle guzzlehttp/psr7
php artisan vendor:publish --tag=auth0
This creates config/auth0.php with guard, middleware, and route configuration.
Add to your .env:
APP_URL=http://localhost:8000
AUTH0_DOMAIN=your-tenant.us.auth0.com
AUTH0_CLIENT_ID=your_client_id
AUTH0_CLIENT_SECRET=your_client_secret
AUTH0_AUDIENCE=https://your-api-identifier
AUTH0_REDIRECT_URI=${APP_URL}/callback
AUTH0_DOMAIN is your Auth0 tenant domain (without https://). AUTH0_CLIENT_ID and AUTH0_CLIENT_SECRET come from your Auth0 Application settings. AUTH0_AUDIENCE must be set to an API identifier registered in Auth0 (Auth0 Dashboard > Applications > APIs) - without it, Auth0 returns opaque access tokens that the SDK cannot decode, causing a crash on session restore. The SDK uses APP_KEY as the cookie secret by default - no separate secret needed.
Important: Ensure APP_URL includes the port if using the built-in dev server (http://localhost:8000). Fresh Laravel installs default to http://localhost (no port) which causes callback URL mismatches.
In your Auth0 Application settings:
http://localhost:8000/callbackhttp://localhost:8000Update config/auth.php to use Auth0 guards:
'guards' => [
'web' => [
'driver' => 'auth0.authenticator',
'provider' => 'auth0-provider',
'configuration' => 'web',
],
],
'providers' => [
'auth0-provider' => [
'driver' => 'auth0.provider',
'repository' => 'auth0.repository',
],
],
The configuration key maps to the guard definition in config/auth0.php (web uses STRATEGY_REGULAR with session-based auth). We override the default web guard so that Laravel's built-in auth middleware and auth()->user() work without specifying a guard name. The SDK also auto-registers an auth0-session guard with identical config, but overriding web is simpler.
The SDK automatically registers these routes when registerAuthenticationRoutes is true in config/auth0.php:
GET /login - Redirects to Auth0 Universal LoginGET /callback - Handles OAuth callback, exchanges code for tokensGET /logout - Destroys session and redirects to Auth0 logoutNo manual route definitions needed for the auth flow.
In routes/web.php:
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('home', ['user' => auth()->user()]);
});
Route::middleware('auth')->group(function () {
Route::get('/profile', function () {
return view('profile', ['user' => auth()->user()]);
});
});
The standard auth middleware works with the Auth0 guard. Unauthenticated users are redirected to /login.
Create resources/views/home.blade.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home</title>
</head>
<body>
@if($user)
<h1>Welcome, {{ $user->name }}!</h1>
<p><a href="/profile">Profile</a></p>
<p><a href="/logout">Logout</a></p>
@else
<h1>Welcome</h1>
<p><a href="/login">Login</a></p>
@endif
</body>
</html>
Create resources/views/profile.blade.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Profile</title>
</head>
<body>
<h1>{{ $user->name }}</h1>
<p>Email: {{ $user->email }}</p>
<img src="{{ $user->picture }}" alt="avatar" width="100" />
<hr>
<h2>User Claims</h2>
<pre>{{ json_encode($user->jsonSerialize(), JSON_PRETTY_PRINT) }}</pre>
<p><a href="/">Home</a> | <a href="/logout">Logout</a></p>
</body>
</html>
php artisan serve
Visit http://localhost:8000 and click Login.
Important: Always access the app via http://localhost:8000 (not http://127.0.0.1:8000). The callback URL uses localhost, so the session cookie must be set for localhost to persist across the Auth0 login redirect. Using 127.0.0.1 causes an "Invalid state" error because the session cookie won't be sent to the localhost callback URL.
| Mistake | Fix |
|---------|-----|
| Using auth0/auth0-php directly in Laravel | Use auth0/login which wraps the SDK with Laravel guards, middleware, and routes |
| App created as SPA type in Auth0 Dashboard | Must be Regular Web Application for server-side session auth |
| Missing callback URL in Auth0 Dashboard | Add http://localhost:8000/callback to Allowed Callback URLs |
| Missing logout URL in Auth0 Dashboard | Add http://localhost:8000 to Allowed Logout URLs |
| Not publishing the config | Run php artisan vendor:publish --tag=auth0 before configuring |
| Using wrong guard driver name | Driver is auth0.authenticator (not auth0 or auth0.guard) |
| Forgetting to set APP_KEY | Run php artisan key:generate - the SDK uses this as cookie secret |
| Calling Auth0::getCredentials() directly | Use Laravel's auth()->user() - the SDK integrates via guards |
| Manually defining /login, /callback, /logout routes | Routes are auto-registered by the service provider |
| Setting AUTH0_DOMAIN with https:// prefix | Use bare domain: tenant.us.auth0.com not https://tenant.us.auth0.com |
| Using $request->user() without middleware | Only available in routes with the auth middleware applied |
| Missing AUTH0_AUDIENCE env var | Without an audience, Auth0 returns opaque tokens the SDK cannot parse - causes "JWT string must contain two dots" crash |
| Visiting http://127.0.0.1:8000 instead of http://localhost:8000 | Session cookies set for 127.0.0.1 won't be sent to the localhost callback - causes "Invalid state" error |
| Using $user->getName() or $user->getEmail() | StatefulUser uses magic __get - use $user->name, $user->email, $user->picture |
| Method | Usage | Purpose |
|--------|-------|---------|
| auth()->user() | In routes/controllers | Returns the authenticated StatefulUser or null |
| auth()->check() | In routes/controllers/views | Returns true if user is authenticated |
| auth()->guard('web') | When using multiple guards | Gets a specific Auth0 guard instance |
| $user->name | On user object | User's display name (via __get magic) |
| $user->email | On user object | User's email (via __get magic) |
| $user->picture | On user object | User's avatar URL (via __get magic) |
| $user->getAuthIdentifier() | On user object | Returns the Auth0 sub claim |
| $user->getAttribute('claim') | On user object | Returns any claim value explicitly |
| $user->jsonSerialize() | On user object | Returns all user claims as array |
The authenticated user is a StatefulUser instance implementing Laravel's Authenticatable contract. It uses __get magic for property-style access to claims:
$user = auth()->user();
$user->name; // display name (via __get)
$user->email; // email address (via __get)
$user->picture; // avatar URL (via __get)
$user->email_verified; // any claim via property access
$user->getAuthIdentifier(); // Auth0 'sub' (e.g. 'auth0|abc123')
$user->getAttribute('sub'); // explicit claim access
$user->jsonSerialize(); // all claims as array
Access any ID token claim as a property: $user->nickname, $user->updated_at, $user->sub, etc. For explicit access, use $user->getAttribute('claim_name').
auth0-laravel-api - Protect Laravel API routes with JWT Bearer token validationauth0-php - Plain PHP web apps without a frameworkauth0-quickstart - Initial Auth0 setupauth0-mfa - Add Multi-Factor Authenticationauth0-cli - Manage Auth0 resources from the terminalGuard configuration (config/auth.php):
'guards' => [
'web' => [
'driver' => 'auth0.authenticator',
'provider' => 'auth0-provider',
'configuration' => 'web',
],
],
'providers' => [
'auth0-provider' => [
'driver' => 'auth0.provider',
'repository' => 'auth0.repository',
],
],
Route protection:
Route::middleware('auth')->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
});
Check auth in Blade:
@auth
<p>Hello, {{ auth()->user()->name }}</p>
@else
<a href="/login">Login</a>
@endauth
Environment variables:
APP_URL - Application URL with port (e.g. http://localhost:8000)AUTH0_DOMAIN - Auth0 tenant domain (e.g. tenant.us.auth0.com)AUTH0_CLIENT_ID - Application client IDAUTH0_CLIENT_SECRET - Application client secretAUTH0_AUDIENCE - API identifier (required for JWT access tokens)AUTH0_REDIRECT_URI - Callback URL (defaults to ${APP_URL}/callback)APP_KEY - Laravel app key, used as cookie encryption secrettools
Use when securing Laravel API endpoints with JWT Bearer token validation, scope/permission checks, or stateless auth - integrates auth0/login (laravel-auth0) with the AuthorizationGuard for REST APIs receiving access tokens from SPAs, mobile apps, or other clients. Triggers on: Laravel API auth, auth0.authorizer, AuthorizationGuard, Laravel JWT, stateless Bearer.
development
Use when adding Auth0 authentication to a Flutter web application — integrates the auth0_flutter SDK (web platform) for browser-based authentication using redirect login, popup login, and credential caching.
development
Use when adding Auth0 authentication to a Flutter mobile application (iOS/Android) — integrates the auth0_flutter SDK (native platform) for Web Auth login/logout via the system browser, with secure credential storage and biometric protection through the CredentialsManager.
tools
Use when adding Auth0 authentication to Windows Forms (WinForms) desktop applications - integrates Auth0.OidcClient.WinForms NuGet package for native login, logout, token refresh, and user profile. Trigger on WinForms authentication, add login to WinForms, Auth0 WinForms, .NET Windows Forms auth, Windows desktop auth