How to add user's information on a JWT? - node.js

I'am using JWT to authenticate users but I want also to add some informations to the token like the username.
This is how I create the tokens after I've authenticated the user :
app.post('/authenticate', function(req, res){
User.findOne({
username: req.body.username
}, function(err, user){
if(!user){
console.log('Authentication failed. User not found');
}
else if(user){
if(user.password != req.body.password){
console.log('Authentication failed. Wrong password');
}
else{
var token = jwt.sign(user, app.get('secretWord'), {
expiresIn : 10800,
});
res.send({
token: token
});
}
}
})
});
How can I associate a username to the token? I tried :
var token = jwt.sign(user, app.get('secretWord'), {
expiresIn : 10800,
username : user.username
});
But that throws an error : "ValidationError: "username" is not allowed.

You can simply add details you want like this
var token = jwt.sign(user.name,user.email, app.get('secretWord'), {
expiresIn : 10800,
});
don't pass the user object in jwt.sign because it contains crucial information like password, session_tokens etc. so Sign only the information which is necessary like name, email, role, user_type etc. like above I have given the solution

The simplest solution would be to insert the username into jwt's payload as an independent variable.
However better practice is to use the user object to generate the token. With this approach you can easily find the user if you have a token taken that the token will contain information about user's properties. Check this link on how to do this easily:
https://scotch.io/tutorials/authenticate-a-node-js-api-with-json-web-tokens
You can skip straight to "Authenticating and Creating a Token", there's a good example on how to do this in node.js.

Related

How to send Bearer token to client and then call token from client

I have done a tutorial trying to get my head around JWT tokens. I seem to have got my head around the token creation as well as using the token to allow or disallow access to a route.
This all works great using postman, but in postman I enter the token under authorization. My question is:
1. how do I send the token to the client so it is saved on that client side.
2. How does the client return the token when they try to access a route?
I need to understand how this happens when NOT using postman. I am sure its pretty simple.
Do I just send
`res.header('Authorization', 'Bearer', + token);`
`res.header('Authorization', 'Bearer' + token);`
But can I send this with other stuff like a message / data etc?
Then when the user tries to access a protected route later, How do I access this header. IOW how is it stored client-side?
This is what I have thus far:
`//login route`
`app.post('/login', async function(req, res, next) {
const { name, password } = req.body;
if (name && password) {
let user = await getUser({ name: name });
if (!user) {
res.status(401).json({ message: 'No such user found' });
}
if (user.password === password) {
// from now on we'll identify the user by the id and the id is the
// only personalized value that goes into our token
let payload = { id: user.id };
let token = jwt.sign(payload, jwtOptions.secretOrKey);
res.json({ msg: 'ok', token: token });
} else {
res.status(401).json({ msg: 'Password is incorrect' });
}
}
});`
`// protected route
app.get('/protected', passport.authenticate('jwt', { session: false }), function(req, res) {
console.log('REQUEST HEADERS ON PROTECTED::',req.headers.authorization)
res.json('Success! You can now see this without a token.');
});`
The console.log under protected route gives me:
"REQUEST HEADERS ON PROTECTED:: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTU2NjI3NTczfQ.gAU2VzpUpXHpcgM6_n8gf7D-xLCS59tK6K2RIlIk-L4" but I gather this is because I used the authorization in postman.
I recently worked with jwt auth using react as my front end and hapi.js as backend. To save the token on the client side, you can use localstorage like this:
You have to save this on the user login component.
localStorage.setItem('token', res.data.token);
And then, to access this token on the protected router, use this :
let token = localStorage.getItem('token');
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
I hope this may help you to solve your problem on the client side.

node js jwt how to pass token to other routes to check logged user information later

I'm creating an application learn for my self. So at the moment i need to authenticate an user using with jsonwebtoken and i know how to create a token to authenticate a user. So actually i need to know how can i retrieve logged users's information later by using the token created by the user when logged into the system. i searched everywhere for a good answer but i couldn't find a good answer
apiRoutes.post('/authenticate', function(req, res) {
// find the user
User.findOne({
name: req.body.name
}, function(err, user) {
if (err) throw err;
if (!user) {
res.json({ success: false, message: 'Authentication failed. User not found.' });
} else if (user) {
// check if password matches
if (user.password != req.body.password) {
res.json({ success: false, message: 'Authentication failed. Wrong password.' });
} else {
// if user is found and password is right
// create a token
var token = jwt.sign(user, app.get('superSecret'));
// return the information including token as JSON
res.json({
success: true,
message: 'Enjoy your token!',
token: token
});
}
}
});
});
this is the user login and token creation process
and the below router i need to retrieve all the user information if the user logged into the system and created the token
apiRoutes.get('/users', function(req, res) {
if(!loggedinUser){
//throw err
}
else {
User.find({}, function(err, users) {
res.json(users);
});
});
}
so please help me to understand this and i hope you guys provide me a good answer for this question
thank you
Once your authorisation token is generated you need to send that token in all requests through client side.
On the the server side you need to implement a authentication middleware in this you will check the authentication token. and process that request further
check this link
How to use the middleware to check the authorization before entering each route in express?
Add User login token in to req.session.token then check it in jwt middle ware .

Setting Up Postman for API Testing When Using Passport Authorization

I am a bit confused while trying to get Postman to work when testing the API of my application. Namely, I am using Passport authentication; however, I do not know which type it defaults to or uses in my code. How can I figure this out and which type should I choose in Postman?
Here is the relevant Passport code:
var login = require('./login');
var signup = require('./signup');
var User = require('../models/user');
module.exports = function(passport, path, nodemailer, sesTransport, EmailTemplate, templateDir, template){
// Passport needs to be able to serialize and deserialize users to support persistent login sessions
passport.serializeUser(function(user, done) {
//console.log('serializing user: ');console.log(user);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
//console.log('deserializing user:',user);
done(err, user);
});
});
// Setting up Passport Strategies for Login and SignUp/Registration
login(passport);
signup(passport, path, nodemailer, sesTransport, EmailTemplate, templateDir, template);
}
Lastly, pretty much all of my API points only work when the user is logged in. How can I emulate the same behavior in Postman by saving the authorization credentials?
Edit:
Perhaps this code is relevant as well:
module.exports = function(passport){
passport.use('login', new LocalStrategy({
passReqToCallback : true,
usernameField: 'email',
passwordField: 'password'
},
function(req, username, password, done) {
// check in mongo if a user with username exists or not
User.findOne({ 'email' : username },
function(err, user) {
// In case of any error, return using the done method
if (err)
return done(err);
// Username does not exist, log the error and redirect back
if (!user){
console.log('User Not Found with username '+username);
return done(null, false, req.flash('message', 'User Not found.'));
}
// User exists but wrong password, log the error
if (!isValidPassword(user, password)){
console.log('Invalid Password');
return done(null, false, req.flash('message', 'Invalid Password')); // redirect back to login page
}
// User and password both match, return user from done method
// which will be treated like success
return done(null, user);
}
);
})
);
var isValidPassword = function(user, password){
return bCrypt.compareSync(password, user.password);
}
}
I don't have a code that runs local auth strategy but I think the following postman setup should work for you.
To request for an access token; assuming your endpoint is auth/local.
open up Postman
create a POST request
under authorization tab set "No Auth"
under body tab -> click on x-www-form-urlencoded
add a key named email and enter the user email
add a key named password and enter the associated secret for the email
See token request screenshot below:
The response will come back with an access_token.
To use the access_token simply create a HTTP request and in the HEADER tab, add the key Authorization followed by a value of "Bearer
See use token request screenshot:
I use this and it works fine in postman.
After getting response of access token
under the Authorization tab. select "Bearer Token" from "Type" drop-down. and Token with field will appear on right. enter the access token.
This works fine with Laravel REST APIs.
Check Screen Shot
Postman Auth Token passing
What I did is. First send the login request thru postman. If you look in the response you should see a cookies tab. Copy the value of the cookie
Postman Picture
When you want to check the "protected" route in the headers you need to choose cookie and in value paste the value you have copied before.
Cookie Header
when we use passport js it stores the user information using sessions, there is a bug in express-session. so by using cookie-session it is solved ( for me ) because it gives a header parameter cookie, which we can use in postman for testing.
when we are in the browser it automatically sets the cookies in the header but for the postman, we have manually do it.
we will get the cookie info form req in express ex:
which we can use in postman like :

Trying to authenticate a user, and process seems stuck

I'm following along in the MEAN machine book and in chapter 9 about Node authentication. I have routes for all users, get, post, put and delete working.
Setup the authenticate route below:
// route to authenticate a user (POST http://localhost:8615/api/authenticate)
apiRouter.post('/authenticate', function(req, res) {
// find the user
// select the name, username and password explicitly
User.findOne({
username: req.body.username
}).select('name username password').exec(function(err, user) {
console.log(user);
if (err) throw err;
// no user with that username was found
if (!user) {
res.json({ success: false, message: 'Authentication failed. User no found.'});
} else {
// if user is found and password is right
// create a token
var token = jwt.sign({
name: user.name,
username: user.username
}, superSecret, {
expiresInMinutes: 1440 // expires in 24 hours
});
}
});
});
My full server.js file here:
https://github.com/leongaban/awesome-test/blob/865714ade6b2f15ffcd8f1fc72ad0ad18836604b/server.js
I created a new user chris / supersecret
Then tried to authenticate him using Postman and it always hangs up :(
Any idea what could be causing it to get stuck?
You're not sending a response when the user is found and the password matches. You create the token but don't do anything (with it) afterwards.

Passing Trusted Client Information with oAuth2orize for the "Resource Owner Password Flow"

I am having some issues understanding how to implement the Resource Owners Password Flow with oAuth2rize and passport.js specifically with the transmission of the client_id and the client_secret so that i can do some checks on the client to ensure anything coming into this end point (/token) using the specific "password" grant type is specifically an official application and no others based on the id and secret.
When building out the solution i can get a token back, but that is before i have tried to do any validation on the client. When i try and access the client variable (posted to the end point) passed into the password exchange strategy i receive the user credentials (username, password) which based on documentation is expected but not what i need to achieve here.
I am at a loss to understand how i get the actual client credentials, i can see in the password function source code you can provide additional options to override the default assignment to req['user'] but does that mean i have to provide some sort of code to add to the req object?
I have setup some integration tests and here is how i am calling my endpoint (using SuperTest):
request('http://localhost:43862')
.post('/oauth/token')
.type('form')
.send({ grant_type: 'password' })
.send({ client_id: 'goodClient' })
.send({ client_secret: 'asecret' })
.send({ username: 'good#user.com' })
.send({ password: 'goodpassword' })
.expect(200, done);
For some reason i seem to be completely over thinking this but for some reason am completely stumped....
As expected it was an understanding issue where we were using a local strategy instead of the ClientPasswordStrategy with the user validation happening within the password exchange before issuing a token.
We are now using the ClientPasswordStrategy and within the exchange.password function we are calling and internal call to our user api to validate the user credentials and if ok then issuing the token.
passport.use(new ClientPasswordStrategy(
function(clientId, clientSecret, next){
Client.verify(clientId, clientSecret, function(err, verified){
if(!verified){
return next(null, false);
}
next(null, clientId);
});
}
));
passport.use(new BearerStrategy(
function(token, next) {
Token.getByToken(token, function(err, tokenObj){
if(err)
return next(err);
if(!tokenObj)
return next(null, false);
User.getByUsername(tokenObj.username, function(err, user){
return next(null, user, { scope: 'all' });
});
});
}
));

Resources