An Interest In:
Web News this Week
- March 30, 2024
- March 29, 2024
- March 28, 2024
- March 27, 2024
- March 26, 2024
- March 25, 2024
- March 24, 2024
Symfony 6 and JWT bundles: Refresh token
* The cover image is originally by geralt and edited with great appreciation.
Summary
Are you interested in JSON Web Token (JWT) authentication and authorization in PHP or Symfony, one of its frameworks?
If so, this post might be helpful:
Symfony 6 and Lexik JWT Bundle 2: Auth with JSON Web Token
Heddi Nabbisen Nov 12 5 min read
Well, lifetime of each access token should be short within practical term in order to mitigate risk on impersonation.
However, when access token is expired, what should we do? Request authentication information to users, again? It must be inconvenient in many cases, mustn't it
That's where refresh token steps in.
This post shows how to implement it in Symfony with JWTRefreshTokenBundle.
Here we go.
Environment
- Alpine Linux 3.16 (on Docker)
- PHP 8.1
- Symfony 6.1
- LexikJWTAuthenticationBundle 2
- JWTRefreshTokenBundle 1.1
- MariaDB 10.9
Tutorial
Overview
Remember you need install LexikJWTAuthenticationBundle and configure your app beforehand.
The steps here are as follows:
- Install the bundle
- PHP 8 specific operation (currently)
- Update database
- Configure
- Testing
1. Install the bundle
JWTRefreshTokenBundle is almost in your hand with composer. Run:
$ composer require gesdinet/jwt-refresh-token-bundle
The output started with:
Info from https://repo.packagist.org: #StandWithUkraineUsing version ^1.1 for gesdinet/jwt-refresh-token-bundle./composer.json has been updatedRunning composer update gesdinet/jwt-refresh-token-bundleLoading composer repositories with package informationUpdating dependenciesLock file operations: 1 install, 0 updates, 0 removals - Locking gesdinet/jwt-refresh-token-bundle (v1.1.1)Writing lock fileInstalling dependencies from lock file (including require-dev)Package operations: 1 install, 0 updates, 0 removals - Downloading gesdinet/jwt-refresh-token-bundle (v1.1.1) - Installing gesdinet/jwt-refresh-token-bundle (v1.1.1): Extracting archiveGenerating optimized autoload files116 packages you are using are looking for funding.Use the `composer fund` command to find out more!
Then it was followed by:
Symfony operations: 1 recipe (44a1f19720c3d647b7a54653d52ca981) - WARNING gesdinet/jwt-refresh-token-bundle (>=1.0): From github.com/symfony/recipes-contrib:main The recipe for this package comes from the "contrib" repository, which is open to community contributions. Review the recipe at https://github.com/symfony/recipes-contrib/tree/main/gesdinet/jwt-refresh-token-bundle/1.0
Read the warning carefully and enter "y" to continue:
Do you want to execute this recipe? [y] Yes [n] No [a] Yes for all packages, only for the current installation session [p] Yes permanently, never ask again for this project (defaults to n): y
The rest was:
- Configuring gesdinet/jwt-refresh-token-bundle (>=1.0): From github.com/symfony/recipes-contrib:mainExecuting script cache:clear [OK]Executing script assets:install public [OK] What's next? Some files have been created and/or updated to configure your new packages.Please review, edit and commit them: these files are yours.No security vulnerability advisories found
2. Adapt it to PHP 8 (currently)
Well, there was a problem. It was unfamiliar with PHP 8 and Symfony 6 by default, because it uses annotations. However, what was required without Symfony flex was attributes.
To fix it, edit src/Entity/RefreshToken.php
:
- /**- * @ORM\Entity- * @ORM\Table("refresh_tokens")- */+ #[ORM\Entity]+ #[ORM\Table(name: 'refresh_token')]
Then run:
$ composer install
3. Update database
You are perhaps familiar with these command lines. Run them:
$ php bin/console make:migration$ php bin/console doctrine:migrations:migrate
4. Configure routes and firewalls for refresh tokens
Edit config/routes.yaml
# ... jwt_auth: path: /auth+ jwt_refresh:+ path: /auth/refresh
Then edit config/packages/security.yaml
security: # ... firewalls: # ... jwt_auth: pattern: ^/auth stateless: true json_login: check_path: jwt_auth success_handler: lexik_jwt_authentication.handler.authentication_success failure_handler: lexik_jwt_authentication.handler.authentication_failure api: pattern: ^/api stateless: true jwt: ~+ refresh_jwt:+ check_path: jwt_refresh # ... # Note: Only the *first* access control that matches will be used access_control: # ... - { path: ^/auth, roles: PUBLIC_ACCESS } - { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
In addition, alternatively, you may want to integrate API routes of both auth and use:
# config/routes.yamljwt_auth: path: /api/authjwt_refresh: path: /api/auth/refresh
+
# config/packages/security.yamlsecurity: # ... firewalls: # ... api: pattern: ^/api stateless: true json_login: check_path: jwt_auth success_handler: lexik_jwt_authentication.handler.authentication_success failure_handler: lexik_jwt_authentication.handler.authentication_failure jwt: ~ entry_point: jwt refresh_jwt: check_path: jwt_refresh # ... access_control: - { path: ^/api/auth, roles: PUBLIC_ACCESS } - { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
That's it!
5. Let's play: API access with JWT
Just as my previous post, connect to /auth with curl to get token:
$ curl -X POST \ -H "Content-Type: application/json" \ -d '{"username":"your-username","password":"your-password"}' \ https://your-domain/auth
You will get refresh token as well as access token.
{"token":"xxx.xxx.xxx","refresh_token":"xxx"}
Gotcha
Let's try a few with the refresh token!
Case of missing :
$ curl -X POST \ https://(your-domain)/auth/refresh
{"code":401,"message":"Missing JWT Refresh Token"}
Case of an invalid one :
$ curl -X POST \ -d refresh_token="wrong-value" \ https://(your-domain)/auth/refresh
{"code":401,"message":"JWT Refresh Token Not Found"}
Case of the valid one :
$ curl -X POST \ -d refresh_token="xxx" \ https://(your-domain)/auth/refresh
{"token":"xxx.xxx.xxx","refresh_token":"xxx"}
Yay, here come new tokens of yours
Original Link: https://dev.to/nabbisen/symfony-6-and-jwt-bundles-refresh-token-2jlj
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To