move to passport.js from key,email,client - node.js

In my app, there are 3 ways to auth. Google, Facebook, and local. I'm not using passport yet.
After the user auth, he choose a client (every user must have at least one client).
Then every API request contains 3 querystring parameters: email, key, client. Currently I'm manullay adding req.user and req.client to req object
I'm want to move to passport, because then the app will easily support twitter and linked signin.
Before I start other login method, I need to migrate the current app to passport.
My app currently not using sessions or cookies. all credentials data, saved in browser localStorage, and sent in each request. I don't want to change it.
The question is: How to make passport login using email, key, and client? how to make it add req.client and not only req.user.
I do not really understand where is the bet option to put my logic, and where to give passport the power.
Do I need to use passport.serializeUser? What to put in the route, and what to put in the app.use??

I would recommend a standards-based way to support cookie-less authentication. Check out: https://github.com/themikenicholson/passport-jwt
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
opts.secretOrKey = 'secret';
opts.issuer = "accounts.examplesoft.com";
opts.audience = "yoursite.net";
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
User.findOne({id: jwt_payload.sub}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false);
// or you could create a new account
}
});
}));

Related

How to create a GoogleStrategy stateless authentication using nodejs and passport.js?

I'm working on a project and I'm evaluating different way to authenticate my app. After trying Firebase and see that is not ok for me I decided to authenticate my app using passport.js.
I've created LocalStrategy, JwtStrategy, Google and Facebook Strategy but I am stuck on the Google one. What I am trying to do is get an access_token that will be passed back on my client and will be used in any future request.
I would like to create a stateless authentication because my client side will be a web app and in the future an Android app.
All the example that I found for GoogleStrategy is using passport.session() to store the logged in user in the session.
First question is: using passport.js for GoogleStrategy do I have to use mandatory the passport.session() ?
By docs GoogleStrategy return an accessToken and a refreshToken..but actually it doesn't!! The refreshToken is always undefined and the accessToken is something different from a jwt token, I thought it was the authorization_code that need to be exchanged with an access_token, but I'm not sure because if I try to exchange that token with an access token I receive an error. Any ideas of what accessToken on GoogleStrategy is?
Second question: is there any way to get jwt token from google? if no, assuming google strategy successful login... should I generate inside my GoogleStrategy my own token using jsonwebtoken library and pass it back on my client?
This is an example of what I'am saying:
passport.use(
new GoogleStrategy(
googleConfig,
async (accessToken, refreshToken, profile, done) => {
// accessToken..contains something different from a JWT token.
// refreshToken..is undefined!!
try {
const existingUser = await User.findOne({ "email": profile.emails[0].value});
if (existingUser) {
// 1. update providers adding the google if not present on user record
.....
// 2. generate access_token and refresh_token
const token = user.generateAccessToken();
const refreshToken = user.generateRefreshToken();
return done(null, {token, refreshToken});
}
// Create a new user on MongoDb.
// generate tokens and returns...
done(null, {....here goes generated tokens});
} catch (error) {
done(error, false);
}
}
)
);
// The generate token function inside my User model
conts jwt = require('jsonwebtoken');
userSchema.methods.generateAccessToken = function () { // this is just an example.
return jwt.sign({
id: this._id,
email: this.email
}, jwtSecret, { expiresIn: "15m" })
}
If you have any advice it will be appreciated.
Thank you all!

Attach the current user to the request with bearer strategy in passport azure ad

I have a NodeJS API server using express and passport for authentication. I am using the passport azure ad bearer strategy for authentication with Microsoft Azure AD. In the examples provided in the documentation(https://github.com/Azure-Samples/active-directory-node-webapi/blob/master/node-server/app.js#L50), the owner (currentUser) is a javascript variable defined globally. How do I attach the user to the request so that I can do something like
server.post('/user', passport.authenticate('oauth-bearer', {
session: false
}), function(req, res, next){
console.log(`I am the current user ${req.user}`);
});
From the example mentioned in the OIDC strategy, I have seen a deserializeUser and serializeUser function that would allow the user ID to be stored in the session, However, in the bearer strategy, we do not have any sessions maintained as authentication will be performed for every incoming request.
This may be a gap in my understanding. I have gone through the documentation for the individual libraries. Please help me if there is a way this can be done
Following is the sample code via which you can embedd the yser object to request object . Thus when you will do ${req.user} in post callback you will get the user object
const BearerStrategy = require('passport-azure-ad').BearerStrategy;
var bearerStrategy = new BearerStrategy(options,
function(token, done) {
findById(token.oid, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
// "Auto-registration"
return done(null, token);
}
const owner = token.oid;
return done(null, user, token);
});
}
);

Meteor client login using LDAP and JWT

I have a big CMS built with Meteor that until now used basic-auth to login as we didn't have more than one editor. However, more people will start working with it, so I am trying to create a login functionality through LDAP so any authorised employee can login with their username/password
I tried to do my best given poor documentation of WebApp.connectHandlers and the lack of content integrating passport with Meteor. I based my LDAP login code on express examples (assuming WebApp.connectHandlers.use() was the Meteor equivalent of Express' app.use())
The login part works, that is to query and verify the user through LDAP.
However I cannot figure how to identify the logged-in user when they make a Meteor.call( ).
What I have in mind at the moment is to send a JWT token back to the authenticated user, store it in a cookie or something, and whenever a Meteor.call( ) is made, the client passes the token as a parameter. Then I would be able to identify the caller and can for example store the username in the database as the person who made a certain change.
Good to mention that I am trying to avoid using Meteor's accounts system as the requirement is to use LDAP without creating any extra tables (that's why the complication of using those several packages together).
Here's my code, with working login but no idea how to pass back the token to the user.
Maybe my whole JWT logic is wrong, I would appreciate any help/suggestions.
var basicAuth = require("basic-auth");
var passport = require("passport");
var bodyParser = require("body-parser");
var LdapStrategy = require("passport-ldapauth");
var jwt = require("jsonwebtoken");
// Example of the real LDAP config
var OPTS = {
server: {
url: "ldap://address:port",
bindDN: "admin",
bindCredentials: "adminPassword",
searchBase: "OU=Users,DC=example,DC=com",
searchFilter: "(&(objectClass=user)(sAMAccountName={{username}}))"
},
credentialsLookup: basicAuth
};
Meteor.startup(() => {
passport.use(new LdapStrategy(OPTS));
WebApp.connectHandlers.use(bodyParser.json());
WebApp.connectHandlers.use(bodyParser.urlencoded({ extended: false }));
WebApp.connectHandlers.use(passport.initialize());
WebApp.connectHandlers.use(
"/",
(req, res, next) => {
// This part before the else is to trigger a basic auth popup to enter username/password
let credentials = basicAuth(req);
if (!credentials) {
res.statusCode = 401;
res.setHeader("WWW-Authenticate", "Basic");
res.end("Access denied");
} else {
passport.authenticate(
"ldapauth",
{
session: false
},
function(err, user, info) {
if (err) {
return next(err);
}
if (user) {
var token = jwt.sign(
{ username: user.sAMAccountName },
"someSecretString"
);
console.log("token", token);
next();
}
}
)(req, res, next);
}
},
function(req, res) {
console.log("debug point#2");
res.send({ status: "ok" });
}
);
}

Passport-jwt authenticate not working well with node-jwt-simple

I'm using passport-jwt to authenticate some routes and I'm creating my jwts with node-jwt-simple/jwt-simple but facing some difficulties cause it looks like my passport-jwt authenticate middleware is not being called at all.
Here is my
passport-jwt-strategy
const jwtOpts = {
jwtFromRequest: ExtractJwt.fromHeader('Authorization'),
secretOrKey: secret,
};
passport.use(new jwtStrategy(jwtOpts, (payload, done) => {
console.log('payload ', payload.sub);
User.findById(payload.sub, (err, user) => {
if(err) { return done(err); }
if(!user) { console.log('didnt find!'); return done(null, false); }
done(null, user);
});
}));
which i'm then integrating it over here.
routes file
router.get('/success',
passport.authenticate('jwt', {session: false}),
async (ctx, next) => ctx.body = await "success!");
Here is also the way I make my jwt.
function tokenForUser(user) {
const timeStamp = new Date().getTime;
return jwt.encode({sub: user._id, iat: timeStamp}, secret);
}
//- Later in signup process
userToSave.save(async(err, user) => {
if(err) { return next(err); }
const token = await tokenForUser(user);
next(token);
});
//- If this helps, here is how my secret file looks like.
const secret = "JKAha23ja1ddHdjjf31";
export default secret;
Problem comes, when I hit that route i only get Unauthorized and in the console nothing gets logged out not even the 'payload' key I specified first.
I should also say that I have the token at ctx.request.get('Authorization') (Koa based) i think it's something like req.header('Authorization') with express in all routes.
Also The exact express based problem can be found on the github issues of node-jwt-simple here incase there is any problem with my code samples.
Thank you.
After I wrapped my head right i knew that this has been my horrible understanding of how the whole authentification process works.
When I decoded the token from ctx.get('Authorization') I got a different _id than the one stored in the db Because I had hardcoded Authorization header in postman and thought "If I ctx.set('Authorization', token); It will replace the one I hardcoded on postman".
Less did I think that this jwt will be included in a header of requests when I make http calls on front end.
I naively thought jwts are passed directly from the server to the browser (Something like how render works) and Not from the server to an ajax process which later embeds it in request made which is the correct way.
The whole code is awesome, except now I have to just pass the token ctx.body = token; after I created it when I signed up.
Thank You.

How to do Authentication with Node.js and MEAN stack?

I am currently working on a text based game with a small team of developers. The game requires login and we are using the MEAN (MongoDB, Express, Angular, Node) Stack for the application codebase, however i am stuck on authentication, as a rails developer i am used to being able to drop in a gem and use the helpers available.
has anybody has any experience with MEAN and Authentication?
the MEAN stack by linnovate uses Passport.js for its authentication. Passport uses different strategies for authentication. One of these strategies is a username and password pair, which they call LocalStrategy.
Here is one of the samples from the Passportjs-Local Github Examples Page
Step 1: Require Passport
First you require the module after doing npm install passport
var passport = require('passport');
Step 2: Configure 'Verify' Function
Use the LocalStrategy within Passport. Strategies in passport require a verify function, which accept credentials (in this case, a username and password), and invoke a callback with a user object. In the real world, this would query a database; however, in this example we are using a baked-in set of users.
passport.use(new LocalStrategy(
function(username, password, done) {
// Find the user by username. If there is no user with the given
// username, or the password is not correct, set the user to `false` to
// indicate failure and set a flash message. Otherwise, return the
// authenticated `user`.
findByUsername(username, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Unknown user ' + username });
}
if (user.password != password) {
return done(null, false, { message: 'Invalid password' });
}
return done(null, user);
})
});
}
));
Step 3: Initialize Passport on app
You need to tell Express that you will be using passport and that it will be managing sessions for you. This is done by using the app.use() during app configuration.
app.use(passport.initialize());
app.use(passport.session());
Step 4: Configure Middleware on the login URI
Next we need to create a method that will accept when a user tries to login to the app using by POST-ing to a specific URI. It will look like this.
// POST /login
// Use passport.authenticate() as route middleware to authenticate the
// request. If authentication fails, the user will be redirected back to the
// login page. Otherwise, the primary route function function will be called,
// which, in this example, will redirect the user to the home page.
//
// curl -v -d "username=bob&password=secret" http://127.0.0.1:3000/login
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }),
function(req, res) {
res.redirect('/');
});
Step 5: Set up Sessions
You may have to create your own serialization for User objects that are being stored in the sessions. That is done with the following
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing.
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
findById(id, function (err, user) {
done(err, user);
});
});
You can have a look at http://meanjs.org/
They have a very solid integration of passport.js strategies.
Especally useful is the implementation of Salt and Crypto-Technies to make the integration safe. Search for Salz within the repo.
See
https://github.com/meanjs/mean/blob/master/modules/users/server/config/strategies/local.js
For serialization and deserialization.
Or if you'd prefer a custom implementation, I recently posted a complete MEAN Stack User Registration and Login Example
Here's the snippet from the user service that handles authentication:
function authenticate(username, password) {
var deferred = Q.defer();
usersDb.findOne({ username: username }, function (err, user) {
if (err) deferred.reject(err);
if (user && bcrypt.compareSync(password, user.hash)) {
// authentication successful
deferred.resolve(jwt.sign({ sub: user._id }, config.secret));
} else {
// authentication failed
deferred.resolve();
}
});
return deferred.promise;
}
Or use mean.io which has user management out of the box.

Resources