Installation
composer require dimkinthepro/jwt-auth-bundle
Add to config/bundles.php (Symfony):
return [
// ...
DimkinThePro\JwtAuthBundle\DimkinTheProJwtAuthBundle::class => ['all' => true],
];
Configuration Publish the default config:
php bin/console dimkin-the-pro:jwt-auth:install
Edit config/packages/dimkin_the_pro_jwt_auth.yaml:
dimkin_the_pro_jwt_auth:
secret_key: '%env(JWT_SECRET_KEY)%' # Generate via `openssl rand -hex 32`
expiration_time: 3600 # 1 hour in seconds
First Use Case Generate a token in a controller:
use DimkinThePro\JwtAuthBundle\Service\JwtService;
class AuthController extends AbstractController {
public function login(JwtService $jwtService, UserRepository $userRepo) {
$user = $userRepo->findOneBy(['email' => 'user@example.com']);
$token = $jwtService->generateToken($user);
return $this->json(['token' => $token]);
}
}
Protect Routes
Add to security.yaml:
firewalls:
api:
pattern: ^/api
jwt: ~
$token = $jwtService->generateToken($user, ['role' => 'admin']); // Custom claims
$jwtService->validateToken($request->headers->get('Authorization'));
Extend token payload dynamically:
$token = $jwtService->generateToken($user, [
'custom_claim' => 'value',
'exp' => time() + 86400, // Override expiration
]);
Implement a refresh endpoint:
public function refresh(JwtService $jwtService, Request $request) {
$refreshToken = $request->get('refresh_token');
$newToken = $jwtService->refreshToken($refreshToken);
return $this->json(['token' => $newToken]);
}
security:
providers:
jwt:
entity: { class: App\Entity\User }
property: email
use DimkinThePro\JwtAuthBundle\Security\User\JwtUserProvider;
services:
App\Security\CustomUserProvider:
parent: DimkinThePro\JwtAuthBundle\Security\User\JwtUserProvider
arguments: ['@App\Service\CustomUserLoader']
Use the JwtListener manually:
use DimkinThePro\JwtAuthBundle\EventListener\JwtListener;
public function onKernelRequest(GetResponseEvent $event) {
$listener = new JwtListener($jwtService);
$listener->onKernelRequest($event);
}
HttpOnly cookies or Authorization: Bearer headers.refreshToken()).$jwtService->setLogger($logger);
Secret Key Management
%env(JWT_SECRET_KEY)% and rotate keys periodically.JWT_SECRET_KEY is set in .env.Time Skew
leeway in jwt_auth.yaml:
leeway: 60 # 60 seconds buffer
Refresh Token Logic
lexik/jwt-auth-bundle for advanced features.Custom User Providers
JwtUserProvider or implement UserInterface:
class CustomUser implements UserInterface {
public function getRoles() { ... }
public function getPassword() { ... }
// ...
}
CORS Headers
Authorization header in preflight requests.Authorization:
# config/packages/nelmio_cors.yaml
paths:
'^/api/*':
methods: [GET, POST, PUT, DELETE]
headers: ['Authorization']
Token Decoding:
php bin/console debug:jwt "your.token.here"
(Note: Requires custom script; no built-in command exists.)
Common Errors:
| Error | Cause | Solution |
|---|---|---|
Invalid token |
Wrong secret key or malformed token | Verify JWT_SECRET_KEY and token format |
Token not found |
Missing Authorization header |
Check request headers |
User not found |
User provider misconfiguration | Debug JwtUserProvider |
Expired token |
Clock skew or short expiration_time |
Adjust leeway or token TTL |
Custom Token Fields
Override JwtService to add fields:
class CustomJwtService extends JwtService {
protected function getPayload(UserInterface $user, array $customClaims = []) {
$payload = parent::getPayload($user, $customClaims);
$payload['uid'] = $user->getId(); // Example
return $payload;
}
}
Event Listeners Extend token logic via events:
use DimkinThePro\JwtAuthBundle\Event\JwtEvents;
$dispatcher->addListener(JwtEvents::TOKEN_CREATED, function ($event) {
$event->getToken()->set('audit', 'login');
});
Non-Symfony Integration
Use the JwtEncoder/JwtDecoder services directly:
$encoder = $container->get('dimkin_the_pro_jwt_auth.encoder');
$token = $encoder->encode(['data' => 'value'], $secretKey);
3600 (1 hour) if not set.HS256 by default (no option to change).lexik/jwt-auth-bundle for cookies.How can I help you explore Laravel packages today?