React axios 401 unauthorized

37,938

You are facing this because your req.user is empty that's why it goes to else statement and returns Unauthorized which you are returning.

Check your server console if it is printing anything console.log(res.locals.user);

Send your auth token with headers like this

headers : {
  'Content-Type' : 'application/json',
  'Accept' : 'application/json',
  'Authorization' : 'Bearer <token_here>'
}

Updated

Your request will always return 401 unauthorized.

https://github.com/manjurulhoque/nodejs-ecommerce-api/blob/master/routes/users.js#L105

Check my code. To get logged in user you have to use

passport.authenticate('jwt', { session: false })
Share:
37,938
randal
Author by

randal

Updated on July 09, 2022

Comments

  • randal
    randal almost 2 years

    I get a 401 error, when trying to authenticate a user. Just to give context, React is using an Express server, and using Passport for authentication. React has a port of 8001, and the Express server has the port of 8000.

    GET /api/users/user 401 2.167 ms - 59

    enter image description here

    enter image description here

    Other get requests Do work. For example

    enter image description here

    React

    export const getUser = () => {
    
        return async (dispatch) =>{
            Axios.get('/api/users/user')
            .then( (res) => {
                console.log(res.data);
                localStorage.setItem('auth', res.data.authenticated);
                dispatch({type: GET_USER, res});
            }).catch( (err) => {
                console.log(err);
            })
        }
    }
    

    axios

    import Axios from 'axios'
    
    let AxiosInstance = Axios.create({
      baseURL: process.env.REACT_APP_BASE_URL, // http://localhost:8000
      withCredentials: true,
      headers: {
        'Content-Type': 'application/json',
      },
    
    })
    
    // AxiosInstance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
    
    AxiosInstance.interceptors.response.use(function(response) {
      return response;
    })
    
    export default AxiosInstance
    

    routes/user

    router.get('/user', (req, res, next) => {
        if(req.user) {
            return res.status(200).json({
                user: req.user,
                authenticated: true
            });
        } else {
            return res.status(401).json({
                error: 'User is not authenticated',
                authenticated: false
            });
        }
    });
    

    File app.js

    var express = require('express');
    var app = express();
    var userRoute = require('./routes/users');
    var postRoute  = require('./routes/posts');
    var bodyParser = require('body-parser');
    var logger = require('morgan');
    var models = require('./models');
    var User = require('./models/user');
    var session = require('express-session');
    var cookieParser = require('cookie-parser') ;
    var cookieSession = require('cookie-session');
    var dotenv = require('dotenv');
    var env = dotenv.config();
    var cors = require('cors');
    const port = process.env.PORT || 8000;
    const passport = require('passport');
    const path = require('path');
    const allowOrigin = process.env.ALLOW_ORIGIN || '*'
    
    // CORS Middleware
    
    if (!process.env.PORT) {
      require('dotenv').config()
    }
    
    if (!process.env.PORT) {
      console.log('[api][port] 8000 set as default')
      console.log('[api][header] Access-Control-Allow-Origin: * set as default')
    } else {
      console.log('[api][node] Loaded ENV vars from .env file')
      console.log(`[api][port] ${process.env.PORT}`)
      console.log(`[api][header] Access-Control-Allow-Origin: ${process.env.ALLOW_ORIGIN}`)
    }
    
    
    app.use(logger('dev'));
    app.use(express.static(path.join(__dirname, 'public')));
    app.use(cookieParser());
    app.use(bodyParser());
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false })); 
    
    
    
    
    app.use(cors({
      origin: process.env.ALLOW_ORIGIN,
      credentials: true,
      allowedHeaders: 'X-Requested-With, Content-Type, Authorization',
      methods: 'GET, POST, PATCH, PUT, POST, DELETE, OPTIONS'
    }))
    
    app.use(session({
      secret : 'nodeauthsecret',
      resave: false,
     saveUninitialized: true,
    
    }));
    
    app.use(passport.initialize());
    app.use(passport.session());
    require('./config/passport')(passport);
    require('./config/passport-github')(passport);
    
    app.use(function(req, res, next) {
      res.locals.user = req.user; // This is the important line
      console.log(res.locals.user);
      next();
    });
    // app.use(function(req, res, next) {
    //   res.setHeader("Access-Control-Allow-Origin", "*");
    //   res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    // });
    
    app.use('/api/users', userRoute )
    
    app.use('/api/posts',  postRoute )
    
    app.listen(port, () => {
      console.log('[api][listen] http://localhost:' + port)
    })
    

    passport.js

    const BCRYPT_SALT_ROUNDS = 12;
    
    const passport = require('passport'),
    
      bcrypt = require('bcrypt'),
      JWTstrategy = require('passport-jwt').Strategy,
      ExtractJWT = require('passport-jwt').ExtractJwt,
      Sequelize = require('sequelize'),
      Op = Sequelize.Op;
    
    module.exports = function(passport, user) {
      const models = require( '../models/index');
      const localStrategy = require('passport-local').Strategy;
    // serialize session, only store user id in the session information
      passport.serializeUser(function(user, done) {
        done(null, user.id);
      });
    
      // from the user id, figure out who the user is...
      passport.deserializeUser(function(userId, done){
        models.User
          .find({ where: { id: userId } })
          .then(function(user){
            done(null, user);
          }).catch(function(err){
            done(err, null);
          });
      });
    
      passport.use(
        'register',
        new localStrategy(
          {
            usernameField: 'username',
            passwordField: 'password',
            passReqToCallback: true,
            session: false,
          },
          (req, username, password, done) => {
            try {
               models.User.findOne({
                where: {
                  [Op.or]: [
                    {
                      username: username,
                    },
                    { email: req.body.email },
                  ],
                },
              }).then(user => {
                if (user != null) {
                  console.log('username or email already taken');
                  return done(null, false, {
                    message: 'username or email already taken',
                  });
                } else {
                  bcrypt.hash(password, BCRYPT_SALT_ROUNDS).then(hashedPassword => {
                    models.User.create({
                      username: req.body.username,
                      password: hashedPassword,
                      email: req.body.email
                    }).then(user => {
                      console.log('user created');
                      return done(null, user);
                    });
                  });
                }
              });
            } catch (err) {
              done(err);
            }
          },
        ),
      );
    
    
    
    passport.use(
      'login',
      new localStrategy(
        {
          usernameField: 'username',
          passwordField: 'password',
          session: false
        },
        (username, password, done, req) => {
          try {
            models.User.findOne({
              where: {
                [Op.or]: [
                  {
                    username: username,
                  }
                ],
              },
            }).then(user => {
              if (user === null) {
                return done(null, false, { message: 'Username doesn\'t exist' });
    
              } else {
                bcrypt.compare(password, user.password).then(response => {
                  if (response !== true) {
                    console.log('passwords do not match');
                    return done(null, false, { message: 'passwords do not match' });
                  }
    
                  console.log('user found & authenticated');
                  // note the return needed with passport local - remove this return for passport JWT
                  return done(null, user);
                });
    
    
              }
            });
          } catch (err) {
            done(err);
          }
        },
      ),
    );
    
    const opts = {
      jwtFromRequest: ExtractJWT.fromAuthHeaderWithScheme('JWT'),
      secretOrKey: process.env.jwtsecret,
    };
    
    
    
    
    passport.use(
      'jwt',
      new JWTstrategy(opts, (jwt_payload, done) => {
        try {
           models.User.findOne({
            where: {
              username: jwt_payload._id,
            },
          }).then(user => {
            if (user) {
              console.log('user found in db in passport');
              // note the return removed with passport JWT - add this return for passport local
              done(null, user);
              // console.log(user);
            } else {
              console.log('user not found in db');
              done(null, false);
            }
          });
        } catch (err) {
          done(err);
        }
      }),
    );
    
    
    }
    
  • randal
    randal about 5 years
    nothing shows in the res.locals.user, it used to work but i changed the proxy set up on the react front end. its using a jwtFromRequest: ExtractJWT.fromAuthHeaderWithScheme('JWT')
  • randal
    randal about 5 years
    'Authorization' : '<type> <credentials>' do i leave it like that ?
  • randal
    randal about 5 years
    its using a jwtFromRequest: ExtractJWT.fromAuthHeaderWithScheme('JWT'), i will update code.
  • randal
    randal about 5 years
    my next question is how would i pass the token from express to react so that i can insert it next to Bearer ?
  • randal
    randal about 5 years
    so request.headers.authorization will fetch the jwt token ?, thank you for the help by the way :)
  • Manzurul Hoque Rumi
    Manzurul Hoque Rumi about 5 years
    You have to pass token from react to express and express will check the expire date and return the user with that token.
  • randal
    randal about 5 years
    i updated the code above, and i have it set up the opposite way. Im sorta confused, im going to work on this with your solution. Thank you.
  • Ahm.
    Ahm. about 5 years
    try now by calling ExtractJwt.fromAuthHeaderWithScheme() and then returning it for authentication in JWTstrategy
  • randal
    randal about 5 years
    ok let me try this out. i will provide full passport code, cause im sorta confused.
  • Manzurul Hoque Rumi
    Manzurul Hoque Rumi about 5 years
    I think you are doing wrong. Token should be sent from client to server. And your is saved in localStorage. Server will verify the token and send your required information.
  • Manzurul Hoque Rumi
    Manzurul Hoque Rumi about 5 years
    @randal Check now :-)
  • randal
    randal about 5 years
    ok, do i still have send the token to the headers, im still stuck on that.
  • Manzurul Hoque Rumi
    Manzurul Hoque Rumi about 5 years
    Yes, to get the user you have to send token with headers. axios.get('http://localhost:8000/api/dashboard/', { headers: {"Authorization" : Bearer ${localStorage.getItem('token')}} })
  • randal
    randal about 5 years
    yeah its still 401 unauthorized.
  • Manzurul Hoque Rumi
    Manzurul Hoque Rumi about 5 years
  • randal
    randal about 5 years
    where are you setting the token ?, im looking through your repo.
  • randal
    randal about 5 years
    i see it. let me give this a shot.
  • randal
    randal about 5 years
    I accepted this an answer, but i still have to make some extra code to get it to work. this is the closet solution possible, thank you for your effort.