J'obtiens une erreur 401 lorsque j'essaie d'authentifier un utilisateur. Juste pour donner du contexte, React utilise un serveur Express et utilise Passport pour l'authentification. React a un port de 8001
, et le serveur Express a le port de 8000
.
GET/api/users/user 401 2,167 ms - 59
Les autres requêtes get fonctionnent. Par exemple
Réagir
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/utilisateur
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
});
}
});
Fichier 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);
}
}),
);
}
Vous êtes confronté à cela car votre req.user
Est vide, c'est pourquoi il va à la déclaration else
et renvoie Unauthorized
que vous retournez.
Vérifiez votre console de serveur si elle imprime quelque chose console.log(res.locals.user);
Envoyez votre auth token
Avec des en-têtes comme celui-ci
headers : {
'Content-Type' : 'application/json',
'Accept' : 'application/json',
'Authorization' : 'Bearer <token_here>'
}
Mise à jour
Votre demande renverra toujours 401 unauthorized
.
https://github.com/manjurulhoque/nodejs-ecommerce-api/blob/master/routes/users.js#L105
Vérifiez mon code. Pour vous connecter, vous devez utiliser
passport.authenticate('jwt', { session: false })
Je pense que vous devez définir le Authorization
dans vos en-têtes, comme mentionné dans MDN
L'en-tête de demande d'autorisation HTTP contient les informations d'identification pour authentifier un agent utilisateur auprès d'un serveur, généralement après que le serveur a répondu avec un
401 Unauthorized status
et l'en-tête WWW-Authenticate.
let ExtractJwt = passportJWT.ExtractJwt;
let Strategy = passportJWT.Strategy;
let opts = {}
opts.secretOrKey= cfg.jwtSecret
opts.jwtFromRequest= ExtractJwt.fromAuthHeaderWithScheme(cfg.authScheme)
new JWTstrategy(
...
return {
initialize: function() {
return passport.initialize();
},
authenticate: function() {
return passport.authenticate(cfg.authScheme, cfg.jwtSession);
}
};
)