JWT Authentication Documentation
The system natively supports JWT for authentication and token management, however the module allows you to manage logs and allows you to download a class to manage the APIs from other PHP projects.
Introduction
JWT (JSON Web Token) is a compact, URL-safe means of representing claims to be transferred between two parties. In authentication systems, JWTs allow you to securely transmit information between client and server as a JSON object.
How JWT Authentication Works
The JWT authentication process follows a simple flow:
- Client sends credentials (username/password) to the server
- Server validates credentials and generates a JWT token
- Server returns the token to the client
- Client stores the token and sends it with subsequent requests
- Server validates the token and processes the request
Basic JWT Authentication Example
Below is a simple example demonstrating how to implement JWT authentication in your application.
Step 1: Authentication Request
First, the client sends a request with username and password to get a JWT token:
// Client-side code: Request a token with username and password
$url = 'https://example.com/?page=jwt-test-api-v1&action=generate-token';
// Set up the request
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
// Set Basic Authentication header
$username = 'admin';
$password = 'admin';
$auth_string = base64_encode("$username:$password");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Basic ' . $auth_string
]);
// Execute the request
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Parse the response
if ($http_code == 200) {
$token_data = json_decode($response, true);
echo "Token received: " . $token_data['token'] . "\n";
echo "Expires at: " . date('Y-m-d H:i:s', $token_data['expires_at']) . "\n";
} else {
echo "Authentication failed: $response\n";
}
Step 2: Server-side Token Generation
The server authenticates the user and generates a JWT token:
// Server-side code: Route handler for generating tokens
Route::set('jwt-test-api-v1', function() {
if ($_REQUEST['action'] == 'generate-token') {
// Extract username and password from Basic Auth header
$credentials = Route::extractCredentials();
// Validate credentials
$login = Get::make('Auth')->login($credentials['username'], $credentials['password'], false);
if ($login == false) {
Response::json([
'error' => 'Invalid credentials'
]);
return;
}
// Get authenticated user
$user = Get::make('Auth')->getUser();
// Generate JWT token
$token = Token::generateJwt($user->id, [
'username' => $user->username,
'email' => $user->email,
// Add other user data as needed
]);
// Calculate expiration time (1 hour from now)
$expires_at = time() + 3600;
// Return token and expiration
Response::json([
'token' => $token,
'expires_at' => $expires_at
]);
}
});
Step 3: Using the Token for API Requests
Once the client has the token, it can make authenticated API requests:
// Client-side code: Using the JWT token for API requests
$url = 'https://example.com/?page=api-endpoint&action=get-data';
$token = $token_data['token']; // Token received from previous step
// Set up the request
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $token
]);
// Execute the request
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Process the response
if ($http_code == 200) {
$data = json_decode($response, true);
echo "API request successful\n";
print_r($data);
} else {
echo "API request failed: $response\n";
}
Step 4: Server-side Token Verification
The server verifies the token for protected API endpoints:
// Server-side code: Verifying JWT token on protected endpoints
Route::set('api-endpoint', function() {
// Extract token from Authorization header
$token = Route::getBearerToken();
if (!$token) {
Response::json([
'error' => 'Authentication required'
]);
return;
}
// Verify token
$user_id = Token::verifyJwt($token);
if ($user_id === false) {
Response::json([
'error' => 'Invalid token: ' . Token::$last_error
]);
return;
}
// Token is valid, proceed with the API request
if ($_REQUEST['action'] == 'get-data') {
// Get user information
$user = Get::make('Auth')->getUser($user_id);
// Return data
Response::json([
'message' => 'Authentication successful',
'user_id' => $user_id,
'username' => $user->username,
'data' => [
// Your API response data here
]
]);
}
});
JWT Token Structure
A JWT token consists of three parts separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
These parts are:
- Header: Contains the token type and signing algorithm
- Payload: Contains the claims (user data and metadata)
- Signature: Verifies the token hasn't been tampered with
Key Concepts
1. Basic Authentication
Used only for the initial token request. The client sends the username and password encoded in the Authorization header:
Authorization: Basic YWRtaW46YWRtaW4=
Where YWRtaW46YWRtaW4= is the Base64 encoding of admin:admin.
2. Bearer Authentication
Used for all subsequent API requests after obtaining a token. The client includes the token in the Authorization header:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
3. Token Expiration
JWT tokens have an expiration time for security. The server returns this as a Unix timestamp:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_at": 1620000000
}
Clients should refresh tokens before they expire to maintain the session.
4. Token Refresh
To refresh a token, the client sends the current token to a refresh endpoint, which issues a new token:
// Client-side token refresh example
$url = 'https://example.com/?page=jwt-test-api-v1&action=refresh-token';
$current_token = $token_data['token'];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $current_token
]);
$response = curl_exec($ch);
curl_close($ch);
$new_token_data = json_decode($response, true);
// Use the new token for subsequent requests
Complete JWT Test Implementation
For a complete implementation example, you can check the JWT test files:
- Server Module: Handles token generation, verification and refreshing
- JWT Test Client: Tests the JWT functionality with a complete authentication flow
To run the test and see the complete flow in action, access /jwt.test.php in your browser. This will execute a series of tests demonstrating:
- Basic Authentication and token generation
- Token verification
- Token refresh
- Verification of the new token
Security Best Practices
- Always use HTTPS to prevent token interception
- Set appropriate token expiration (typically 15-60 minutes)
- Don't store sensitive data in the token payload
- Implement proper error handling for authentication failures
- Use secure algorithms for token signing (RS256 recommended for production)
Documenting JWT APIs
Remember to document your JWT endpoints using the #[ApiDoc] attribute when implementing authentication APIs:
use App\Attributes\{ApiEndpoint, ApiDoc};
#[ApiEndpoint('auth/login', 'POST')]
#[ApiDoc(
'Authenticate user and return JWT token',
['body' => ['username' => 'string', 'password' => 'string']],
['token' => 'string', 'expires_at' => 'int', 'user' => ['id' => 'int', 'username' => 'string']]
)]
public function login($request) {
// Login logic
}
Conclusion
JWT provides a simple yet powerful way to implement authentication in your API. By understanding the basic flow and implementing the provided examples, you can quickly add secure authentication to your application.