JWT Authentication in React Make Authenticated Requests

Learning objective: By the end of this lesson, students will be able to authenticate requests to a back-end server using a JWT in a React application.

Authenticating requests with a JWT

Let’s make the Dashboard component useful by fetching some data from the server. We’ll need to authenticate this request with a JWT. This is because the server will only respond with the data if the request includes a valid token. The server will not respond with the requested data without the token.

Fetching data from the server

Let’s start by creating a new service function that fetches the data we need. This function will make the authenticated request for user data to the server.

The function shouldn’t go in the authService.js file because while the request needs to be authenticated, the request itself isn’t related to authentication. Instead, we’ll create a new file that will contain all of our service functions for fetching user data:

touch src/services/userService.js

🎓 You Do

Create a new service function called index() in userService.js that makes a GET request to /users to fetch user data from the server. The function should:

Move to the Dashboard component’s file.

Try it out!

Return to your browser, open the console, and navigate to the dashboard while logged in. If you’ve set everything up correctly, you should see… an error. That’s ok though; the error message should indicate that the token is invalid and you’re unauthorized to access that route on the server. We’ll fix that next!

😎 Having trouble with this? That’s ok, a lot is going on here! Try debugging any problems you have, but if you need it, there is a solution below.

Solution

First - the userService.js file:

// src/services/userService.js

const BASE_URL = `${import.meta.env.VITE_BACK_END_SERVER_URL}/users`;

const index = async () => {
  try {
    const res = await fetch(BASE_URL);

    const data = await res.json();

    if (data.err) {
      throw new Error(data.err);
    }

    return data
  } catch (err) {
    console.log(err);
    throw new Error(err);
  }
};


export {
  index,
};

Next, the Dashboard component:

// src/components/Dashboard/Dashboard.jsx

import { useEffect, useContext } from 'react';

import { UserContext } from '../../contexts/UserContext';

import * as userService from '../../services/userService';

const Dashboard = () => {
  const { user } = useContext(UserContext);

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        const fetchedUsers = await userService.index();
        console.log(fetchedUsers);
      } catch (err) {
        console.log(err)
      }
    }
    if (user) fetchUsers();
  }, [user]);

  return (
    <main>
      <h1>Welcome, {user.username}</h1>
      <p>
        This is the dashboard page where you can see a list of all the users.
      </p>
    </main>
  );
};

export default Dashboard;

Making an authenticated request

Let’s fix the unauthorized error we’re seeing in the console.

To do this, we need to include the JWT in the request to the server so that it knows who we are. We’ll do this by adding an Authorization header to the request. This header will contain the word Bearer along with the JWT.

// src/services/userService.js

const index = async () => {
  try {
    // Change the fetch request so that it includes the Authorization header
    const res = await fetch(BASE_URL, {
      headers: { Authorization: `Bearer ${localStorage.getItem('token')}` },
    });

    const data = await res.json();

    if (data.err) {
      throw new Error(data.err);
    }

    return data
  } catch (err) {
    console.log(err);
    throw new Error(err);
  }
};

Note the formatting of the Authorization header: Bearer followed by a space and then the token. This exact format is required, and our back-end server will expect it.

Try navigating to the dashboard again. If everything is set up correctly, you should see the data returned from the server logged to the console!

🎓 You Do

All that’s left to do is put that data into state and display it! Tackle this on your own. Display the data in a list that shows the username of each user.