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, header access after verification, and clock-skew leeway. Install via Composer; optional sodium_compat for libsodium environments.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require firebase/php-jwt
    

    For asymmetric algorithms (e.g., RS256), ensure OpenSSL is enabled in your PHP environment. For libsodium support (e.g., EdDSA), install paragonie/sodium_compat:

    composer require paragonie/sodium_compat
    
  2. First Use Case: Generate a JWT for API authentication:

    use Firebase\JWT\JWT;
    
    $key = 'your-secret-key';
    $payload = [
        'user_id' => 123,
        'exp' => time() + 3600, // Expires in 1 hour
    ];
    
    $jwt = JWT::encode($payload, $key, 'HS256');
    
  3. Where to Look First:


Implementation Patterns

Common Workflows

1. API Authentication Middleware

Use JWT in Laravel middleware to validate requests:

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\ExpiredException;

public function handle($request, Closure $next)
{
    $token = $request->bearerToken();
    if (!$token) {
        return response()->json(['error' => 'Unauthorized'], 401);
    }

    try {
        $decoded = JWT::decode($token, new Key('secret', 'HS256'));
        $request->merge(['user' => (array) $decoded]);
        return $next($request);
    } catch (ExpiredException $e) {
        return response()->json(['error' => 'Token expired'], 401);
    } catch (\Exception $e) {
        return response()->json(['error' => 'Invalid token'], 401);
    }
}

2. Key Rotation with JWKS

Fetch and cache public keys from a JWKS endpoint (e.g., Auth0, Firebase):

use Firebase\JWT\JWK;
use Firebase\JWT\CachedKeySet;
use GuzzleHttp\Client;
use Phpfastcache\CacheManager;

$jwksUri = 'https://your-api.com/.well-known/jwks.json';
$httpClient = new Client();
$cache = CacheManager::getInstance('files');

$keySet = new CachedKeySet(
    $jwksUri,
    $httpClient,
    new \GuzzleHttp\Psr7\HttpFactory(),
    $cache,
    3600, // Cache for 1 hour
    true  // Enable rate limiting
);

$decoded = JWT::decode($jwt, $keySet);

3. Custom Claims and Validation

Extend payload validation logic:

$payload = [
    'iss' => 'your-app.com',
    'aud' => 'api.your-app.com',
    'scope' => ['read', 'write'],
    'exp' => time() + 3600,
];

$jwt = JWT::encode($payload, 'secret', 'HS256');

// Validate on decode
$decoded = JWT::decode($jwt, new Key('secret', 'HS256'));
if (!in_array('read', $decoded->scope)) {
    abort(403, 'Insufficient permissions');
}

4. Asymmetric Signing (RS256/ES256)

Use private/public key pairs for server-to-server auth:

// Encode with private key
$privateKey = file_get_contents('private.pem');
$jwt = JWT::encode($payload, $privateKey, 'RS256');

// Decode with public key
$publicKey = file_get_contents('public.pem');
$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));

5. Passphrase-Protected Keys

Handle encrypted private keys (e.g., RSA with passphrase):

$passphrase = config('jwt.passphrase');
$privateKey = openssl_pkey_get_private(
    file_get_contents('private_key.pem'),
    $passphrase
);
$jwt = JWT::encode($payload, $privateKey, 'RS256');

Integration Tips

Laravel-Specific Patterns

  1. Store Keys in Config:

    // config/jwt.php
    return [
        'secret' => env('JWT_SECRET'),
        'algorithms' => ['HS256', 'RS256'],
        'leeway' => 60,
    ];
    

    Access via config('jwt.secret').

  2. Service Provider: Bind the JWT decoder as a singleton:

    public function register()
    {
        $this->app->singleton('jwt', function () {
            return new \Firebase\JWT\JWT();
        });
    }
    
  3. Testing: Mock JWT decoding in tests:

    $mockJWT = Mockery::mock('Firebase\JWT\JWT');
    $mockJWT->shouldReceive('decode')
            ->once()
            ->andReturn((object) ['user_id' => 123]);
    $this->app->instance('jwt', $mockJWT);
    

Performance

  • Cache JWKS: Use CachedKeySet to avoid repeated HTTP requests to key endpoints.
  • Leeway: Set JWT::$leeway to account for clock skew (e.g., 60 seconds).
  • Algorithm Choice: Prefer symmetric (HS256) for performance if security allows; use asymmetric (RS256) for server-to-server.

Gotchas and Tips

Pitfalls

  1. Algorithm Mismatch:

    • Issue: Using HS256 with an RSA key or vice versa throws UnexpectedValueException.
    • Fix: Ensure the key type matches the algorithm (e.g., HS256 → secret key, RS256 → RSA key).
  2. Key Length:

    • Issue: Keys shorter than 32 bytes for HS256 or invalid RSA keys cause DomainException.
    • Fix: Use a 64-character random string for HS256 or generate valid RSA keys:
      openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048
      openssl rsa -pubout -in private.pem -out public.pem
      
  3. Libsodium Dependencies:

    • Issue: EdDSA fails if libsodium is missing, even with paragonie/sodium_compat.
    • Fix: Verify sodium_crypto_sign_keypair() is available:
      if (!function_exists('sodium_crypto_sign_keypair')) {
          throw new \RuntimeException('libsodium extension required for EdDSA');
      }
      
  4. Clock Skew:

    • Issue: Tokens expire prematurely due to server time differences.
    • Fix: Set JWT::$leeway to a small value (e.g., 60 seconds) to account for skew:
      JWT::$leeway = 60;
      
  5. JWKS Caching:

    • Issue: CachedKeySet may not refresh keys during rotation.
    • Fix: Set $expiresAfter to a low value (e.g., 300 seconds) and enable $rateLimit:
      $keySet = new CachedKeySet($jwksUri, $httpClient, $httpFactory, $cache, 300, true);
      
  6. Passphrase Handling:

    • Issue: Forgetting the passphrase for encrypted private keys causes openssl_pkey_get_private() to return false.
    • Fix: Store passphrases securely (e.g., environment variables or Laravel Vault) and validate:
      $privateKey = openssl_pkey_get_private($keyFile, $passphrase);
      if (!$privateKey) {
          throw new \RuntimeException('Invalid passphrase');
      }
      
  7. Custom Headers:

    • Issue: Manually decoding headers (e.g., x-forwarded-for) is insecure.
    • Fix: Avoid this unless absolutely necessary. Use standard JWT claims instead.

Debugging Tips

  1. Validate JWT Structure: Split the JWT to inspect parts:
    list($headerB
    
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.
codraw/entity-migrator
codraw/doctrine-extra
codraw/aws-tool-kit
codraw/validator
codraw/workflow
codraw/open-api
codraw/cron-job
codraw/process
codraw/log
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony