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

Simplejwt Laravel Package

kelvinmo/simplejwt

SimpleJWT is a PHP 8+ library for creating, signing, verifying, and encrypting JSON Web Tokens (JWT/JWS/JWE). Supports JWK/COSE keys, HMAC/RSA/ECDSA/EdDSA, key management (RSA-OAEP, ECDH-ES, PBES2), and AES-GCM/CBC-HS encryption.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require kelvinmo/simplejwt
    

    Ensure your composer.json includes PHP 8.0+ and extensions: gmp, hash, openssl, and sodium (for EdDSA/X25519).

  2. First Use Case: Generate a JWT for API authentication:

    use SimpleJWT\Keys\KeySet;
    use SimpleJWT\JWT;
    
    $keySet = KeySet::createFromSecret('your-secret-key');
    $headers = ['alg' => 'HS256', 'typ' => 'JWT'];
    $claims = ['sub' => 'user123', 'exp' => time() + 3600];
    $jwt = new JWT($headers, $claims);
    $token = $jwt->encode($keySet);
    
  3. Where to Look First:

    • README.md for core workflows.
    • SimpleJWT\Keys\KeySet for key management.
    • SimpleJWT\JWT and SimpleJWT\JWE for token operations.

Implementation Patterns

Key Management Workflows

  1. HMAC Secrets:

    $keySet = KeySet::createFromSecret('secret-key');
    

    Use for stateless APIs (e.g., API gateways).

  2. Asymmetric Keys (RSA/ECDSA):

    $privateKey = new \SimpleJWT\Keys\RSAKey(file_get_contents('private.pem'), 'pem');
    $publicKey = new \SimpleJWT\Keys\RSAKey(file_get_contents('public.pem'), 'pem');
    $keySet->add($privateKey, true); // Auto-generate kid
    $keySet->add($publicKey);
    

    Ideal for server-to-server or user authentication with public/private pairs.

  3. Key Rotation:

    $keySet->add($newPrivateKey, true); // Add new key with kid
    $keySet->remove($oldPrivateKey);   // Remove old key
    

    Store keys in environment variables or a secrets manager (e.g., AWS Secrets Manager).

Token Creation & Validation

  1. JWT Creation:

    $jwt = new JWT(['alg' => 'RS256'], ['sub' => 'user123', 'iat' => time()]);
    $token = $jwt->encode($keySet);
    
    • Use HS256 for simplicity, RS256/ES256 for security.
    • Disable auto-kid/iat with $jwt->encode($keySet, false).
  2. JWT Validation:

    try {
        $decoded = JWT::decode($token, $keySet, 'RS256');
        $claims = $decoded->getClaims();
    } catch (\SimpleJWT\InvalidTokenException $e) {
        // Handle invalid token (expired, tampered, etc.)
    }
    
    • Always validate alg against a whitelist (e.g., ['HS256', 'RS256']).
    • Use JWT::deserialise() for debugging (no validation).
  3. JWE (Encrypted Tokens):

    $jwe = new \SimpleJWT\JWE(['alg' => 'PBES2-HS256+A128KW', 'enc' => 'A128CBC-HS256'], 'secret-payload');
    $encrypted = $jwe->encrypt($keySet);
    $decrypted = \SimpleJWT\JWE::decrypt($encrypted, $keySet, 'PBES2-HS256+A128KW');
    

    Use for confidential claims (e.g., PII in tokens).

Integration with Laravel

  1. Middleware for JWT Validation:

    use SimpleJWT\JWT;
    
    class AuthenticateJWT
    {
        public function handle($request, Closure $next)
        {
            $token = $request->bearerToken();
            if (!$token) abort(401);
    
            try {
                $decoded = JWT::decode($token, $this->keySet, 'HS256');
                $request->merge(['user' => $decoded->getClaims()]);
            } catch (\Exception $e) {
                abort(401);
            }
            return $next($request);
        }
    }
    
  2. Service Provider for Key Management:

    class JWTServiceProvider extends ServiceProvider
    {
        public function register()
        {
            $this->app->singleton('jwt.keySet', function () {
                return KeySet::createFromSecret(config('jwt.secret'));
            });
        }
    }
    
  3. API Resource Responses:

    return response()->json([
        'data' => $user,
        'access_token' => (new JWT(['alg' => 'HS256'], [
            'sub' => $user->id,
            'exp' => time() + 3600
        ])->encode($this->keySet)),
    ]);
    

Gotchas and Tips

Pitfalls

  1. Algorithm Mismatch:

    • Issue: InvalidTokenException with SIGNATURE_VERIFICATION_ERROR.
    • Fix: Ensure the alg in the token matches the one passed to decode(). Example: JWT::decode($token, $keySet, 'HS256') must match the token’s alg.
  2. Key ID (kid) Handling:

    • Issue: Tokens fail validation if kid is missing or mismatched.
    • Fix: Always include kid in keys or use KeySet::add($key, true) to auto-generate it.
    • Debug: Check SimpleJWT\Keys\Key::getKeyId() to verify kid values.
  3. Clock Skew:

    • Issue: Tokens expire prematurely due to server time differences.
    • Fix: Use nbf (Not Before) claims and adjust server time or add a leeway buffer:
      $claims['exp'] = time() + 3600;
      $claims['nbf'] = time() - 60; // Allow 1-minute leeway
      
  4. PEM vs. JWK:

    • Issue: RSAKey fails to load from PEM files.
    • Fix: Ensure PEM files contain only the key (no X.509 certificates). Use:
      $key = new \SimpleJWT\Keys\RSAKey(file_get_contents('private.pem'), 'pem');
      
  5. PHP Extensions:

    • Issue: SodiumException or RuntimeException during EdDSA/X25519 operations.
    • Fix: Enable the sodium extension in php.ini or Dockerfile:
      extension=sodium
      

Debugging Tips

  1. Deserialize Without Validation:

    $result = JWT::deserialise($token);
    print_r($result['claims']); // Inspect claims
    print_r($result['signatures']); // Inspect signatures
    
  2. Key Validation:

    try {
        $keySet->validateKey($token, 'HS256');
    } catch (\SimpleJWT\KeyException $e) {
        // Key is invalid or unsupported
    }
    
  3. Algorithm Support:

    • Check supported algorithms in SimpleJWT\Algorithms.
    • Example: PBES2-HS256+A128KW requires openssl and gmp.

Performance Tips

  1. KeySet Caching:

    $keySet = Cache::remember('jwt.keys', 3600, function () {
        return KeySet::createFromSecret(config('jwt.secret'));
    });
    
  2. Avoid Re-encoding:

    • Reuse JWT objects for multiple encodes if claims/headers are static.
  3. JWE Optimization:

    • Prefer symmetric algorithms (e.g., A256GCM) for performance-critical paths.

Extension Points

  1. Custom Claims Validation:

    $decoded = JWT::decode($token, $keySet, 'HS256');
    if (!$decoded->getClaim('role') === 'admin') {
        abort(403);
    }
    
  2. Multi-Recipient JWE:

    $jwe = new \SimpleJWT\JWE(['alg' => 'ECDH-ES+A128KW', 'enc' => 'A128GCM'], 'secret');
    $encrypted = $jwe->encrypt($key
    
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.
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
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata