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 8+ library for JWT/JWS/JWE and JWK/COSE keys. Supports HS/RSA/ECDSA/EdDSA signatures, key management (RSA-OAEP, AES-KW, PBES2, ECDH-ES/X25519) and AES-GCM/CBC-HS encryption.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require kelvinmo/simplejwt
    

    Ensure PHP 8.0+ with gmp, hash, openssl, and sodium extensions enabled.

  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 the JWT:

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

Where to Look First

  • Key Management: Start with KeySet and key types (SymmetricKey, RSAKey, etc.) in SimpleJWT/Keys.
  • JWT Creation/Verification: Focus on \SimpleJWT\JWT class methods (encode, decode).
  • Documentation: Check the README for algorithm support and examples.

Implementation Patterns

Workflows

1. Token Generation Workflow

  • HMAC (Symmetric) Tokens:
    $keySet = KeySet::createFromSecret(env('JWT_SECRET'));
    $jwt = new \SimpleJWT\JWT(['alg' => 'HS256'], [
        'iss' => 'your-app',
        'exp' => time() + 3600,
        'user_id' => 123
    ]);
    $token = $jwt->encode($keySet);
    
  • RSA/ECDSA Tokens: Load a private key from a PEM file:
    $keySet = new KeySet();
    $privateKey = new \SimpleJWT\Keys\RSAKey(file_get_contents('private.pem'), 'pem');
    $keySet->add($privateKey);
    $jwt = new \SimpleJWT\JWT(['alg' => 'RS256'], ['sub' => 'user123']);
    $token = $jwt->encode($keySet);
    

2. Token Verification Workflow

  • Single Key Verification:
    $publicKeySet = new KeySet();
    $publicKey = new \SimpleJWT\Keys\RSAKey(file_get_contents('public.pem'), 'pem');
    $publicKeySet->add($publicKey);
    $decoded = \SimpleJWT\JWT::decode($token, $publicKeySet, 'RS256');
    
  • Key Rotation: Use KeySet to manage multiple keys (e.g., for rolling keys):
    $keySet = new KeySet();
    $keySet->load(file_get_contents('keys.json')); // Load JWK Set
    $decoded = \SimpleJWT\JWT::decode($token, $keySet, 'RS256');
    

3. JWE (Encrypted Tokens)

  • Encryption:
    $keySet = KeySet::createFromSecret('encryption-secret');
    $jwe = new \SimpleJWT\JWE(['alg' => 'PBES2-HS256+A128KW', 'enc' => 'A128CBC-HS256'], 'sensitive-data');
    $encrypted = $jwe->encrypt($keySet);
    
  • Decryption:
    $decrypted = \SimpleJWT\JWE::decrypt($encrypted, $keySet, 'PBES2-HS256+A128KW');
    

4. Custom Claims and Headers

  • Add custom claims/headers during token creation:
    $jwt = new \SimpleJWT\JWT([
        'alg' => 'HS256',
        'custom_header' => 'value'
    ], [
        'sub' => 'user123',
        'custom_claim' => 'data'
    ]);
    

5. Middleware Integration (Laravel)

  • Create a middleware to verify tokens on protected routes:
    use SimpleJWT\JWT;
    use SimpleJWT\Keys\KeySet;
    
    class VerifyJWTMiddleware
    {
        public function handle($request, Closure $next)
        {
            $token = $request->bearerToken();
            $keySet = new KeySet();
            $keySet->load(file_get_contents(storage_path('keys/jwks.json')));
    
            try {
                $decoded = JWT::decode($token, $keySet, 'RS256');
                $request->merge(['user' => $decoded->getClaims()]);
            } catch (\SimpleJWT\InvalidTokenException $e) {
                abort(401, 'Invalid token');
            }
    
            return $next($request);
        }
    }
    

Integration Tips

  1. Key Management:

    • Store keys in environment variables or encrypted storage (e.g., Laravel Vault).
    • Use KeySet::load() to load JWK Sets from JSON files for key rotation.
  2. Algorithm Selection:

    • Prefer asymmetric algorithms (RS256, ES256) for production over symmetric (HS256) for better security.
    • Use EdDSA (Ed25519) for lightweight, secure signatures.
  3. Token Storage:

    • Store tokens in HTTP-only, Secure cookies or Authorization: Bearer headers.
    • Avoid storing sensitive claims in JWTs; use references (e.g., user_id) and fetch data from the database.
  4. Performance:

    • Cache KeySet instances if keys rarely change.
    • For high-throughput systems, benchmark algorithms (e.g., RS256 vs. ES256).
  5. Testing:

    • Use JWT::deserialise() for unit tests to avoid key dependencies:
      $result = JWT::deserialise($token);
      $this->assertEquals('user123', $result['claims']['sub']);
      

Gotchas and Tips

Pitfalls

  1. Algorithm Mismatch:

    • Always verify the alg header matches the key type (e.g., HS256 for symmetric keys, RS256 for RSA).
    • Fix: Use JWT::decode($token, $keySet, 'expected_alg') to enforce validation.
  2. Key ID (kid) Issues:

    • If kid is missing or mismatched, tokens may fail verification.
    • Fix: Ensure keys have unique kid values:
      $key = new \SimpleJWT\Keys\RSAKey($pem, 'pem');
      $key->setKeyId('my-key-id'); // Explicitly set kid
      
  3. Clock Skew:

    • Tokens with exp or nbf claims may fail if server clocks are unsynchronized.
    • Fix: Configure a small leeway (e.g., 5 minutes) in your validation logic:
      $decoded = JWT::decode($token, $keySet, 'HS256', 300); // 5-minute leeway
      
  4. PEM File Parsing:

    • PEM files must contain only the key (no X.509 certificates or headers).
    • Fix: Use openssl rsa -in key.pem -outform PEM to extract raw keys.
  5. PHP Extensions:

    • Missing sodium or gmp extensions will break EdDSA/X25519 or RSA operations.
    • Fix: Install extensions or fall back to alternative algorithms (e.g., ES256 instead of EdDSA).
  6. Token Tampering:

    • Never trust deserialise() results without verification. Always use decode() in production.
  7. Key Rotation:

    • Old keys must remain valid until new tokens expire. Use KeySet to manage multiple keys:
      $keySet->add($oldKey);
      $keySet->add($newKey);
      

Debugging Tips

  1. InvalidTokenException:

    • Check the error code (e.g., SIGNATURE_VERIFICATION_ERROR, TOKEN_EXPIRED).
    • Use try-catch to log detailed errors:
      try {
          $decoded = JWT::decode($token, $keySet, 'HS256');
      } catch (\SimpleJWT\InvalidTokenException $e) {
          \Log::error('JWT Error: ' . $e->getMessage() . ' (Code: ' . $e->getErrorCode() . ')');
      }
      
  2. Algorithm Validation:

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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope