Token authentication is a common way to authenticate users after they successfully log in. Instead of sending the user's password with every API request, the application receives a token after login and sends that token with future protected API requests.
Token authentication is a method where a server provides a token to an authenticated client. The client then uses that token to access protected API resources.
Login
↓
Verify User
↓
Generate Token
↓
Send Token
↓
Mobile App
↓
Protected API Request
↓
Verify Token
A mobile application should not send the user's password with every API request. Instead, the application can authenticate once and use a token for later requests.
React Native
↓
Email + Password
↓
Login API
↓
Verify Credentials
↓
Generate Token
↓
Return Token
↓
React Native
↓
Store Token
↓
Protected API
↓
Send Token
↓
Verify Token
↓
Return Data
The mobile application first sends the user's login information to the login API.
POST /api/login.php
{
"email": "user@example.com",
"password": "123456"
}
The server receives the credentials and verifies the user.
The API finds the user in the database and verifies the supplied password against the stored password hash.
$stmt = $pdo->prepare(
"SELECT * FROM users WHERE email = ?"
);
$stmt->execute([$email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (
!$user ||
!password_verify(
$password,
$user['password']
)
) {
http_response_code(401);
exit;
}
After successful authentication, the server generates a token for the authenticated user.
For learning purposes, a token can be represented as a random value.
$token = bin2hex(
random_bytes(32)
);
echo $token;
The token generation method should be designed according to the authentication system being implemented.
A token may look like a long random string.
9f3a7d2c8b1e4f6a
0a9c5d7e2b8f1a3c
6d4e9b7c2a5f8d1e
The client does not need to understand the internal meaning of the token. It simply sends the token back to the API when authentication is required.
After generating the token, the login API can return it in a JSON response.
echo json_encode([
"success" => true,
"message" => "Login successful",
"token" => $token
]);
{
"success": true,
"message": "Login successful",
"token": "9f3a7d2c8b1e4f6a..."
}
The React Native application reads the token from this response.
After receiving the token, the mobile application needs to keep it so that it can use it for later API requests.
Login API
↓
Token
↓
React Native
↓
Token Storage
↓
Protected Requests
A later lesson will cover storing authentication tokens in a React Native application.
The token can be sent through the Authorization header.
Authorization: Bearer YOUR_TOKEN
The API can then extract and validate the token before returning protected data.
A common token authentication format is the Bearer authentication scheme.
Authorization: Bearer 9f3a7d2c8b1e4f6a...
The word Bearer identifies the authentication scheme and the value after it is the token.
Suppose we have a profile API:
GET /api/profile.php
The API requires a valid token before returning the user's profile.
Request
↓
Read Authorization Header
↓
Extract Token
↓
Validate Token
↓
Valid?
┌──┴──┐
Yes No
↓ ↓
Data 401
The PHP API can read the Authorization header from the incoming request.
$authorization =
$_SERVER['HTTP_AUTHORIZATION'] ?? '';
if ($authorization === '') {
http_response_code(401);
echo json_encode([
"success" => false,
"message" => "Token required"
]);
exit;
}
$authorization =
$_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (
!preg_match(
'/Bearer\s+(.+)/i',
$authorization,
$matches
)
) {
http_response_code(401);
echo json_encode([
"success" => false,
"message" =>
"Invalid authorization header"
]);
exit;
}
$token = trim($matches[1]);
The extracted value can then be checked against the authentication system used by the application.
One simple token authentication design is to store a token associated with a user in a database table.
For example, a table could contain:
| Column | Purpose |
|---|---|
| id | Token record ID |
| user_id | Authenticated user |
| token | Authentication token |
| expires_at | Token expiration time |
| created_at | Token creation time |
A simple token table can be created using MySQL.
CREATE TABLE user_tokens (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
token VARCHAR(255) NOT NULL,
expires_at DATETIME NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
In a production system, the exact schema should be designed according to the selected authentication strategy and security requirements.
$token = bin2hex(
random_bytes(32)
);
$stmt = $pdo->prepare(
"INSERT INTO user_tokens
(user_id, token)
VALUES (?, ?)"
);
$stmt->execute([
$user['id'],
$token
]);
The token is now associated with the authenticated user.
A protected API can search for the supplied token.
$stmt = $pdo->prepare(
"SELECT user_id
FROM user_tokens
WHERE token = ?
LIMIT 1"
);
$stmt->execute([$token]);
$tokenData =
$stmt->fetch(PDO::FETCH_ASSOC);
if (!$tokenData) {
http_response_code(401);
echo json_encode([
"success" => false,
"message" => "Invalid token"
]);
exit;
}
After a valid token is found, the API can use the associated user ID to identify the authenticated user.
$userId = $tokenData['user_id'];
$stmt = $pdo->prepare(
"SELECT id, name, email
FROM users
WHERE id = ?"
);
$stmt->execute([$userId]);
$user = $stmt->fetch(
PDO::FETCH_ASSOC
);
Tokens can have an expiration time. An expired token should not be accepted for protected API requests.
$stmt = $pdo->prepare(
"SELECT user_id
FROM user_tokens
WHERE token = ?
AND (
expires_at IS NULL
OR expires_at > NOW()
)
LIMIT 1"
);
$stmt->execute([$token]);
If the token does not exist or has expired, the API should reject the request.
http_response_code(401);
echo json_encode([
"success" => false,
"message" => "Invalid or expired token"
]);
The mobile application can then ask the user to log in again when appropriate.
const response = await fetch(
"https://example.com/api/profile.php",
{
method: "GET",
headers: {
"Authorization":
"Bearer " + token,
"Accept": "application/json"
}
}
);
const data = await response.json();
console.log(data);
The mobile application should check whether the API request was successful.
if (response.ok) {
console.log("Authenticated");
} else if (response.status === 401) {
console.log(
"Authentication required"
);
}
A simple logout process can remove or invalidate the token associated with the user.
DELETE FROM user_tokens
WHERE token = ?
After the token is removed, the same token can no longer be used by the protected API.
LOGIN
↓
React Native
↓
Email + Password
↓
PHP Login API
↓
Verify Password
↓
Generate Token
↓
MySQL
↓
Return Token
↓
React Native
↓
Store Token
↓
Protected API
↓
Authorization Header
↓
Verify Token
↓
Identify User
↓
Return JSON
<?php
header("Content-Type: application/json");
$authorization =
$_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (
!preg_match(
'/Bearer\s+(.+)/i',
$authorization,
$matches
)
) {
http_response_code(401);
echo json_encode([
"success" => false,
"message" => "Token required"
]);
exit;
}
$token = trim($matches[1]);
$stmt = $pdo->prepare(
"SELECT user_id
FROM user_tokens
WHERE token = ?
AND (
expires_at IS NULL
OR expires_at > NOW()
)
LIMIT 1"
);
$stmt->execute([$token]);
$tokenData =
$stmt->fetch(PDO::FETCH_ASSOC);
if (!$tokenData) {
http_response_code(401);
echo json_encode([
"success" => false,
"message" => "Invalid or expired token"
]);
exit;
}
echo json_encode([
"success" => true,
"message" => "Token is valid",
"user_id" => $tokenData['user_id']
]);
?>
Postman can be used to test token-protected APIs.
Step 1: Login using the login API.
POST
http://localhost/api/login.php
Step 2: Copy the returned token.
Step 3: Open the protected API.
GET
http://localhost/api/profile.php
Step 4: Add the Authorization header.
Authorization: Bearer YOUR_TOKEN
If the token is valid, the protected API should return the requested data.
Token authentication allows a user to log in once and then use an authentication token for subsequent protected API requests. The server creates the token after successfully verifying the user's credentials. The mobile application sends the token through the Authorization header, and the server validates it before allowing access.
Login
↓
Verify Password
↓
Generate Token
↓
Return Token
↓
React Native
↓
Store Token
↓
Authorization Header
↓
Protected API
↓
Validate Token
↓
Identify User
↓
Return Data
Question: Where is a Bearer token commonly sent in an HTTP request?