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

Jwt Authentication Bundle Laravel Package

lexik/jwt-authentication-bundle

JWT authentication bundle for Symfony APIs. Issues and validates JSON Web Tokens, supports PHP 8.2+ and Symfony 6.4–8, and offers extensive docs for setup, configuration, customization, testing, CORS, and programmatic token creation.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require lexik/jwt-authentication-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true],
    ];
    
  2. Configure config/packages/lexik_jwt_authentication.yaml

    lexik_jwt_authentication:
        secret_key: '%env(JWT_SECRET_KEY)%' # Generate with `openssl rand -hex 32`
        public_key: '%env(JWT_PUBLIC_KEY)%' # Optional for asymmetric encryption
        pass_phrase: '%env(JWT_PASSPHRASE)%' # Optional
        token_ttl: 3600 # Token lifetime in seconds
    
  3. First Use Case: Secure an API Endpoint Add the is_granted('IS_AUTHENTICATED_FULLY') voter to your controller:

    use Symfony\Component\Security\Http\Attribute\IsGranted;
    
    #[IsGranted('IS_AUTHENTICATED_FULLY')]
    public function secureEndpoint(): JsonResponse
    {
        return new JsonResponse(['message' => 'Access granted']);
    }
    
  4. Generate a Token Use the /api/login_check endpoint (configured in security.yaml):

    security:
        firewalls:
            api:
                pattern: ^/api
                stateless: true
                jwt: ~
    

    Send a POST request with credentials to /api/login_check to receive a JWT.


Implementation Patterns

Workflows

  1. Token-Based Authentication Flow

    • Login: POST to /login_check with username/password.
    • Subsequent Requests: Include the JWT in the Authorization: Bearer <token> header.
    • Logout: Invalidate the token via JWTInvalidationManager (requires token storage).
  2. Custom User Provider Extend Lexik\Bundle\JWTAuthenticationBundle\Services\JWTUserProvider:

    use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTUserProviderInterface;
    
    class CustomUserProvider implements JWTUserProviderInterface
    {
        public function loadUserByIdentifier(string $identifier): UserInterface
        {
            // Custom logic to fetch user (e.g., from API, DB, or cache)
            return $this->userRepository->findOneBy(['email' => $identifier]);
        }
    }
    

    Register as a service:

    lexik_jwt_authentication.user_provider: App\Security\CustomUserProvider
    
  3. Token Creation Programmatically Use JWTManager to generate tokens:

    use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
    
    public function __construct(private JWTTokenManagerInterface $jwtManager) {}
    
    public function generateToken(UserInterface $user): string
    {
        return $this->jwtManager->create($user);
    }
    
  4. Event-Driven Customization Listen to JWT events (e.g., JWTEncodedEvent, JWTAuthenticatedEvent):

    use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTEncodedEvent;
    
    public function onJWTEncoded(JWTEncodedEvent $event): void
    {
        $data = $event->getData();
        $data['custom_claim'] = 'value'; // Add custom claims
        $event->setData($data);
    }
    

    Register the subscriber:

    services:
        App\EventListener\JWTSubscriber:
            tags: ['kernel.event_subscriber']
    
  5. Token Extraction from Cookies Configure cookie-based auth in lexik_jwt_authentication.yaml:

    lexik_jwt_authentication:
        cookie:
            enabled: true
            name: jwt_token
            path: /
            domain: ~
            secure: auto
            http_only: true
            same_site: lax
    

Integration Tips

  1. Symfony Security Integration Use JWTTokenAuthenticator in your firewall:

    security:
        firewalls:
            api:
                pattern: ^/api
                stateless: true
                provider: app_user_provider
                jwt: ~
    
  2. API Platform Integration Add #[IsGranted('ROLE_USER')] to API resources:

    use Symfony\Component\Security\Http\Attribute\IsGranted;
    
    #[IsGranted('ROLE_USER')]
    #[ApiResource]
    class User {}
    
  3. Testing Tokens Use JWTTokenManager in tests:

    use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
    
    public function testAuthenticatedRequest(Client $client, JWTTokenManagerInterface $jwtManager)
    {
        $user = $this->createMock(UserInterface::class);
        $token = $jwtManager->create($user);
    
        $client->request('GET', '/api/endpoint', [], [], [
            'HTTP_Authorization' => 'Bearer ' . $token,
        ]);
    }
    
  4. Token Invalidation Store tokens in a database (e.g., jwt_tokens table) and invalidate on logout:

    use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
    
    public function logout(JWTTokenManagerInterface $jwtManager, Request $request)
    {
        $token = $request->headers->get('Authorization', '');
        if (preg_match('/Bearer\s(\S+)/', $token, $matches)) {
            $jwtManager->invalidate($matches[1]);
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Key Management

    • Issue: Hardcoding keys in config or version control.
    • Fix: Use environment variables (%env(JWT_SECRET_KEY)%) and rotate keys periodically.
    • Tip: Use openssl genrsa -out private.pem 4096 and openssl rsa -pubout -in private.pem -out public.pem for asymmetric keys.
  2. Token Expiration

    • Issue: Forgetting to set token_ttl or using 0 (infinite lifetime).
    • Fix: Configure a reasonable TTL (e.g., 3600 for 1 hour) and implement refresh tokens for long sessions.
  3. Stateless vs. Stateful

    • Issue: Assuming stateless auth means no token storage.
    • Fix: If invalidating tokens, store them in a database or Redis (e.g., lexik_jwt_authentication.token_storage).
    • Tip: Use JWTInvalidationManager for manual invalidation.
  4. CORS Headers

    • Issue: Missing WWW-Authenticate header in 401 responses.
    • Fix: Configure CORS in lexik_jwt_authentication.yaml:
      lexik_jwt_authentication:
          cors_origin: ['http://localhost:3000']
      
    • Tip: Use WWW-Authenticate: Bearer for OAuth2 compliance.
  5. Event Propagation

    • Issue: Events not firing due to incorrect subscriber registration.
    • Fix: Ensure subscribers are tagged as kernel.event_subscriber and events are dispatched in the correct order.
  6. Cookie Security

    • Issue: Cookies not marked as Secure or HttpOnly.
    • Fix: Configure cookie settings:
      lexik_jwt_authentication:
          cookie:
              secure: true
              http_only: true
              same_site: strict
      

Debugging

  1. Token Decoding Errors

    • Symptom: JWTException with "Invalid token signature".
    • Debug:
      • Verify secret_key/public_key in config.
      • Check key formats (PEM for asymmetric, raw for symmetric).
      • Ensure pass_phrase matches if used.
    • Fix: Regenerate keys and update config.
  2. Authentication Failures

    • Symptom: 401 without clear error message.
    • Debug:
      • Check AuthenticationFailureHandler for custom responses.
      • Enable debug mode to see full exceptions.
      • Verify user_provider is correctly implemented.
    • Fix: Override AuthenticationFailureHandler:
      use Lexik\Bundle\JWTAuthenticationBundle\Exception\AuthenticationFailureHandler;
      
      class CustomFailureHandler extends AuthenticationFailureHandler
      {
          public function createFailureResponse(Request $request): Response
          {
              return new JsonResponse(['error' => 'Invalid credentials'], 401);
          }
      }
      
      Register in security.yaml:
      security:
          firewalls:
              api:
                  jwt: ~
                  authentication_failure_handler: App\Security\CustomFailureHandler
      
  3. Performance Issues

    • Symptom: Slow token validation.
    • Debug:
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui