jaredhanson / passport

Simple, unobtrusive authentication for Node.js.
https://www.passportjs.org?utm_source=github&utm_medium=referral&utm_campaign=passport&utm_content=about
MIT License
22.98k stars 1.24k forks source link

req.isAuthenticated() is always returning false after authenticating with AWS cognito using 'passport' and 'passport-cognito' for strategy. #914

Open Anubhav-Nigam opened 2 years ago

Anubhav-Nigam commented 2 years ago

req.isAuthenticated() is returning false even after authenticating with AWS cognito.

The function which I am using for adding login routes is:


addAuthenticationRoutesCognito: function (app) {

app.use(passport.initialize());
app.use(passport.session());
app.use(function (req, res, next) {
  res.setHeader('Cache-control', 'no-store');
  res.setHeader('Pragma', 'no-cache');
  next();
});
passport.serializeUser((user, cb) => {
  cb(null, user);
});
passport.deserializeUser((user, cb) => {
  cb(null, user);
});

let config = {};
let cognitoRedirectUri;
if (process.env.hasOwnProperty("NODE_ENV") && process.env.NODE_ENV === "development") {
  /*in use for development purpose only*/
  cognitoRedirectUri = "http://localhost:3000/";
} else {
  cognitoRedirectUri = process.env.APP_URL;
}

let loginUrl = "https://" + cognitoDomain + ".auth.ap-south-1.amazoncognito.com/login?response_type=token&client_id=" + cognitoAppClientId + "&redirect_uri=" + cognitoRedirectUri;
console.log('COGNITO LOGIN URL = ', loginUrl);

config.userPoolId = cognitoUserPoolId;
config.clientId = cognitoAppClientId;
config.region = cognitoRegion;

let strategy = new CognitoStrategy(config, function(accessToken, idToken, refreshToken, user, cb) {
  // verify callback
  process.nextTick(function() {
    // ...
    cb(null, user);
  });
});

passport.use(strategy);

app.get(loginUrl, passport.authenticate('cognito', {
  successRedirect: landingPageUrl,
  forceLogin: true
}));

app.get("/home", passport.authenticate('cognito'), foundationAuth.getUserDetailsAndJWT.bind(foundationAuth));

}

And for checking if the request is authenticated I am using:


function ensureAuthenticatedCognito(req, res, next) {
console.log("is request authenticated ? " + req.isAuthenticated());
console.log("original ULR = " + req.originalUrl);
console.log('req====',req);

if (!req.isAuthenticated()) {
let cognitoObj = authManager.getCognitoInstance();
// console.log('cognitoObj.loginUrl==', cognitoObj.loginUrl);
authManager.validateUrlAndRedirectCognito(cognitoObj.loginUrl, req, res);
// return next();
} else {
return next();
}
}

The _passport object printed inside res is:


_passport:
{ instance:
Authenticator {
_key: 'passport',
_strategies: [Object],
_serializers: [Array],
_deserializers: [Array],
_infoTransformers: [],
_framework: [Object],
_userProperty: 'user',
Authenticator: [Function: Authenticator],
Passport: [Function: Authenticator],
Strategy: [Function],
strategies: [Object] } }

getCognitoInstance() returns the login page url of hosted UI of cognito. validateUrlAndRedirectCognito() redirects to that url.

Since the value of '_userProperty' is 'user', req.isAuthenticated() should return true after authentication. Please help me with what is wrong in this code.

bencipher commented 2 years ago

Disclaimer: I started writing nodejs like a week ago and I have basic js knowledge, so my use of terms may be basic.

Now, from what I see, the issue is with your deserializer function not working properly. You need to attach the user object to the done callback, like this: passport.deserializeUser((id, done) => User.findById(id, (err, user) => done(err, user))); so in your own case, it should be:

Model = require('your model here') // e.g. const User = require('../models/User');
passport.deserializeUser((user_id, cb) => {
Model.findById(user_id, (err, user) => cb(null, user));
});
// I personally would prefer to use user_id instead of user to avoid the id clashing with the user object.

Recap: The serializer expects an id of the currently logged-in user which it then uses to build the session for the passport library.

Also, make sure you set the appropriate libraries and initialize the express-session or express-cookie before passport session. i.e

app.use(passport.initialize());
app.use(passport.session());

Hope this helps.