React axios 401 unauthorized
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 })
randal
Updated on July 09, 2022Comments
-
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 of8000
.GET /api/users/user 401 2.167 ms - 59
Other get requests Do work. For example
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 about 5 yearsnothing 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 about 5 years
'Authorization' : '<type> <credentials>'
do i leave it like that ? -
randal about 5 yearsits using a
jwtFromRequest: ExtractJWT.fromAuthHeaderWithScheme('JWT'),
i will update code. -
randal about 5 yearsmy next question is how would i pass the token from express to react so that i can insert it next to Bearer ?
-
randal about 5 yearsso
request.headers.authorization
will fetch the jwt token ?, thank you for the help by the way :) -
Manzurul Hoque Rumi about 5 yearsYou have to pass token from react to express and express will check the expire date and return the user with that token.
-
randal about 5 yearsi 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. about 5 yearstry now by calling
ExtractJwt.fromAuthHeaderWithScheme()
and then returning it for authentication inJWTstrategy
-
randal about 5 yearsok let me try this out. i will provide full passport code, cause im sorta confused.
-
Manzurul Hoque Rumi about 5 yearsI 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 about 5 years@randal Check now :-)
-
randal about 5 yearsok, do i still have send the token to the headers, im still stuck on that.
-
Manzurul Hoque Rumi about 5 yearsYes, 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 about 5 yearsyeah its still 401 unauthorized.
-
Manzurul Hoque Rumi about 5 years
-
randal about 5 yearswhere are you setting the token ?, im looking through your repo.
-
randal about 5 yearsi see it. let me give this a shot.
-
randal about 5 yearsI 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.