Reputation: 105
I am trying to authenticate the nodejs api's using passport-jwt authentication strategy, but it always throws 401 unauthorized error. I tried various implementations but passport.authenticate function just doesn't seem to work.
Using below passport versions:
"passport": "^0.4.0",
"passport-jwt": "^4.0.0",
Please see my code below:
Tried below options:
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken()
jwtFromRequest: ExtractJwt.fromHeader('authorization')
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('Bearer')
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('jwt')
But not working.
Tried looking into passport-jwt 401 Unauthorized and other links for reference as well.
app.js file:
const express = require('express');
const bodyParser = require('body-parser');
const passport = require('passport');
const cors = require('cors');
const app = express();
const login = require('./routes/login');
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// app.use(passport.initialize());
app.use('/', login);
app.listen(8000, () => console.log('Server running on http://localhost:8000/'));
login.js file in route folder:
const express = require('express');
const router = express.Router();
const passport = require('passport');
const passportref = require('./../controllers/passport');
const loginController = require('./../controllers/loginController');
router.post('/putemailregistration',loginController.putEmailregistration);
router.get('/login', passportref.authenticate,loginController.verifyLogin);
module.exports = router;
Passport.js file:
const passport = require('passport');
const JWTStrategy = require("passport-jwt").Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const models = require('./../models');
const opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: 'incredible',
}
passport.use(new JWTStrategy(opts,async (payload, done) => {
try {
console.log(`inside jwt strategy func`);
const user = models.Userabout.findById({
where: { email: { [Op.eq]: payload.email } },
attributes: ['id', 'email', 'password'],
});
console.log(`value of user: ${user}`);
if (typeof user !== 'undefined' && user !== null) {
return done(null, user);
}
else {
return done(null, false);
}
} catch (err) {
done(err, false);
}
}));
module.exports = {
initialize: () => passport.initialize(),
authenticate: passport.authenticate("jwt", { session: false }),
};
loginController.js file:
const { Op } = require('sequelize');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const models = require('./../models');
const saltRounds = 10;
module.exports.putEmailregistration = async (req, res) => {
try {
console.log(`inside put email registration`);
if (req.body.email === null || req.body.password === null) {
res.sendStatus(400).json('no data');
} else {
const emailregister = await models.Userdata.create({
email: req.body.email,
password: bcrypt.hashSync(req.body.password,
bcrypt.genSaltSync(saltRounds)),
});
const tokenid = jwt.sign({
id: emailregister.id,
email: emailregister.email,
}, process.env.JWT_SECRETKEY,
{ expiresIn: 3600 });
res.json({ success: true, token: 'bearer ' + tokenid });
}
} catch (err) {
console.log(`error at put email registration: ${err}`);
}
}
module.exports.verifyLogin = (req, res) => {
console.log(`i managed to get here`);
// console.log(`user: ${req.user}`);
// res.send(req.user.email);
}
Upvotes: 4
Views: 7606
Reputation: 841
There seem to be many different problems which can lead to this issue. In my case, it was a wrong format of the public key – the key has to be in PEM format:
const opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyn2vP592Ju/iKXQW1DCrSTXyQXyo11Qed1SdzFWC+mRtdgioKibzYMBt2MfAJa6YoyrVNgOtGvK659MjHALtotPQGmis1VVvBeMFdfh+zyFJi8NPqgBTXz6bQfnu85dbxVAg95J+1Ud0m4IUXME1ElOyp1pi88+w0C6ErVcFCyEDS3uAajBY6vBIuPrlokbl6RDcvR9zX85s+R/s7JeP1XV/e8gbnYgZwxcn/6+7moHPDl4LqvVDKnDq9n4W6561s8zzw8EoAwwYXUC3ZPe2/3DcUCh+zTF2nOy8HiN808CzqLq1VeD13q9DgkAmBWFNSaXb6vK6RIQ9+zr2cwdXiwIDAQAB
-----END PUBLIC KEY-----`
};
For debugging, it helps to add a callback as the third parameter to the passport.authenticate()
Method:
passport.authenticate('jwt',
{ session: false },
(err, user, info, status) => { /* do some logging here */ })
Upvotes: 0
Reputation: 1012
In my case the error was calling done(null) instead of done(null, jwtPayload) which lead to 401s
passport.use(new JwtStrategy({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: secret,
}, function (jwtPayload, done) {
done(null, jwtPayload); // I was calling just done(null)
})).authenticate('jwt', { session: false })
Upvotes: 0
Reputation: 482
In my case, I was using expiresIn
value from the environment variable. The environment variable values will be of String
type and If we pass a string value to expiresIn
, it will be taken in milliseconds. So a value of 3600 was getting converted to 3 seconds and by the time I copy the token from the sign-in response to the auth header, it was getting expired.
https://www.npmjs.com/package/jsonwebtoken#usage
Upvotes: 1
Reputation: 41
To solve this you can manage it in your middle ware
function authorized(request, response, next) {
passport.authenticate('jwt', { session: false, }, async (error, token) => {
if (error || !token) {
response.status(401).json({ message: 'Unauthorized Message' });
}
try {
console.log('token',token)
const user = await User.findOne(
{_id: token._id}
);
request.user = user;
} catch (error) {
next(error);
}
next();
})(request, response, next);
}
router.get(
'/',
authorized,
trimRequest.all,
user.getItems
)
Upvotes: 2
Reputation: 224
Use
passport.use('jwt',new JWTStrategy({opts},verify_callback(){})
in passport.js
Upvotes: 0
Reputation: 105
After lot of debugging, i finally resolved the issue. Hope this might help someone
Upvotes: 2