I am trying to implement sign-in with google and passport but I am running into a bit of a problem. I successfully authenticate with google, but my data isn't being passed to the front end. I Haven't changed anything from the original code except for the URI and necessary client id and secret. Can anyone tell me what I am missing?
var express = require( 'express' )
, app = express()
, server = require( 'http' ).createServer( app )
, passport = require( 'passport' )
, util = require( 'util' )
, bodyParser = require( 'body-parser' )
, cookieParser = require( 'cookie-parser' )
, session = require( 'express-session' )
, RedisStore = require( 'connect-redis' )( session )
, GoogleStrategy = require( 'passport-google-oauth2' ).Strategy;
// API Access link for creating client ID and secret:
// https://code.google.com/apis/console/
var GOOGLE_CLIENT_ID = "307841191614-1shiak514mrjugtbon3dm2if8hbhnvdv.apps.googleusercontent.com"
, GOOGLE_CLIENT_SECRET = "fgViegEgHWuoc1X-p63iPmpF";
// 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. However, since this example does not
// have a database of user records, the complete Google profile is
// serialized and deserialized.
passport.serializeUser(function(user, done) {
done(null, user);
console.log("User: "+ user.displayName); // If there is a persistent session, the console logs out the displayName
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
// Use the GoogleStrategy within Passport.
// Strategies in Passport require a `verify` function, which accept
// credentials (in this case, an accessToken, refreshToken, and Google
// profile), and invoke a callback with a user object.
passport.use(new GoogleStrategy({
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
//NOTE :
//Carefull ! and avoid usage of Private IP, otherwise you will get the device_id device_name issue for Private IP during authentication
//The workaround is to set up thru the google cloud console a fully qualified domain name such as http://mydomain:3000/
//then edit your /etc/hosts local file to point on your private IP.
//Also both sign-in button + callbackURL has to be share the same url, otherwise two cookies will be created and lead to lost your session
//if you use it.
callbackURL: "http://127.0.0.1:3000/oauth2callback",
passReqToCallback : true
},
function(request, accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
// To keep the example simple, the user's Google profile is returned to
// represent the logged-in user. In a typical application, you would want
// to associate the Google account with a user record in your database,
// and return that user instead.
console.log(profile); //logs google profile successfully
return done(null, profile);
});
}
));
// configure Express
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use( express.static(__dirname + '/public'));
app.use( cookieParser());
app.use( bodyParser.json());
app.use( bodyParser.urlencoded({
extended: true
}));
app.use( session({
secret: 'cookie_secret',
name: 'kaas',
store: new RedisStore({
host: '127.0.0.1',
port: 6379
}),
proxy: true,
resave: true,
saveUninitialized: true
}));
app.use( passport.initialize());
app.use( passport.session());
/*
===
===
===
Here is where the data is not being read.
*/
app.get('/', function(req, res){
res.render('index', { user: req.user });
console.log(req.user); //Output: undefined
});
app.get('/account', ensureAuthenticated, function(req, res){
res.render('account', { user: req.user });
});
app.get('/login', function(req, res){
res.render('login', { user: req.user });
});
// GET /auth/google
// Use passport.authenticate() as route middleware to authenticate the
// request. The first step in Google authentication will involve
// redirecting the user to google.com. After authorization, Google
// will redirect the user back to this application at /auth/google/callback
app.get('/auth/google', passport.authenticate('google', { scope: [
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.profile.emails.read']
}));
// GET /auth/google/callback
// 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.
app.get( '/oauth2callback',
passport.authenticate( 'google', {
successRedirect: '/',
failureRedirect: '/login'
}));
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
server.listen( 3000 );
// Simple route middleware to ensure user is authenticated.
// Use this route middleware on any resource that needs to be protected. If
// the request is authenticated (typically via a persistent login session),
// the request will proceed. Otherwise, the user will be redirected to the
// login page.
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/login');
}
`
Here is the simple layout that doesn't seem to be receiving any data.
<% if (!user) { %>
<h2>Welcome! Please log in.</h2>
<% } else { %>
<h2>Hello, <%= user.displayName %>.</h2>
<% } %>
Your code works, I just used same example on my app.
I had the same problem and I realized that I'm not using a valid account in my tests.
This API retrieves data from Google+ profile. Are you using a valid Google account with linked Google+ profile to authenticate?
Related
Using passport.js local strategy I am trying to use the req.user to obtain current user id so that I can store recipes in the database with the users id. The problem seems to be around the deserialization part of the passport.js file I have in my config file in my app. Whenever I hit the /api/saveRecipe route for some reason it gets deserialized and the req user is then no longer available.
Notes: I am authenticating on my backend server using react on the front end.
Below is my server.js file
Problem: req.user is available after calling passport.authenticate('local') but once api/saveRecipe route is hit req.user is no longer available.
After researching this subject on S.O. it appears that it most often has to do with order in the server file setup but i have looked and reviewed and i believe my setup correct...
const express = require("express");
const bodyParser = require("body-parser");
const session = require("express-session");
const routes = require("./routes");
// Requiring passport as we've configured it
let passport = require("./config/passport");
const sequelize = require("sequelize");
// const routes = require("./routes");
const app = express();
var db = require("./models");
const PORT = process.env.PORT || 3001;
// Define middleware here
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
// passport stuff
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static("public"));
// We need to use sessions to keep track of our user's login status
// app.use(cookieParser('cookit'));
app.use(
session({
secret: "cookit",
name: "cookit_Cookie"
})
);
app.use(passport.initialize());
app.use(passport.session());
// Serve up static assets (usually on heroku)
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/public"));
}
// the view files are JavaScript files, hence the extension
app.set('view engine', 'js');
// the directory containing the view files
app.set('pages', './');
// Add routes, both API and view
app.use(routes);
// Syncing our database and logging a message to the user upon success
db.connection.sync().then(function() {
console.log("\nDB connected\n")
// Start the API server
app.listen(PORT, function() {
console.log(`🌎 ==> API Server now listening on PORT ${PORT}!`);
});
});
module.exports = app;
my passport.js code
//we import passport packages required for authentication
var passport = require("passport");
var LocalStrategy = require("passport-local").Strategy;
//
//We will need the models folder to check passport against
var db = require("../models");
// Telling passport we want to use a Local Strategy. In other words, we want login with a username/email and password
passport.use(
new LocalStrategy(
// Our user will sign in using an email, rather than a "username"
{
usernameField: "email",
passwordField: "password",
passReqToCallback: true
},
function(req, username, password, done) {
// console.log(`loggin in with email: ${username} \n and password: ${password}`)
// When a user tries to sign in this code runs
db.User.findOne({
where: {
email: username
}
}).then(function(dbUser) {
// console.log(dbUser)
// If there's no user with the given email
if (!dbUser) {
return done(null, false, {
message: "Incorrect email."
});
}
// If there is a user with the given email, but the password the user gives us is incorrect
else if (!dbUser.validPassword(password)) {
return done(null, false, {
message: "Incorrect password."
});
}
// If none of the above, return the user
return done(null, dbUser);
});
}
)
);
// serialize determines what to store in the session data so we are storing email, ID and firstName
passport.serializeUser(function(user, done) {
console.log(`\n\n serializing ${user.id}\n`)
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log(`\n\n DEserializing ${id}\n`)
db.User.findOne({where: {id:id}}, function(err, user) {
done(err, user);
});
});
// Exporting our configured passport
module.exports = passport;
const router = require("express").Router();
const controller = require("../../controllers/controller.js");
const passport = require("../../config/passport");
router.post(
"/login",
passport.authenticate("local", { failureRedirect: "/login" }),
function(req, res) {
console.log(`req body -${req.body}`);
res.json({
message: "user authenticated",
});
}
);
router.post("/saveRecipe", (req, res) => {
console.log(req.user)
if (req.isAuthenticated()) {
controller.saveRecipe;
} else {
res.json({ message: "user not signed in" });
}
});
module.exports = router;
The problem is in your router.post('login'). Try changing it to something like this:
app.post('/login', passport.authenticate('local-login', {
successRedirect: '/profile',
failureRedirect: '/login/failed'})
)
This will correctly set the req.user in your next requests!
I'm trying to add auth0 to my web app, I've followed their tutorials and other tutorials on the web, including creating account/client and everything else, but I keep getting the usual white page loading screen and after several minutes I receive this error:
ERR_EMPTY_RESPONSE
These are parts of my code:
app.js
...
var cookieParser = require('cookie-parser');
var session = require('express-session');
var passport = require('passport');
var Auth0Strategy = require('passport-auth0');
...
// Configure Passport to use Auth0
var strategy = new Auth0Strategy(
{
domain: process.env.AUTH0_DOMAIN,
clientID: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
callbackURL: process.env.AUTH0_CALLBACK_URL
},
(accessToken, refreshToken, extraParams, profile, done) => {
return done(null, profile);
}
);
passport.use(strategy);
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
...
app.use(cookieParser());
app.use(
session(
{
secret: uuid(),
resave: false,
saveUninitialized: false
}
)
);
app.use(passport.initialize());
app.use(passport.session());
...
app.get('/', routes.index);
app.get('/home', routes.home);
...
http.createServer(app).listen(app.get('port'), function(){
console.log('Server listening on port: ' + app.get('port'));
});
module.exports = app;
index.js
exports.home = function(req, res){
res.render('home', { title: ' homepage ' });
};
exports.index = function(req, res){
var express = require('express');
var passport = require('passport');
var router = express.Router();
var env = {
AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID,
AUTH0_DOMAIN: process.env.AUTH0_DOMAIN,
AUTH0_CALLBACK_URL: process.env.AUTH0_CALLBACK_URL
};
// GET home page.
router.get('/', function(req, res, next) {
res.render('home', { title: ' homepage ' });
});
// Perform the login
router.get(
'/login',
passport.authenticate('auth0', {
clientID: env.AUTH0_CLIENT_ID,
domain: env.AUTH0_DOMAIN,
redirectUri: env.AUTH0_CALLBACK_URL,
audience: 'https://' + env.AUTH0_DOMAIN + '/userinfo',
responseType: 'code',
scope: 'openid'
}),
function(req, res) {
res.redirect('/');
}
);
// Perform session logout and redirect to homepage
router.get('/logout', (req, res) => {
req.logout();
res.redirect('/');
});
// Perform the final stage of authentication and redirect to '/home'
router.get(
'/callback',
passport.authenticate('auth0', {
failureRedirect: '/'
}),
function(req, res) {
res.redirect(req.session.returnTo || '/home');
}
);
}
There are some parts that are not clear to me or on which I would like to have a confirmation:
1) the callback URL must be my homepage (180.180.180.180/home) or the real first page (180.180.180.180)? Which one should be included in the auth0 dashboard?
2) In the router, should I also specify the / login and / logout fields or should these be managed directly by the auth0 API?
Sorry for my ignorance but it's days I have this problem, I do not understand if it's an authorization error with the auth0 account or something else.
I have the credentials in a .env file, but they should not be the problem, as I can access other data in them to connect to my MySQL database.
As per the documentation of auth0 The callback URL is not necessarily the same URL to which you want users redirected after authentication.
redirect_uri field is used as a callback URL. Auth0 invokes callback URLs after the authentication process and are where your application gets routed.
You can redirect the user to a non callback URL after authenticating the user and storing the same url in web storage.
On app.get(/login)...>authenticated>>landing page>>stores the access tokens
So post authentication it should login to your landing page (home).
On app.get(/logout), you can clear the access tokens or make it available for desired time and let it get expired after certain time.
I have read everything on the argument but still cannot understand it. The documentation on the Passport Js web site is very vague.
I am using Passport JS with the passport-ldapauth Strategy. I do not have a Database. I obviously don't want to hit the LDAP server on each request. I would like to authenticate the user the first time on the POST /login route using the passport strategy with LDAP, store the user in the session and on each subsequent requests I just want to check if the user is already logged in.
I am trying to use the session but I cannot understand how to use Passport + session with the serialize/deserialize flow. Every example I checked use a User.findOne in the deserializeUser function.
As of now I disabled the use of the session for Passport and I am using a custom middleware where I check if req.session.user != null. If that's the case the user is already logged in and I hit next(). Otherwise redirect to login.
Here is some code (for sake of simplicity I deleted the code not related to the question):
Passport configuration:
var express = require('express'),
session = require('express-session'),
passport = require('passport'),
LdapStrategy = require('passport-ldapauth');
var app = express();
var LdapStrategyOptions = {
server: {
url: '<url>',
bindDN: '<dn>',
bindCredentials: "<pwd>",
searchBase: '<searchBase>',
searchFilter: '<filter>'
}
};
passport.use(new LdapStrategy(LdapStrategyOptions));
app.use(cookieParser());
app.use(session({
store: new LokiStore({autosave: false}),
resave: false,
saveUninitialized: false
secret: env.get("SESSION_SECRET")
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(passport.initialize());
Routes:
// LOGIN ROUTE
app.get('/login',
function(req, res) {
res.render('login');
});
// LOGIN HANDLER ROUTE
app.post('/login',
passport.authenticate('ldapauth', { session: false }),
function(req, res) {
req.session.userId = req.user.cn;
req.session.user = {
"userId": req.user.cn,
"displayName": req.user.displayName
};
res.redirect('/');
});
// LOGOUT ROUTE
app.get('/logout',
function(req, res) {
req.session.destroy(function(err) {
req.logout();
res.redirect('/');
});
});
// HOME ROUTE
app.get('/', isLoggedIn, function(req, res) {
res.render('home');
});
IsLoggedIn Middleware:
var isLoggedIn = function(req, res, next) {
if (req.session.user != null){
console.log("is auth ok '" + req.session.user.userId +"'");
return next();
}
console.log("redirect to auth/login");
res.redirect('/auth/login');
}
What am I missing? Is there any security fault in my setup?
Any help is appreciated.
From passportjs docs:
In a typical web application, the credentials used to authenticate a user will only be transmitted during the login request. If authentication succeeds, a session will be established and maintained via a cookie set in the user's browser.
Each subsequent request will not contain credentials, but rather the unique cookie that identifies the session. In order to support login sessions, Passport will serialize and deserialize user instances to and from the session.
Basically serializeUser is supposed to return a unique user identifier so you can deserializeUser back into JSON later.
So for your implementation you should probably do something along these lines:
DISCLAIMER: I have no experience with LDAP.
passport.serializeUser(function(user, done) {
//We can identify the user uniquely by the CN,
//so we only serialize this into the session token.
done(null, user.cn);
});
passport.deserializeUser(function(cn, done) {
//Directly query LDAP.
//I'm not sure passport caches the result (only calls deserializeUser for new sessions)
//but worst case you can cache the result yourself.
somehowLoadUserFromLDAPByCN(cn, function(err, user) {
done(err, {
userId: user.cn,
displayName: user.displayName
});
});
});
If you only need an id and a display name, it's totally fine to keep them in session. You should only load the full user profile when you need more fields.
I am novice to Node passport authentication. I completely write an example of passport authentication as below:
var express = require('express');
var passport = require('passport');
var passportLocal = require('passport-local');
/*
Since express doesn't support sessions by
default you need following middlewares.
*/
// For storing session ID in browser
var cookieParser = require('cookie-parser');
// For rendering credentials from request bodies
var bodyParser = require('body-parser');
/*
For server side storage of session information.
All these session information is in server memory.
If the machine app reboot all sessions infromation
will disapear. The information coming with request
, thanks to cookies, with the session information
stored in the server used in deserializing the users.
Be careful properly handle session information
in server farms, round robbining and load balancing etc.
But it is easy to configure express-session middleware
to use external storage. In this case we use local machine.
*/
var expressSession = require('express-session');
var app = express();
app.set('view engine', 'ejs');
// For sessions. Need before Passport middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(expressSession({
// This is the secret used to sign the session ID cookie.
secret: process.env.SESSION_SECRET || 'd7n5ihsxx9by8ydt',
resave: false,
saveUninitialized: false
}));
// Passport need 2 middlewares
app.use(passport.initialize());
app.use(passport.session());
/*
Strategies need to be told how to veryfy username and password
that is inside authorization header that is client is goint to send.
*/
function verifyCredentials(username, password, done) {
/*
Use crypto.pbkdf2(password, salt, iterations, keylen[, digest], callback)
For the real app.
*/
if (username === password) {
/*
done() first argument is Error
Second argument 'user' is any object required for your business logic.
But make it as much as smaller for fast serializing and deserializing.
*/
done(null, {
id : 123,
name: username,
role: 'Admin',
catogery : 'Operator'
});
} else {
done(null, null);
}
};
/*
Now we have to configure passport. Call the local strategy with
single function function(username, password, done) where done is callback
funciton.
*/
passport.use(new passportLocal.Strategy(verifyCredentials));
/*
passport.serializeUser serializes the 'user' object.
The callback function done, need a small piece of
'user' object which is required in deserializing.
In following case 'user.id' is saved to session
req.session.passport.user = {id:'..'}
*/
passport.serializeUser(function(user, done) {
done(null, user.id);
});
/*
In deserialize function you provide in first argument of
deserialize function that same key of user object that was
given to done function in serialize call. So your whole object is
retrieved with help of that key. that key here is id.
In deSerialize function that key is matched with in
memory array / database or any data resource.
*/
passport.deserializeUser(function(id, done){
/*
Query database or cache here! Example
User.findById(id, function(err, user) {
done(err, user);
});
*/
done(null, {
id : id,
name: id,
role: 'Admin',
catogery : 'Operator'
});
});
/*
Middleware for API's. 3rd party middlewares are available
to download and install if you want. Middleware is
nothing but a simple function with the following format.
'next' is callback function which is used to pass the request
to the next middleware inline.
*/
function ensureAuthenticated(req, res, next){
if(req.isAuthenticated()){
next();
} else {
res.status(403).json( {msg: '403 Forbidden'} );
}
}
app.get('/', function(req, res) {
res.render('index', {
/*
Express doesn't have isAuthenticated for req.
But passport add it to req. Also the 'user' object
added in done() callback is available through req.
*/
isAuthenticated : req.isAuthenticated(),
user : req.user
});
});
app.get('/login', function(req, res) {
res.render('login');
});
app.get('/logout', function(req, res) {
//Passport add logout method to request object
req.logout();
res.redirect('/');
});
/*
In this end point, the middleware passport.authenticate('local') is called.
passport.authenticate('local') returns a functon similar to ensureAuthenticated.
*/
app.post('/login', passport.authenticate('local'), function(req, res) {
res.redirect('/');
});
/*
Second endpoint for API's. The endpoint is authenticated
with a middleware which is between URI and function.
*/
app.get('/api/data', passport.authenticate('local'), function(req, res) {
res.json([
{name: 'My'},
{name: 'Kumara'}
]);
});
app.get('/api/data/me', function(req, res) {
res.json([
{name: 'My'},
{name: 'Kumara'}
]);
});
var port = process.env.PORT || 3000;
app.listen(port, function() {
console.log('Server is running on Port : ' + port);
})
My question:
I have two URI's:
/api/data
/api/data/me
I assumed that since I have authenticated /api/data it will automatically authenticate /api/data/me since /api/data part is already authenticated, /api/data/me is like a child of /api/data. But it's not. Does this mean do I have to authenticate each and every API's?
If not, how can I group set of API's in a single strategy?
A wildcard could be used to match everything under a certain path. For example:
app.get('/api/data/*', passport.authenticate('local'), function(req, res, next) {
next(); // call next matching route
});
app.get('/api/data/me', function(req, res) {
res.json([
{name: 'My'},
{name: 'Kumara'}
]);
});
This enables the passport middleware for all requests under /api/data/ so that the user will need to authenticate using the passport local strategy. Logic for individual endpoints under /api/data/ can then be implemented without including the passport middleware.
There's more information about express route matching on the user guide. http://expressjs.com/en/guide/routing.html
I'm using Passport.js to login a user with username and password. I'm essentially using the sample code from the Passport site. Here are the relevant parts (I think) of my code:
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login/fail', failureFlash: false }),
function(req, res) {
// Successful login
//console.log("Login successful.");
// I CAN ACCESS req.user here
});
This seems to login correctly. However, I would like to be able to access the login user's information in other parts of the code, such as:
app.get('/test', function(req, res){
// How can I get the user's login info here?
console.log(req.user); // <------ this outputs undefined
});
I have checked other questions on SO, but I'm not sure what I'm doing wrong here. Thank you!
Late to the party but found this unanswered after googling the answer myself.
Inside the request will be a req.user object that you can work withr.
Routes like so:
app.get('/api/portfolio', passport.authenticate('jwt', { session: false }), stocks.buy);
Controller like this:
buy: function(req, res) {
console.log(req.body);
//res.json({lel: req.user._id});
res.json({lel: req.user});
}
In reference to the Passport documentation, the user object is contained in req.user. See below.
app.post('/login',
passport.authenticate('local'),function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
res.redirect('/users/' + req.user.username);
});
That way, you can access your user object from the page you redirect to.
In case you get stuck, you can refer to my Github project where I implemented it clearly.
I'm pretty new to javascript but as I understand it from the tutorials you have to implement some session middleware first as indicated by 250R.
const session = require('express-session')
const app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
let sess = {
genid: (req) => {
console.log('Inside the session middleware')
console.log(req.sessionID)
return uuid()
},
store: new FileStore(),
secret: 'keyboard cat', // password from environment
resave: false,
rolling: true,
saveUninitialized: true,
cookie: {
HttpOnly: true,
maxAge: 30 * 60 * 1000 // 30 minutes
}
}
app.use(session(sess))
// call passport after configuring the session with express-session
// as it rides on top of it
app.use(passport.initialize())
app.use(passport.session())
// then you will be able to use the 'user' property on the `req` object
// containing all your session details
app.get('/test', function (req, res) {
console.log(req.user)
})
res.render accepts an optional parameter that is an object containing local variables for the view.
If you use passport and already authenticated the user then req.user contains the authenticated user.
// app.js
app.get('/dashboard', (req, res) => {
res.render('./dashboard', { user: req.user })
})
// index.ejs
<%= user.name %>
You can define your route this way as follows.
router.post('/login',
passport.authenticate('local' , {failureRedirect:'/login', failureFlash: true}),
function(req, res) {
res.redirect('/home?' + req.user.username);
});
In the above code snippet, you can access and pass any field of the user object as "req.user.field_name" to the page you want to redirect. One thing to note here is that the base url of the page you want to redirect to should be followed by a question mark.
late to party but this worked for me
use this in your app.js
app.use(function(req,res,next){
res.locals.currentUser = req.user;
next();
})
get current user details in client side like ejs
<%= locals.currentUser.[parameter like name || email] %>
Solution for those using Next.js:
Oddly, —> the solution <— comes from a recently removed part of the README of next-connect, but works just as it should. You can ignore the typescript parts if you're using plain JS.
The key part is the getServerSideProps function in ./src/pages/index (or whichever file you want to get the user object for).
// —> ./src/authMiddleware.ts
// You'll need your session, initialised passport and passport with the session,
// so here's an example of how we've got ours setup, yours may be different
//
// Create the Passport middleware for SAML auth.
//
export const ppinit = passport.initialize();
//
// Set up Passport to work with expressjs sessions.
//
export const ppsession = passport.session();
//
// Set up expressjs session handling middleware
//
export const sess = session({
secret: process.env.sessionSecret as string,
resave: true,
saveUninitialized: true,
store: sessionStore,
});
// —> ./src/pages/index.ts
// update your user interface to match yours
export interface User {
id: string;
name: string;
}
interface ExtendedReq extends NextApiRequest {
user: User;
}
interface ServerProps {
req: ExtendedReq;
res: NextApiResponse;
}
interface ServerPropsReturn {
user?: User;
}
export async function getServerSideProps({ req, res }: ServerProps) {
const middleware = nc()
.use(sess, ppinit, ppsession)
.get((req: Express.Request, res: NextApiResponse, next) => {
next();
});
try {
await middleware.run(req, res);
} catch (e) {
// handle the error
}
const props: ServerPropsReturn = {};
if (req.user) props.user = req.user;
return { props };
}
interface Props {
user?: User;
}
//
// A trivial Home page - it should show minimal info if the user is not authenticated.
//
export default function Home({ user }: Props) {
return (
<>
<Head>
<title>My app</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<h1>Welcome to My App {user?.name}</h1>
</main>
</>
);
}
You'll need to make sure that you register a middleware that populates req.session before registering the passport middlewares.
For example the following uses express cookieSession middleware
app.configure(function() {
// some code ...
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.cookieSession()); // Express cookie session middleware
app.use(passport.initialize()); // passport initialize middleware
app.use(passport.session()); // passport session middleware
// more code ...
});