Weave 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

Jwt Bundle Laravel Package

abotteram/jwt-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require abotteram/jwt-bundle
    

    Register the bundle in config/bundles.php (Symfony):

    return [
        // ...
        Abotteram\JwtBundle\AbotteramJwtBundle::class => ['all' => true],
    ];
    
  2. Configuration Publish the default config:

    php bin/console abotteram:jwt:install
    

    Edit config/packages/abotteram_jwt.yaml:

    abotteram_jwt:
        secret_key: '%env(JWT_SECRET_KEY)%'  # Set in .env
        algorithm: 'HS256'
        expiration_time: 3600  # 1 hour
    
  3. First Use Case: Generating a Token Inject the JwtService and generate a token:

    use Abotteram\JwtBundle\Service\JwtService;
    
    class AuthController extends AbstractController
    {
        public function login(JwtService $jwtService): JsonResponse
        {
            $user = $this->getUser(); // Assume user is authenticated
            $token = $jwtService->generateToken(['id' => $user->id]);
    
            return $this->json(['token' => $token]);
        }
    }
    
  4. First Use Case: Validating a Token Use the JwtListener or manually validate:

    use Abotteram\JwtBundle\Service\JwtService;
    
    public function protectedRoute(JwtService $jwtService, Request $request): JsonResponse
    {
        $token = $request->headers->get('Authorization');
        if (!$jwtService->validateToken($token)) {
            return $this->json(['error' => 'Unauthorized'], 401);
        }
    
        $data = $jwtService->decodeToken($token);
        return $this->json(['data' => $data]);
    }
    

Implementation Patterns

Common Workflows

1. Token Generation

  • Dynamic Claims: Pass an associative array to generateToken() for custom claims:
    $token = $jwtService->generateToken([
        'id' => $user->id,
        'roles' => $user->roles,
        'exp' => time() + 3600, // Override expiration
    ]);
    
  • Refresh Tokens: Generate a short-lived access token + long-lived refresh token:
    $accessToken = $jwtService->generateToken(['type' => 'access'], 3600);
    $refreshToken = $jwtService->generateToken(['type' => 'refresh'], 86400);
    

2. Token Validation & Decoding

  • Automatic Validation: Use the JwtListener to auto-validate incoming requests (configure in config/packages/abotteram_jwt.yaml):
    abotteram_jwt:
        listener:
            enabled: true
            protected_paths: ['^/api/protected']
    
  • Manual Validation: Decode and validate tokens in controllers:
    $decoded = $jwtService->decodeToken($token);
    if ($jwtService->isTokenExpired($decoded)) {
        throw new \RuntimeException('Token expired');
    }
    

3. Integration with Symfony Security

  • Guard Authenticator: Create a custom authenticator:
    use Abotteram\JwtBundle\Service\JwtService;
    
    class JwtAuthenticator extends AbstractGuardAuthenticator
    {
        public function supports(Request $request): bool
        {
            return $request->headers->has('Authorization');
        }
    
        public function getCredentials(Request $request)
        {
            return $request->headers->get('Authorization');
        }
    
        public function getUser($credentials, UserProviderInterface $userProvider)
        {
            $jwtService = $this->container->get(JwtService::class);
            $data = $jwtService->decodeToken($credentials);
            return $userProvider->loadUserByIdentifier($data['id']);
        }
    }
    

4. Token Storage

  • Database Storage: Store tokens in a tokens table and validate against it:
    // Example: Check if token exists in DB before validating
    $token = $request->headers->get('Authorization');
    $isValid = $jwtService->validateToken($token) && TokenRepository::exists($token);
    

Integration Tips

1. Environment Variables

  • Use .env for sensitive keys:
    JWT_SECRET_KEY=your-256-bit-secret
    JWT_ALGORITHM=HS256
    
  • Override config per environment (e.g., config/packages/abotteram_jwt_dev.yaml).

2. Custom Claims

  • Extend the JwtService to add custom logic:
    class CustomJwtService extends JwtService
    {
        public function generateUserToken(User $user): string
        {
            return $this->generateToken([
                'id' => $user->id,
                'username' => $user->username,
                'custom_claim' => $this->generateCustomClaim($user),
            ]);
        }
    }
    

3. Rate Limiting

  • Combine with Symfony’s RateLimiter to prevent brute-force attacks:
    # config/packages/security.yaml
    firewalls:
        main:
            rate_limiter: auth_rate_limiter
    

4. Testing

  • Mock JwtService in PHPUnit:
    $mockJwt = $this->createMock(JwtService::class);
    $mockJwt->method('validateToken')->willReturn(true);
    $mockJwt->method('decodeToken')->willReturn(['id' => 1]);
    $this->container->set(JwtService::class, $mockJwt);
    

Gotchas and Tips

Pitfalls

1. Secret Key Management

  • Gotcha: Hardcoding secret_key in config (even in dev) leaks security. Fix: Always use %env(JWT_SECRET_KEY)% and ensure .env is in .gitignore.
  • Tip: Rotate keys periodically and invalidate old tokens.

2. Algorithm Mismatch

  • Gotcha: Using HS256 without a strong secret key or RS256 without a valid keypair. Fix: For RS256, generate keys with:
    openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048
    openssl pkey -in private.pem -pubout -out public.pem
    
    Configure in abotteram_jwt.yaml:
    algorithm: 'RS256'
    private_key_path: '%kernel.project_dir%/config/jwt/private.pem'
    public_key_path: '%kernel.project_dir%/config/jwt/public.pem'
    

3. Token Expiration

  • Gotcha: Forgetting to set expiration_time or relying solely on exp claim. Fix: Default to a short TTL (e.g., 1 hour) and use refresh tokens for longer sessions.

4. Listener Conflicts

  • Gotcha: JwtListener blocking all routes or throwing errors due to missing headers. Fix: Exclude public paths and validate headers:
    abotteram_jwt:
        listener:
            enabled: true
            protected_paths: ['^/api']
            header_name: 'X-AUTH-TOKEN'  # Custom header
    

5. Clock Skew

  • Gotcha: Token validation fails due to server clock drift. Fix: Use a time server (e.g., NTP) or add a leeway buffer:
    $jwtService->setLeeway(30); // Allow 30-second clock skew
    

Debugging Tips

1. Token Decoding

  • Decode tokens manually to inspect claims:
    $decoded = $jwtService->decodeToken($token, false); // Skip validation
    var_dump($decoded);
    
  • Use online tools like jwt.io to verify tokens.

2. Listener Debugging

  • Disable the listener temporarily to isolate issues:
    abotteram_jwt:
        listener:
            enabled: false
    
  • Check Symfony’s profiler for JwtListener events.

3. Logging

  • Enable debug logging in config/packages/abotteram_jwt.yaml:
    abotteram_jwt:
        debug: true
    
  • Log token generation/validation:
    $jwtService->setLogger($this->container->get('logger'));
    

Extension

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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log