Deps: Add admin9/laravel-oidc-server
This commit is contained in:
parent
ce209cd14d
commit
9c44d65f94
205
.claude/skills/passport-development/SKILL.md
Normal file
205
.claude/skills/passport-development/SKILL.md
Normal file
@ -0,0 +1,205 @@
|
||||
---
|
||||
name: passport-development
|
||||
description: "Develops OAuth2 API authentication with Laravel Passport. Activates when installing or configuring Passport; setting up OAuth2 grants (authorization code, client credentials, personal access tokens, device authorization); managing OAuth clients; protecting API routes with token authentication; defining or checking token scopes; configuring SPA cookie authentication; handling token lifetimes and refresh tokens; or when the user mentions Passport, OAuth2, API tokens, bearer tokens, or API authentication. Make sure to use this skill whenever the user works with OAuth2, API tokens, or third-party API access, even if they don't explicitly mention Passport."
|
||||
license: MIT
|
||||
metadata:
|
||||
author: laravel
|
||||
---
|
||||
|
||||
# Passport OAuth2 Authentication
|
||||
|
||||
## Documentation First
|
||||
|
||||
**Always use `search-docs` before writing Passport code.** The documentation covers every grant type, configuration option, and edge case in detail. This skill teaches you how to navigate Passport — the docs have the implementation specifics.
|
||||
|
||||
```
|
||||
search-docs(queries: ["Passport installation"], packages: ["laravel/framework@12.x"])
|
||||
```
|
||||
|
||||
The Passport docs live under the `laravel/framework` package — not `laravel/passport`.
|
||||
|
||||
## When to Apply
|
||||
|
||||
Activate this skill when:
|
||||
|
||||
- Installing or configuring Passport
|
||||
- Setting up OAuth2 authorization grants
|
||||
- Creating or managing OAuth clients
|
||||
- Protecting API routes with token authentication
|
||||
- Defining or checking token scopes
|
||||
- Configuring SPA cookie-based authentication
|
||||
- Choosing between Passport and Sanctum
|
||||
|
||||
## Passport vs. Sanctum
|
||||
|
||||
**Passport** is a full OAuth2 server — use it when third-party applications need to consume your API and when you need OAuth2 authorization code grants, client credentials for machine-to-machine auth, or device authorization flow.
|
||||
|
||||
**Sanctum** is simpler — use it when first-party SPAs, third parties, or mobile apps consume the API but you don't need the full OAuth2 grant flows.
|
||||
|
||||
## Installation
|
||||
|
||||
Three steps are always required:
|
||||
|
||||
### 1. Install Passport
|
||||
|
||||
```bash
|
||||
php artisan install:api --passport
|
||||
```
|
||||
|
||||
This publishes migrations, generates encryption keys, and registers routes.
|
||||
|
||||
### 2. Configure the User model
|
||||
|
||||
The User model needs both the `HasApiTokens` trait AND the `OAuthenticatable` interface. Missing the interface is the most common Passport setup mistake — it causes runtime errors that can be confusing to debug.
|
||||
|
||||
```php
|
||||
use Laravel\Passport\Contracts\OAuthenticatable;
|
||||
use Laravel\Passport\HasApiTokens;
|
||||
|
||||
class User extends Authenticatable implements OAuthenticatable
|
||||
{
|
||||
use HasApiTokens;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Configure the auth guard
|
||||
|
||||
The `api` guard must use the `passport` driver in `config/auth.php`. Using `token` or `sanctum` here silently breaks Passport authentication.
|
||||
|
||||
```php
|
||||
'guards' => [
|
||||
'api' => [
|
||||
'driver' => 'passport',
|
||||
'provider' => 'users',
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
## Choosing a Grant Type
|
||||
|
||||
Matching the right grant to the use case is the most important Passport decision. Use `search-docs` for implementation details of any grant.
|
||||
|
||||
| Use Case | Grant Type | Client Flag |
|
||||
|----------|-----------|-------------|
|
||||
| Third-party app accessing user data | Authorization Code | (default) |
|
||||
| Mobile/SPA without client secret | Authorization Code + PKCE | `--public` |
|
||||
| Machine-to-machine, no user context | Client Credentials | `--client` |
|
||||
| User-generated API keys | Personal Access Tokens | `--personal` |
|
||||
| Smart TV, CLI, IoT devices | Device Authorization | `--device` |
|
||||
|
||||
**Legacy grants** (Password, Implicit) are disabled by default and not recommended. They must be explicitly enabled with `Passport::enablePasswordGrant()` or `Passport::enableImplicitGrant()`.
|
||||
|
||||
## Client Management
|
||||
|
||||
Create clients with the appropriate flag for the grant type:
|
||||
|
||||
```bash
|
||||
php artisan passport:client # Authorization code
|
||||
|
||||
php artisan passport:client --public # PKCE (no secret)
|
||||
|
||||
php artisan passport:client --client # Client credentials
|
||||
|
||||
php artisan passport:client --personal # Personal access tokens
|
||||
|
||||
php artisan passport:client --device # Device authorization
|
||||
|
||||
```
|
||||
|
||||
Additional flags: `--name=`, `--redirect_uri=`, `--provider=`.
|
||||
|
||||
Client secrets are hashed by default — the plain-text secret is only shown at creation time and cannot be retrieved later.
|
||||
|
||||
## Protecting Routes
|
||||
|
||||
Apply `auth:api` middleware. Clients send tokens via the `Authorization: Bearer <token>` header.
|
||||
|
||||
```php
|
||||
Route::get('/user', function (Request $request) {
|
||||
return $request->user();
|
||||
})->middleware('auth:api');
|
||||
```
|
||||
|
||||
### Scope Enforcement
|
||||
|
||||
Scope middleware must come alongside `auth:api`:
|
||||
|
||||
- `CheckToken::using('scope1', 'scope2')` — requires ALL listed scopes
|
||||
- `CheckTokenForAnyScope::using('scope1', 'scope2')` — requires ANY listed scope
|
||||
- `EnsureClientIsResourceOwner::using('scope1')` — restricts to client credential tokens
|
||||
|
||||
```php
|
||||
use Laravel\Passport\Http\Middleware\CheckToken;
|
||||
|
||||
Route::get('/orders', function () {
|
||||
// ...
|
||||
})->middleware(['auth:api', CheckToken::using('orders:read')]);
|
||||
```
|
||||
|
||||
### Programmatic scope checking
|
||||
|
||||
```php
|
||||
if ($request->user()->tokenCan('place-orders')) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Use `search-docs` for full scope middleware registration and usage patterns.
|
||||
|
||||
## Key Configuration
|
||||
|
||||
Configure in `AppServiceProvider::boot()`. Use `search-docs` for the full list of options.
|
||||
|
||||
```php
|
||||
// Token lifetimes (each is independent)
|
||||
Passport::tokensExpireIn(now()->addDays(15));
|
||||
Passport::refreshTokensExpireIn(now()->addDays(30));
|
||||
Passport::personalAccessTokensExpireIn(now()->addMonths(6));
|
||||
|
||||
// Define scopes
|
||||
Passport::tokensCan([
|
||||
'place-orders' => 'Place orders',
|
||||
'check-status' => 'Check order status',
|
||||
]);
|
||||
```
|
||||
|
||||
## SPA Cookie Authentication
|
||||
|
||||
For first-party SPAs, the `CreateFreshApiToken` middleware issues a `laravel_token` cookie containing an encrypted JWT. The SPA must include CSRF tokens — missing the `X-CSRF-TOKEN` or `X-XSRF-TOKEN` header causes 419 errors.
|
||||
|
||||
Use `search-docs` for setup details — this feature has specific CSRF and cookie configuration requirements.
|
||||
|
||||
## Testing
|
||||
|
||||
Passport provides helpers to bypass full OAuth flows in tests:
|
||||
|
||||
```php
|
||||
Passport::actingAs($user, ['scope1', 'scope2']);
|
||||
Passport::actingAsClient($client, ['scope1']);
|
||||
```
|
||||
|
||||
## Token Maintenance
|
||||
|
||||
```bash
|
||||
php artisan passport:purge # Purge revoked & expired
|
||||
|
||||
php artisan passport:purge --revoked # Only revoked
|
||||
|
||||
php artisan passport:purge --expired # Only expired
|
||||
|
||||
```
|
||||
|
||||
Schedule `passport:purge` for regular expired token clean-up.
|
||||
|
||||
## Events
|
||||
|
||||
All in `Laravel\Passport\Events`: `AccessTokenCreated`, `AccessTokenRevoked`, `RefreshTokenCreated`.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
- **Missing `OAuthenticatable` interface** — both the `HasApiTokens` trait and the `OAuthenticatable` interface are required on the User model. Missing the interface causes runtime errors.
|
||||
- **Wrong guard driver** — the `api` guard must use `passport`, not `token` or `sanctum`. This fails silently.
|
||||
- **Token lifetime confusion** — access token, refresh token, and personal access token lifetimes are all independent settings.
|
||||
- **Missing CSRF for SPA cookie auth** — `CreateFreshApiToken` requires CSRF tokens. Use `Passport::ignoreCsrfToken()` only if you understand the security implications.
|
||||
- **Client secrets are hashed** — the plain-text secret is only available at creation time.
|
||||
- **Legacy grants are disabled** — Password and Implicit grants must be explicitly enabled and are not recommended.
|
||||
@ -5,6 +5,8 @@
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Admin9\OidcServer\Concerns\HasOidcClaims;
|
||||
use Admin9\OidcServer\Contracts\OidcUserInterface;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Database\Factories\UserFactory;
|
||||
use DateTime;
|
||||
@ -24,10 +26,10 @@
|
||||
*/
|
||||
#[Fillable(['name', 'email', 'password', 'immutable_id'])]
|
||||
#[Hidden(['password', 'two_factor_secret', 'two_factor_recovery_codes', 'remember_token'])]
|
||||
final class User extends Authenticatable
|
||||
final class User extends Authenticatable implements OidcUserInterface
|
||||
{
|
||||
/** @use HasFactory<UserFactory> */
|
||||
use HasFactory, SoftDeletes;
|
||||
use HasFactory, HasOidcClaims, SoftDeletes;
|
||||
|
||||
use HasRoles;
|
||||
use Notifiable;
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
"ext-libxml": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-zlib": "*",
|
||||
"admin9/laravel-oidc-server": "^1.1",
|
||||
"gehrisandro/tailwind-merge-laravel": "^1.4",
|
||||
"laravel/fortify": "^1.34",
|
||||
"laravel/framework": "^13.7",
|
||||
|
||||
66
composer.lock
generated
66
composer.lock
generated
@ -4,8 +4,72 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "b3aa0d920261f901b2242b3f9b1afb8c",
|
||||
"content-hash": "666b1735e7d483cade400d22019b7296",
|
||||
"packages": [
|
||||
{
|
||||
"name": "admin9/laravel-oidc-server",
|
||||
"version": "v1.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/admin9-labs/laravel-oidc-server.git",
|
||||
"reference": "4e8fb23dc96b17af555dbd9508e62f4e013395cd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/admin9-labs/laravel-oidc-server/zipball/4e8fb23dc96b17af555dbd9508e62f4e013395cd",
|
||||
"reference": "4e8fb23dc96b17af555dbd9508e62f4e013395cd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"defuse/php-encryption": "^2.4",
|
||||
"laravel/passport": "^12.0|^13.0",
|
||||
"lcobucci/jwt": "^5.0",
|
||||
"php": "^8.2",
|
||||
"spatie/laravel-package-tools": "^1.16"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^9.0|^10.0",
|
||||
"pestphp/pest": "^3.0",
|
||||
"phpunit/phpunit": "^11.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Admin9\\OidcServer\\OidcServerServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Admin9\\OidcServer\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "ADMIN9 Labs",
|
||||
"homepage": "https://github.com/admin9-labs"
|
||||
}
|
||||
],
|
||||
"description": "OpenID Connect Server for Laravel Passport — adds OIDC Discovery, JWKS, UserInfo, Token Introspection, Token Revocation, and RP-Initiated Logout.",
|
||||
"homepage": "https://github.com/admin9-labs/laravel-oidc-server",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"oauth2",
|
||||
"oidc",
|
||||
"openid-connect",
|
||||
"passport"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/admin9-labs/laravel-oidc-server/issues",
|
||||
"source": "https://github.com/admin9-labs/laravel-oidc-server"
|
||||
},
|
||||
"time": "2026-03-13T14:18:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
"version": "v3.1.1",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user