@dedrick
To implement roles with JWT in Symfony 4, you can follow these steps:
Step 1: Install JWT package
First, you need to install the lexik/jwt-authentication-bundle
package. Run the following command to install it:
1
|
composer require lexik/jwt-authentication-bundle |
Step 2: Configure JWT
Next, configure JWT in your config/packages/lexik_jwt_authentication.yaml
file:
1 2 3 4 5 6 7 |
# config/packages/lexik_jwt_authentication.yaml lexik_jwt_authentication: secret_key: '%env(APP_SECRET)%' public_key: '%env(APP_PUBLIC_KEY)%' pass_phrase: '%env(APP_PASSPHRASE)%' token_ttl: 3600 # token expires after 1 hour |
Note: Make sure you have set the APP_SECRET
, APP_PUBLIC_KEY
, and APP_PASSPHRASE
environment variables.
Step 3: Generate the authentication controller Run the following command to generate the authentication controller:
1
|
php bin/console make:controller AuthController |
This will create a new controller file at src/Controller/AuthController.php
.
Step 4: Implement authentication endpoints
In the AuthController
, add the following methods to handle authentication endpoints:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
// src/Controller/AuthController.php // ... use SymfonyComponentSecurityCoreEncoderUserPasswordEncoderInterface; use SymfonyComponentSecurityCoreUserUserInterface; use LexikBundleJWTAuthenticationBundleServicesJWTTokenManagerInterface; use LexikBundleJWTAuthenticationBundleEncoderJWTEncoderInterface; class AuthController extends AbstractController { // ... /** * @Route("/login", name="login", methods={"POST"}) */ public function login(Request $request, UserInterface $user, UserPasswordEncoderInterface $encoder, JWTEncoderInterface $jwtEncoder, JWTTokenManagerInterface $jwtManager) { $data = json_decode($request->getContent(), true); $isValid = $encoder->isPasswordValid($user, $data['password']); if (!$isValid) { throw new UnauthorizedHttpException('Invalid credentials'); } $payload = [ 'username' => $user->getUsername(), 'roles' => $user->getRoles(), 'exp' => time() + $this->getParameter('jwt_token_ttl') ]; $token = $jwtEncoder->encode($payload); $jwtManager->create($user); return $this->json([ 'token' => $token ]); } /** * @Route("/me", name="me", methods={"GET"}) */ public function me() { // Use Symfony's authentication system to get the user details $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); // The user is authenticated, return the user details return $this->json([ 'user' => $this->getUser() ]); } } |
Step 5: Add routes
Configure the routes for the authentication endpoints in config/routes.yaml
:
1 2 3 4 5 6 7 |
# config/routes.yaml # ... auth: resource: 'AppControllerAuthController' type: annotation |
Step 6: Implement authorization
To implement authorization with roles, you can use Symfony's built-in @Security
annotation in your controller or create a new event listener to check the roles. Here's an example using the @Security
annotation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// src/Controller/SecureController.php use SymfonyComponentRoutingAnnotationRoute; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentSecurityCoreExceptionAccessDeniedException; use SymfonyComponentSecurityCoreExceptionAuthenticationCredentialsNotFoundException; use SymfonyComponentSecurityCoreUserUserInterface; use SensioBundleFrameworkExtraBundleConfigurationSecurity; class SecureController extends AbstractController { // ... /** * @Route("/admin", name="admin") * @Security("is_granted('ROLE_ADMIN')") */ public function admin(UserInterface $user) { // Only users with the ROLE_ADMIN role can access this endpoint // ... } } |
That's it! You have implemented roles with JWT in Symfony 4 using the lexik/jwt-authentication-bundle
package.