
Using PHP-JWT to Implement Token and Token Refreshing
The php-jwt
library is a very useful mechanism for token-based authentication. It works especially well for securing user authentication in apps. However, all tokens come with an expiration time. So what happens when a token expires? How can we refresh it seamlessly, without the user noticing?
The key is for the frontend to handle token expiration. When the token is expired, the backend will respond with a message indicating expiration. We can define a specific error code (e.g., 1002
) for this scenario. Upon receiving this code, the frontend can automatically call the refresh token API and continue with the original request. Let’s walk through the implementation using the ThinkPHP framework and JWT.
Step 1: Install the JWT Package
Use Composer to install the JWT extension for ThinkPHP:
composer require thans/tp-jwt-auth
Then generate the JWT configuration file:
php think jwt:create
Step 2: First-Time Login to Get a Token
Example frontend code to fetch the token:
function get_token() {
$.ajax({
type: "GET",
url: "{:url('index/index/token')}",
dataType: "json",
success: (res) => {
localStorage.setItem('token', res.token)
}
});
}
Controller code to generate the token:
use thans\jwt\facade\JWTAuth;
public function token()
{
$token = JWTAuth::builder([
'userInfo' => [
'id' => 1,
'username' => 'jeevin'
]
]);
return json(['code' => 200, 'msg' => 'success', 'token' => $token]);
}
Step 3: Access Protected Resources Using the Token
Example frontend code to access user data:
function get_user() {
let isRefreshing = true; // Prevent multiple refresh requests
$.ajax({
type: "GET",
url: "{:url('index/index/user')}",
data: { token: localStorage.getItem('token') },
dataType: "json",
success: (res) => {
if (res.code === 1002) {
if (isRefreshing) {
refreshTokenRequest(); // Refresh the token if expired
}
}
isRefreshing = false;
}
});
}
Function to refresh the token:
function refreshTokenRequest() {
$.ajax({
type: "GET",
url: "{:url('index/index/refesh_token')}",
data: { token: localStorage.getItem('token') },
dataType: "json",
success: (res) => {
if (res.code === 200) {
localStorage.setItem('token', res.token);
}
}
});
}
Step 4: Backend Logic for Protected Resources and Token Refresh
Get user info:
public function user()
{
try {
$token = JWTAuth::auth();
return json(['code' => 200, 'msg' => 'Success', 'token' => $token]);
} catch (\thans\jwt\exception\TokenExpiredException $e) {
return json(['code' => 1002, 'msg' => 'Token expired']);
} catch (\Exception $e) {
return json(['code' => 400, 'msg' => $e->getMessage()]);
}
}
Refresh token API:
public function RefeshToken()
{
$token = JWTAuth::refresh();
return json(['code' => 200, 'msg' => 'Success', 'token' => $token]);
}
Conclusion
With php-jwt
and a little help from the frontend, you can easily implement a secure and user-friendly token-based authentication system in ThinkPHP. By handling token expiration on the client side and using a refresh token endpoint, users can stay authenticated without any interruptions.