How to securely access custom backend API after SPA authentication?

Hello,

I am attempting to create a single-page ReactJs application that prompts my user to log in using the Auth0 Universal Login page. Once the user is logged into my React app, the app needs to call my custom NodeJS API which will do two things:

  1. Perform Management API calls in order to generate a user management screen.
  2. Perform simple CRUD operations on a custom database.

I am starting with the ReactJS quickstart app. I am trying to understand how to extend it to securely call my custom backend API. I was hoping that I could simply pass the access token generated by the quickstart app to my API as a bearer token and that my API could simply validate it and then perform the requested actions. But, I am not sure this is possible.

Bottom Line: Once my user is authenticated by my ReactApp, how do I enable the React app to access my backend API? And, how do I prevent anyone not authorized by my ReactApp to access my backend API?

Your idea is absolutely correct, you need to get an access_token in the frontend and send it to your backend, which will validate it and do whatever is required

1 Like

Hey there @idatarbel and thanks for the input @phi1ipp!

I recommend checking out the node-oauth2-jwt-bearer library outlined here:

For using the Management API in particular, you’ll want to take a look at the ManagementClient of node-auth0.

Hope this helps!

Great.

  1. Can you point me to example access token validation code for NodeJs?

  2. And, what if anything beyond what I set up to run the React quick start app do I need to set up in the Auth0 dashboard to get this API communication to work? For instance, do I need a separate machine to machine API? Do I need a separate custom auth server or something?

Sorry, I somehow missed tyf’s response. The suggestion to use node-oauth2-jwt-bearer worked.

For those who face the same question I did (how to call a custom backend API after your user has been authenticated), here’s the NodeJs API code you need:

//I use import instead of require because I have other dependencies in my express server that necessitate import statements:
import { auth } from 'express-oauth2-jwt-bearer';

//Next, I get values for two variables from the Auth0 dashboard's Application section.  Note that 
//you have to preface variables with "REACT_APP_" when you put them in a .env file or ReactJs 
//won't be able to locate them.
const auth0IssuerBaseUrl= process.env.REACT_APP_AUTH0_ISSUER_BASE_URL;
const auth0Audience = process.env.REACT_APP_AUTH0_AUDIENCE;

// Next, make sure you set cors as follows or you will get cors errors when your front end calls your API:
app.use(cors({
    origin: '*'
}));

//Next, plug in this access token validation code.  Make sure this code comes AFTER the cors 
//code or this code will generate a cors error.
app.use( auth({
    issuerBaseURL: auth0IssuerBaseUrl,
    audience: auth0Audience
  }));

Here is a test method from the ReactJs front end app:

const callApi = async () => {
    try {
      //This will work:
      let token = await getAccessTokenSilently();

      //This won't work -- which is expected -- because it is an invalid token.
      //let token = "Doesn't work";

      const response = await fetch(`${apiOrigin}/api/private`, {
        headers: {
          'content-type': 'application/json',
          accept: 'application/json',
          Authorization: `Bearer ${token}`,
        },
      });

1 Like

That’s great I’m glad to hear the library worked for you, and thanks for sharing with the community! :rocket:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.