1
votes

I am new to development and am trying to create an app with a React frontend and an Express backend to make calls to a third party API. To access the data, I have a login page where the user retrieves the data and a token is stored locally.

The token is then passed using auth-header.js:

export default function authHeader() {
    const user = JSON.parse(localStorage.getItem("user"));

    if (user) {
        return {
          "Authorization": "Bearer " + user 
        };
    } else {
      return {};
    }
  }

Which is used as a header in the axios call to the backend in user-service.js:

import axios from 'axios';
import authHeader from './auth-header';
require('dotenv').config();

class UserService {
    getRoles() {
        return axios.get(process.env.REACT_APP_SERVICE + '/api/users/roles', { headers: authHeader() });
    }
}

export default new UserService();

Then sent to the NodeJS/Express backend in app.js:

var createError = require('http-errors');
var express = require('express');
var axios = require('axios');
var cors = require('cors');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var authRouter = require('./routes/auth.routes');
var userRouter = require('./routes/user.routes');

var corsOptions = {
  origin: "http://localhost:3000"
};

var app = express();
app.use(cors(corsOptions));

app.use(function(req, res, next) {
  res.header(
    "Access-Control-Allow-Headers",
    "x-access-token, Origin, Content-Type, Accept"
  );
  next();
});

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// routes
app.use('/', indexRouter);
app.use('/api/auth/login', authRouter);
app.use('/api/users/roles', userRouter);

Which is routed by user.routes.js:

var express = require('express');
var router = express.Router();

const controller = require("../controllers/user.controller");

router.get('/', controller.roles);

module.exports = router;

And the headers are passed into the axios call in user.controller.js to retrieve the data from the third party API to be sent back to the frontend:

var axios = require('axios');

const api_url = "https://my-api-url.com";

module.exports = {
    roles: (req, res) => {
        console.log("grabbing user info");
        return axios.get(api_url + "/api/users/me", {
          headers: req.headers["authorization"]
        }
        ).then((response) => {
          console.log(response.data);
          res.send({ 
            roles: response.data.roles 
          });
        }).catch((err) => {
          console.log("failed to grab user info");
          res.send("error");
        });
    }
};

I receive the following errors:

server      | made login request...
server      | POST /api/auth/login 200 866.508 ms - 1308
server      | grabbing user info
server      | failed to grab user info
server      | GET /api/users/roles 304 4.095 ms - -
server      | grabbing user info
server      | failed to grab user info
server      | GET /api/users/roles 304 3.157 ms - -

The 304 error is a bit ambiguous and I'm having trouble debugging it. I also don't understand why the axios call is failing.

When I console.log(req.headers["authorization"]) it prints the correct information. So I'm at a loss with understanding why it doesn't accept the token and retrieve the data. Is there any formatting I need to change? Is there a better way to retrieve the headers other than "req.headers["authorization"]"? I would also like to use best practices, but at the moment I'm not sure where the flaw in my logic is or how to troubleshoot. Any advice would be really appreciated.

1
did you try logging the error? catch(err => { console.log(err) })azium
This was the result: server | TypeError: name.toUpperCase is not a function server | at processHeader (/usr/src/app/node_modules/axios/lib/helpers/normalizeHeaderName.js:7:41) server | at Object.forEachCristina

1 Answers

0
votes

You are setting headers to be the value of the authorization header. headers should be an object

...
headers: {
  authorization: req.headers["authorization"]
}
...