Nextjs: how to append jwt token to headers of every API call

3 min read 05-10-2024
Nextjs: how to append jwt token to headers of every API call


Securing Your Next.js App: How to Append JWT Tokens to API Calls

Building a secure web application requires careful consideration of how you manage user authentication and authorization. One common approach is using JSON Web Tokens (JWTs), which provide a standardized and secure way to transmit information between parties. In Next.js, integrating JWTs into your API calls can be straightforward. This article explores the process of appending JWT tokens to every API request made from your Next.js application.

Scenario: Imagine you have a Next.js application that relies on a backend API for data retrieval and user management. You want to ensure that every API call made from your Next.js frontend is authenticated with a valid JWT.

Original Code (Example):

// components/MyComponent.js
import { useState } from 'react';

const MyComponent = () => {
  const [userData, setUserData] = useState(null);

  const fetchData = async () => {
    try {
      const response = await fetch('/api/users');
      const data = await response.json();
      setUserData(data);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <div>
      <button onClick={fetchData}>Fetch User Data</button>
      {userData && <p>Welcome, {userData.name}</p>}
    </div>
  );
};

export default MyComponent;

Analysis & Solution:

The code above makes a simple API call to /api/users, but it lacks authentication. To append a JWT token to the request header, we'll modify the fetch call using a custom fetch wrapper or an HTTP library like Axios.

1. Custom fetch Wrapper:

// utils/api.js
import { getAccessToken } from './auth';

const api = async (url, options = {}) => {
  const accessToken = getAccessToken();
  const headers = {
    Authorization: `Bearer ${accessToken}`,
    ...options.headers,
  };

  const response = await fetch(url, {
    ...options,
    headers,
  });

  if (!response.ok) {
    throw new Error(`API Error: ${response.status}`);
  }

  return response;
};

export default api;

This api function takes the API endpoint and optional request options as arguments. It retrieves the access token from local storage (using getAccessToken function), constructs the authorization header, and uses fetch to make the request.

2. Integrating with Axios:

// utils/api.js
import axios from 'axios';
import { getAccessToken } from './auth';

const api = axios.create({
  baseURL: 'http://your-api-endpoint', // Set your API base URL
  headers: {
    Authorization: `Bearer ${getAccessToken()}`,
  },
});

export default api;

Axios provides a more structured way to manage API requests. We create an Axios instance with the base URL and a default authorization header. The getAccessToken function is used to retrieve the token.

3. Updating Component Code:

// components/MyComponent.js
import { useState } from 'react';
import api from '../utils/api'; // Import your API helper

const MyComponent = () => {
  const [userData, setUserData] = useState(null);

  const fetchData = async () => {
    try {
      const response = await api.get('/users'); // Use the api instance
      const data = await response.data;
      setUserData(data);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <div>
      <button onClick={fetchData}>Fetch User Data</button>
      {userData && <p>Welcome, {userData.name}</p>}
    </div>
  );
};

export default MyComponent;

In the component code, we now use api.get('/users') to fetch the user data. This ensures that the JWT is automatically included in the request header.

Additional Value:

  • Centralized Authentication: This approach keeps your authentication logic centralized, reducing code duplication.
  • Code Reusability: The api function or Axios instance can be used across different components, making your API calls consistent.
  • Error Handling: Implementing error handling in the api helper function ensures proper response handling in case of authentication failures or other API errors.

References and Resources:

Conclusion:

By implementing these techniques, you can effectively append JWT tokens to every API call made from your Next.js application. This ensures that your frontend applications are securely authenticated and authorized with your backend services. Remember to choose the approach that best suits your project's needs and preferences, and consider using a dedicated library for JWT management to simplify the process.