Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Jwt Laravel Package

firebase/php-jwt

Encode and decode JSON Web Tokens (JWT) in PHP per RFC 7519. Supports common signing algorithms, key handling, and optional leeway for clock skew. Install via Composer; libsodium compatible via sodium_compat.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require firebase/php-jwt
    

    For environments without libsodium, add:

    composer require paragonie/sodium_compat
    
  2. First Use Case: Encode a JWT with a symmetric key (e.g., HS256):

    use Firebase\JWT\JWT;
    
    $key = 'your-secret-key';
    $payload = ['user_id' => 123, 'iat' => time()];
    $jwt = JWT::encode($payload, $key, 'HS256');
    

    Decode it in a Laravel middleware or controller:

    $decoded = JWT::decode($jwt, new \Firebase\JWT\Key($key, 'HS256'));
    $userId = $decoded->user_id;
    
  3. Key Locations:

    • Store keys in Laravel’s .env (e.g., JWT_SECRET=your-key).
    • Use Laravel’s config() helper to centralize keys:
      config(['jwt.secret' => env('JWT_SECRET')]);
      

Implementation Patterns

1. Authentication Workflows

  • API Token Generation:
    // In a Laravel controller or service
    $token = JWT::encode([
        'user_id' => auth()->id(),
        'roles' => ['admin'],
        'exp' => now()->addHours(1)->timestamp,
    ], config('jwt.secret'), 'HS256');
    return response()->json(['token' => $token]);
    
  • Token Validation Middleware:
    namespace App\Http\Middleware;
    use Closure;
    use Firebase\JWT\JWT;
    use Firebase\JWT\Key;
    
    class AuthenticateJWT
    {
        public function handle($request, Closure $next)
        {
            $token = $request->bearerToken();
            if (!$token) return response()->json(['error' => 'Unauthorized'], 401);
    
            try {
                $decoded = JWT::decode($token, new Key(config('jwt.secret'), 'HS256'));
                $request->merge(['user' => (array) $decoded]);
                return $next($request);
            } catch (\Exception $e) {
                return response()->json(['error' => 'Invalid token'], 401);
            }
        }
    }
    
    Register in app/Http/Kernel.php:
    protected $routeMiddleware = [
        'jwt.auth' => \App\Http\Middleware\AuthenticateJWT::class,
    ];
    

2. Asymmetric Keys (RS256/ES256)

  • Key Management: Store private/public keys in storage/app/jwt/ or use Laravel’s filesystem:
    $privateKey = file_get_contents(storage_path('app/jwt/private.pem'));
    $publicKey = file_get_contents(storage_path('app/jwt/public.pem'));
    
  • Encoding/Decoding:
    $jwt = JWT::encode($payload, $privateKey, 'RS256');
    $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
    

3. JWKS Integration

  • Dynamic Key Rotation: Use CachedKeySet for OAuth providers (e.g., Auth0, Firebase):
    use Firebase\JWT\CachedKeySet;
    use Firebase\JWT\JWT;
    
    $keySet = new CachedKeySet(
        'https://your-provider.com/.well-known/jwks.json',
        new \GuzzleHttp\Client(),
        new \GuzzleHttp\Psr7\HttpFactory(),
        \PhpFastCache\CacheManager::getInstance('files')
    );
    $decoded = JWT::decode($jwt, $keySet);
    
  • Laravel Service Provider: Bind CachedKeySet in AppServiceProvider:
    $this->app->singleton('jwks', function () {
        return new CachedKeySet(
            config('services.jwks_uri'),
            new \GuzzleHttp\Client(),
            new \GuzzleHttp\Psr7\HttpFactory(),
            \PhpFastCache\CacheManager::getInstance('files')
        );
    });
    

4. Custom Claims and Metadata

  • Add Metadata to Headers:
    $jwt = JWT::encode(
        $payload,
        $key,
        'HS256',
        null, // No custom header key
        ['jti' => 'unique-id-123', 'scope' => 'read:write']
    );
    
  • Extract Headers:
    $headers = new \stdClass();
    JWT::decode($jwt, new Key($key, 'HS256'), $headers);
    $scope = $headers->scope;
    

5. Testing

  • Unit Tests: Use Mockery to test JWT validation:
    $mockKey = Mockery::mock(\Firebase\JWT\Key::class);
    $mockKey->shouldReceive('getKey')->andReturn('test-key');
    $mockKey->shouldReceive('getAlgorithm')->andReturn('HS256');
    
    $decoded = JWT::decode($jwt, $mockKey);
    $this->assertEquals('expected_value', $decoded->claim);
    
  • Feature Tests: Test API endpoints with valid/invalid tokens:
    $response = $this->withHeader('Authorization', 'Bearer ' . $jwt)
        ->get('/api/protected');
    $response->assertStatus(200);
    

Gotchas and Tips

1. Common Pitfalls

  • Key Length: Symmetric keys (e.g., HS256) must be ≥32 characters. Use:
    $key = Str::random(32); // Laravel helper
    
  • Algorithm Mismatch: Always specify the algorithm when decoding:
    // ❌ Fails silently if algorithm is omitted!
    $decoded = JWT::decode($jwt, $key); // Wrong!
    
    // ✅ Correct
    $decoded = JWT::decode($jwt, new Key($key, 'HS256'));
    
  • Time Skew: Set $leeway to account for clock differences (e.g., between servers):
    JWT::$leeway = 60; // 1 minute
    

2. Debugging

  • Decode Without Validation: For debugging, manually decode the JWT parts (unsafe for production!):
    list($headerB64, $payloadB64, $signature) = explode('.', $jwt);
    $header = json_decode(base64_decode($headerB64));
    $payload = json_decode(base64_decode($payloadB64));
    
  • Exception Handling: Catch specific exceptions for granular error handling:
    try {
        $decoded = JWT::decode($jwt, $key);
    } catch (\Firebase\JWT\ExpiredException $e) {
        return response()->json(['error' => 'Token expired'], 401);
    } catch (\Firebase\JWT\SignatureInvalidException $e) {
        return response()->json(['error' => 'Invalid signature'], 401);
    }
    

3. Performance Tips

  • Cache JWKS: Use CachedKeySet to avoid repeated HTTP requests to JWKS endpoints.
  • Avoid Re-encoding: Reuse the same key for encoding/decoding in a session to reduce overhead.
  • Use stdClass: Decoded payloads are stdClass objects by default. Cast to array if needed:
    $arrayPayload = (array) $decoded;
    

4. Security Best Practices

  • Key Rotation: Use kid (key ID) claims to support multiple keys:
    $jwt = JWT::encode($payload, $privateKey, 'RS256', 'kid-123');
    $keys = [
        'kid-123' => new Key($publicKey1, 'RS256'),
        'kid-456' => new Key($publicKey2, 'RS256'),
    ];
    $decoded = JWT::decode($jwt, $keys);
    
  • Short-Lived Tokens: Set exp (expiration) claims to minimize exposure:
    $payload['exp'] = now()->addMinutes(15)->timestamp;
    
  • Avoid none Algorithm: Never use the none algorithm (disables signature verification).

5. Laravel-Specific Tips

  • Store Keys in Config: Add to config/jwt.php:
    return
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4