Access Tokens and Refresh Tokens
Access Tokens and Refresh Tokens are used in authentication and authorization to provide secure access to resources in a web application.
Access Token:
- A short-lived token that allows access to certain resources.
- It is usually included in the headers of API requests to authenticate the client.
- It typically has an expiration time (e.g., 15 minutes to 1 hour).
Refresh Token:
- A long-lived token that is used to obtain a new access token after the previous one expires.
- It is usually stored securely and sent to the server to get a new access token when needed.
- It typically has a longer expiration time (e.g., several days to months).
How to Use Access Tokens and Refresh Tokens
1. Authentication Flow
-
User Logs In:
- The user sends their credentials (username and password) to the server.
-
Server Validates Credentials:
- The server validates the credentials and, if valid, generates an access token and a refresh token.
-
Tokens Sent to Client:
- The server sends both tokens to the client.
-
Client Stores Tokens:
- The client stores the access token (e.g., in memory or local storage) and the refresh token (e.g., in a secure HTTP-only cookie).
-
Accessing Protected Resources:
- The client includes the access token in the Authorization header of requests to access protected resources.
- Example:
GET /protected-resource Authorization: Bearer <access_token>
-
Token Expiration:
- If the access token expires, the client uses the refresh token to obtain a new access token.
-
Refreshing the Access Token:
- The client sends the refresh token to the server to request a new access token.
- Example:
POST /refresh-token Content-Type: application/json { "refreshToken": "<refresh_token>" }
-
Server Validates Refresh Token:
- The server validates the refresh token and, if valid, generates a new access token (and optionally a new refresh token) and sends them to the client.
-
Client Uses New Access Token:
- The client uses the new access token to continue accessing protected resources.
2. Implementation Example with Express.js
Here’s an example of implementing access token and refresh token in an Express.js application:
Dependencies:
npm install express jsonwebtoken bcryptjs body-parser
Server Setup:
-
Server Setup:
- Create a simple Express.js server with endpoints for login, accessing protected resources, and refreshing tokens.
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const bodyParser = require('body-parser');
const app = express();
const PORT = process.env.PORT || 3000;
app.use(bodyParser.json());
// Dummy user data
const users = [
{
id: 1,
username: 'user1',
password: bcrypt.hashSync('password1', 8), // hashed password
},
];
// Secret keys
const accessTokenSecret = 'youraccesstokensecret';
const refreshTokenSecret = 'yourrefreshtokensecret';
const refreshTokens = [];
// Login endpoint
app.post('/login', (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username);
if (!user || !bcrypt.compareSync(password, user.password)) {
return res.status(401).send('Username or password incorrect');
}
const accessToken = jwt.sign({ userId: user.id }, accessTokenSecret, { expiresIn: '20m' });
const refreshToken = jwt.sign({ userId: user.id }, refreshTokenSecret, { expiresIn: '7d' });
refreshTokens.push(refreshToken);
res.json({ accessToken, refreshToken });
});
// Protected resource endpoint
app.get('/protected', authenticateToken, (req, res) => {
res.send('This is a protected resource');
});
// Refresh token endpoint
app.post('/refresh-token', (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken || !refreshTokens.includes(refreshToken)) {
return res.status(403).send('Refresh token not found, login again');
}
jwt.verify(refreshToken, refreshTokenSecret, (err, user) => {
if (err) return res.status(403).send('Invalid refresh token');
const newAccessToken = jwt.sign({ userId: user.userId }, accessTokenSecret, { expiresIn: '20m' });
res.json({ accessToken: newAccessToken });
});
});
// Middleware to authenticate token
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, accessTokenSecret, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Explanation:
-
User Login:
- User sends a POST request to
/login
with their username and password. - Server validates the credentials and, if valid, generates an access token and a refresh token.
- Server sends the tokens to the client.
- User sends a POST request to
-
Accessing Protected Resource:
- Client sends a GET request to
/protected
with the access token in the Authorization header. - Server validates the access token using the
authenticateToken
middleware and grants access if the token is valid.
- Client sends a GET request to
-
Refreshing the Access Token:
- Client sends a POST request to
/refresh-token
with the refresh token. - Server validates the refresh token and, if valid, generates a new access token and sends it to the client.
- Client sends a POST request to
This example covers the basic implementation of using access tokens and refresh tokens in an Express.js application. You can further enhance security by storing tokens securely, implementing additional validation checks, and following best practices for handling sensitive data.
If you enjoy my content and would like to support my work, you can buy me a coffee. Your support is greatly appreciated!
Disclaimer: This content is generated by AI.
Top comments (0)