Ad

Accessing Passport's Req.user Within React (ES6)? API Call Returns Req.user As Undefined

I'm making an app using React Starter Kit that uses Passport for authentication. I'm at the stage now where I'm trying to access the req.user object in the front end, but I'm having trouble passing that req.user object into the React/ES6 environment.

I tried to pass the object as a prop and as context, to no avail. At this point, I decided to make an API endpoint where I can return the value of req.user as JSON, however req.user is being returned as undefined, despite it working fine under get('*').

This is the GET call I made, that is returning undefined:

server.get('/user', (req, res) => {
  console.info('user: ', req.user);
});

While

server.get('*', async (req, res, next) => {
  console.info('*: ', req.user);
  // ... the rest of the React Starter Kit rendering code

does return an object for req.user as it should, which leaves me confused. Is the passport session restricted to certain urls or something?

Middleware:

    server.use(express.static(path.join(__dirname, 'public')));
    server.use(cookieParser());
    server.use(session({
      secret: 'keyboard cat',
      cookie: { httpOnly: false },
      resave: true,
      saveUninitialized: true,
    }));

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

And serialize/deserialize are as simple as they get:

    passport.serializeUser((user, done) => {
      console.log('serializeUser');
      done(null, user);
    });

    passport.deserializeUser((obj, done) => {
      console.log('deserializeUser');
      done(null, obj);
    });

I know there are similar SO threads about req.user being undefined, but none seem to have my situation where it's only sometimes undefined based on where it's requested. Thanks for reading and any suggestions you have. Cheers!


EDIT: Here's the auth flow

    [initial app load with fresh server instance...]
    in (*) passport FALSE
    indexPage mounting...
    in (/user) passport FALSE
    [click login button and successfully login]
    serializeUser
    deserializeUser
    in (*) passport is TRUE
    indexPage mounting...
    in (/user) passport FALSE

I did some further testing, and noticed something interesting when triggering the API call with the Chrome console. I'm using fetch to do this by the way - I do fetch('/user') then log the response in componentDidMount method. Now, when I do this in the Chrome console: fetch(/*), the terminal console logs in (*) passport is false again.

So the problem seems to be that passport is altogether disappearing after the initial render. An issue with cookies maybe? I'm going to investigate further and see what I can find.

Ad

Answer

When using fetch(), much like with XMLHttpRequest(), you need to tell the browser explicitly that any credentials (like session cookies, which Passport needs in order to identify the active session) need to be sent along with the request:

fetch('/user', { credentials : 'same-origin' }).then(...);

The various values that you can use are documented here.

Ad
source: stackoverflow.com
Ad