Pre-Request Authorization Handshakes in Axios
Executing a pre-request authorization handshake in Axios is primarily achieved through asynchronous request interceptors. This mechanism allows the client to pause an outgoing HTTP request, perform an independent authentication handshake—such as obtaining an OAuth token or fetching a CSRF token—and attach the resulting credentials to the original request headers before it is transmitted across the network.
The Core Mechanism: Request Interceptors
Axios provides the axios.interceptors.request.use
method, which accepts an asynchronous callback function. When an HTTP
request is initiated, Axios evaluates this interceptor pipeline before
dispatching the network call. Because the interceptor function can
return a Promise, Axios waits for the promise to resolve
before proceeding with the request.
import axios from 'axios';
let authToken = null;
// Create an Axios instance
const apiClient = axios.create({
baseURL: 'https://api.example.com',
});
// Configure the request interceptor for authorization handshakes
apiClient.interceptors.request.use(async (config) => {
// Check if token is already present or valid
if (!authToken) {
// Perform the pre-request authorization handshake
const authResponse = await axios.post('https://auth.example.com/handshake', {
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
});
authToken = authResponse.data.token;
}
// Inject the authorization credential into the headers
config.headers.Authorization = `Bearer ${authToken}`;
// Return the modified configuration to proceed with the request
return config;
}, (error) => {
return Promise.reject(error);
});Execution Flow
- Trigger: A call to
apiClient.get(),apiClient.post(), or another request method is made. - Interception: Axios intercepts the execution flow
and passes the request configuration object (
config) to the registered request interceptor. - Handshake Execution: The interceptor checks for an existing, valid authorization artifact (such as a JWT, session token, or CSRF cookie). If none exists or the token has expired, an asynchronous HTTP call is made directly to the identity provider or authorization server.
- Header Mutation: Once the handshake resolves, the
credentials are added to
config.headers. - Request Continuation: The interceptor returns the
modified
configobject, signaling Axios to proceed with sending the original request.
Handling Concurrent Requests
When multiple requests are fired simultaneously, uncoordinated interceptors can cause multiple redundant handshake requests. To prevent this, the handshake promise should be shared across pending requests.
let handshakePromise = null;
apiClient.interceptors.request.use(async (config) => {
if (!authToken) {
// If a handshake is not already running, initiate one
if (!handshakePromise) {
handshakePromise = axios.post('https://auth.example.com/handshake', {
clientId: 'YOUR_CLIENT_ID',
}).then((res) => {
authToken = res.data.token;
handshakePromise = null; // Reset lock
}).catch((err) => {
handshakePromise = null;
return Promise.reject(err);
});
}
// Await the shared handshake resolution
await handshakePromise;
}
config.headers.Authorization = `Bearer ${authToken}`;
return config;
});By leveraging asynchronous request interceptors alongside promise caching, Axios ensures that pre-request authorization handshakes are executed reliably, securely, and without redundant network overhead.