kurisukun
kurisukun

Reputation: 3159

Passport.js: how to access user object after authentication?

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!

Upvotes: 45

Views: 63286

Answers (8)

fredrivett
fredrivett

Reputation: 6584

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>
    </>
  );
}

Upvotes: 0

Gunal Bondre
Gunal Bondre

Reputation: 94

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] %>

Upvotes: 0

Hasan Sefa Ozalp
Hasan Sefa Ozalp

Reputation: 7208

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 %>

Upvotes: 2

DarkLite1
DarkLite1

Reputation: 14705

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)
})

Upvotes: 2

Sajeed786
Sajeed786

Reputation: 21

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.

Upvotes: 1

L.T
L.T

Reputation: 370

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.

Upvotes: 13

Darcys22
Darcys22

Reputation: 1234

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});
    }

Upvotes: 74

250R
250R

Reputation: 37151

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 ...

});

Upvotes: -3

Related Questions