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 lightweight PHP library for creating, signing, verifying, and encrypting JSON Web Tokens (JWT/JWS/JWE). Supports JWK/COSE keys, HMAC/RSA/ECDSA/EdDSA algorithms, and common key management and AES encryption methods.

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 with HMAC-SHA256 (HS256) using a secret:

    use SimpleJWT\Keys\KeySet;
    
    $keySet = KeySet::createFromSecret('your-secret-key');
    $jwt = new \SimpleJWT\JWT(['alg' => 'HS256'], ['sub' => 'user123']);
    $token = $jwt->encode($keySet);
    
  3. Verify a Token:

    $decoded = \SimpleJWT\JWT::decode($token, $keySet, 'HS256');
    $claims = $decoded->getClaims();
    

Where to Look First

  • Key Management: Focus on KeySet for loading keys (PEM, JWK, or secrets).
  • Core Classes: JWT and JWE for signing/verifying and encrypting/decrypting.
  • Algorithms: Check src/Crypt for supported algorithms (e.g., HS256, RS256, A128GCM).

Implementation Patterns

Workflows

  1. API Authentication:

    • Sign Tokens: Use JWT with asymmetric keys (e.g., RS256) for stateless auth.
      $keySet = new KeySet();
      $keySet->add(new \SimpleJWT\Keys\RSAKey(file_get_contents('private.pem'), 'pem'));
      $jwt = new \SimpleJWT\JWT(['alg' => 'RS256'], ['user_id' => 1]);
      $token = $jwt->encode($keySet);
      
    • Validate Tokens: Middleware to decode/verify tokens:
      $decoded = \SimpleJWT\JWT::decode($request->bearerToken(), $publicKeySet, 'RS256');
      
  2. Secure Data Exchange:

    • Encrypt with JWE: Use JWE for confidential payloads (e.g., A256GCM).
      $jwe = new \SimpleJWT\JWE(['alg' => 'PBES2-HS256+A128KW', 'enc' => 'A128GCM'], 'sensitive-data');
      $encrypted = $jwe->encrypt($keySet);
      
    • Decrypt: Use recipient-specific keys:
      $decrypted = \SimpleJWT\JWE::decrypt($encrypted, $recipientKeySet, 'PBES2-HS256+A128KW');
      
  3. Key Rotation:

    • Load multiple keys into a KeySet and let the library auto-select the correct one via kid header.
    • Example: Rotate RSA keys by adding new keys with unique kid values.

Integration Tips

  • Laravel Middleware:
    public function handle($request, Closure $next) {
        $token = $request->bearerToken();
        $keySet = KeySet::createFromSecret(config('jwt.secret'));
        $decoded = \SimpleJWT\JWT::decode($token, $keySet, 'HS256');
        auth()->setUser($decoded->getClaims()['user_id']);
        return $next($request);
    }
    
  • Environment Config: Store keys in .env and load them dynamically:
    $keySet = new KeySet();
    $keySet->add(new \SimpleJWT\Keys\RSAKey(env('JWT_PRIVATE_KEY'), 'pem'));
    
  • Error Handling: Catch SimpleJWT\InvalidTokenException for malformed/expired tokens and return 401 responses.

Gotchas and Tips

Pitfalls

  1. Key Format Mismatches:

    • Issue: PEM files must contain raw keys only (no X.509 certificates). Using a certificate will throw KeyException.
    • Fix: Strip headers/footers from PEM files or use openssl to extract the key:
      openssl rsa -in cert.pem -out private.pem
      
  2. Algorithm Mismatches:

    • Issue: Decoding a token signed with RS256 using HS256 will fail silently (or throw InvalidTokenException).
    • Fix: Always verify the alg header matches the key type:
      $alg = $decoded->getHeader('alg');
      if ($alg !== 'RS256') throw new \RuntimeException('Invalid algorithm');
      
  3. Key ID (kid) Handling:

    • Issue: Missing kid headers can cause key selection failures in rotated key sets.
    • Fix: Explicitly set kid when adding keys:
      $key = new \SimpleJWT\Keys\RSAKey($pemKey, 'pem');
      $key->setKeyId('key-1'); // Assign a unique ID
      $keySet->add($key);
      
  4. PHP Extensions:

    • Issue: Missing sodium or gmp extensions will break EdDSA/X25519 algorithms.
    • Fix: Enable extensions in php.ini or use Docker with pre-configured images.

Debugging Tips

  • Deserialize First: Use JWT::deserialise() to inspect tokens without verification:
    $result = \SimpleJWT\JWT::deserialise($token);
    dump($result['claims']); // Check claims before verifying
    
  • Key Validation: Validate keys before use:
    try {
        $key = new \SimpleJWT\Keys\RSAKey($pemKey, 'pem');
        $key->validate(); // Throws KeyException if invalid
    } catch (\SimpleJWT\KeyException $e) {
        // Handle invalid key
    }
    
  • Algorithm Support: Check supported algorithms in src/Crypt to avoid unsupported combos (e.g., A128GCM requires sodium).

Extension Points

  1. Custom Claims: Extend JWT to add domain-specific claims:

    class CustomJWT extends \SimpleJWT\JWT {
        public function __construct(array $headers, array $claims) {
            $claims['custom_claim'] = 'value';
            parent::__construct($headers, $claims);
        }
    }
    
  2. Key Management: Integrate with Laravel’s Hash or Crypt facades for key storage:

    $keySet = new KeySet();
    $keySet->add(new \SimpleJWT\Keys\SymmetricKey(
        Hash::make('secret'),
        'bin'
    ));
    
  3. Multi-Tenancy: Use kid headers to route tokens to tenant-specific key sets:

    $kid = $decoded->getHeader('kid');
    $tenantKeySet = $this->getKeySetForTenant($kid);
    
  4. Logging: Wrap decode() calls to log token validation attempts:

    try {
        $decoded = \SimpleJWT\JWT::decode($token, $keySet, 'HS256');
    } catch (\SimpleJWT\InvalidTokenException $e) {
        \Log::warning("Token validation failed: {$e->getMessage()}");
        throw $e;
    }
    

Config Quirks

  • Auto-Completion: Disable automatic iat/kid insertion by passing false to encode():
    $jwt->encode($keySet, false); // Skip auto-claims/headers
    
  • JWK Thumbnails: Generate RFC7517-compliant kid values:
    $key->getKeyId(true); // Force RFC7517 thumbnail
    
  • Base64URL Encoding: The library uses strict Base64URL encoding (no padding). Avoid manual base64_encode() calls—use Util::base64url_encode().
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