Passport strategy called, passed a Payload user - still null on /users/me?

default discord avatar
3 months ago

So I'm diving into passport strategies in Payload at the moment, and I decided to start somewhat small with a passport-custom strategy.

The end plan is to create one that verifies the firebase JWTs from my React Native apps.

I've added it as a strategy in the users collection:

 auth: {
    strategies: [
        name: "custom",
        strategy: () => customStrategy(),

And here's the customStrategy:

export default (): Strategy => {
  const strategy = new Strategy(async (req, done) => {
    // Extracts the JWT
    const token = extractJWT(req);
    if (!token) {
      done(null, false);

    // Verifies and decodes the JWT
    const verifiedToken = await verifyToken(token);

    // Finds the user
    if (verifiedToken) {
      const userDoc = await payload.find({
        collection: "users",
        where: {
          oauthId: {
            equals: verifiedToken.user_id,
        showHiddenFields: true,

      // The user exists, so it should work
      const user =[0];
      if (user && > 0) {
        // Yes, user exists. Passing the user document to done
        done(null, user);
    } else {
      done(null, false);

  return strategy;

It's green down until the done() callback.

The user exists and is passed to the callback.



still returns null.

The strategy names seems to be (simplified version:)

${collection}-${name / index}

, when set up in Payload where the passport.use() is called with the strategy.

Ideas? Am I missing anything obvious in the implementation?

Overriding the /users/me endpoint to return req.user solves the issue. The strategy looks like it's been working all along 😅

    Open the post
    Continue the discussion in Discord
    Like what we're doing?
    Star us on GitHub!


    Connect with the Payload Community on Discord



    Can't find what you're looking for?

    Get help straight from the Payload team with an Enterprise License.