Payload.autheticate middleware returns undefined for req.user on collections that aren't in config.admin.user

default discord avatar
paper-krane
last year
1 1

Current Behavior

Just as the title says, when using Payload's payload.authenticate middleware, the req.user object is only successful when accessing the collection used in the config.admin.user. But when trying to access a different auth enabled collection, it returns undefined.

Expected Behavior

I could be wrong but after reading the docs, I thought you could use this middleware thee authenticate any collection. I am definitely still learning Payload so my apologies if I am incorrect.

Steps to Reproduce & Detailed Description

I am using Payload 1.1.21.

I am just testing out a small idea and the only things I am using aside from Payload is LiquidJS for my templating, body-parser, and Stripe with I already configured an alias for. Everything else, I really just stuck to the docs for and haven't even set Stripe up yet to even interact with the app.

I see the cookie being placed with the token and prefix, and I first tested signing in via the Payload admin login page to first set the admin cookie then went to the account page and was able to authenticate and read the req.user in the console. Then, I signed out of the Admin user, made sure the cookie was gone and then used my login page to sign in as a mock user for my Users collection. I also see the cookie being set, see the token generated and even read the successful response from payload.login but when it redirects to the /account route, it shows unauthenticated and the req.user is undefined.

Here is my configuration and how I triggered this behavior:

payload.config.js

import Admins from './path/toAdmins';
import Users from './path/to/Users';

export default buildConfig({
	serverURL: process.env.APP_URL,
	admin: {
		user: Admins.slug
        },
        cookiePrefix: 'pk',
        // rest of configuration
});

Admins.js

const Admins = {
        slug: 'admins',
	auth: true,
	admin: {
		useAsTitle: 'email',
                disableDuplicate: true
	}
        // rest of admin config / fields
}

export default Admins

Users.js

const Users = {
        slug: 'users',
	auth: true,
	admin: {
		useAsTitle: 'email',
                disableDuplicate: true
	}
        // rest of admin config / fields
}

export default Users;

Finally for the routes, I am signing in using the Local API login and I copied it directly from the docs:

import express from 'express';
import payload from 'payload';

const app = express();

payload.init({
    secret: process.env.SECRET_KEY,
    mongoURL: 'mongodb://localhost/payload',
    express: app,
});

const router = express.Router();

router.use(payload.authenticate); 

router.get('/login', (req, res) => {
    res.render('login') // Renders a basic login from using LiquidJS
});

router.post('/login', async(req, res) => {
try {
    const result = await payload.login({
        collection: 'users', 
        data: { 
            email: req.body.email,
            password: req.body.password,
        },
        req: req,
        res: res,
        depth: 2
    });

    res.redirect('/account');
} catch(err) {
    res.send(err);
}
});

router.get('/account', (req, res) => {
    console.log(req.user);

    if (req.user) {
        return res.send(`Authenticated successfully as ${req.user.email}.`);
    }

    return res.send('Not authenticated');
});

app.use('/', router);

app.listen(3000, async () => {
    payload.logger.info(`listening on ${3000}...`);
});

Just want to end this and say thank you to the entire Payload team behind this. Haven't been this excited about a CMS in years! Really hoping to figure this small issue out! Thank you again!

  • discord user avatar
    jmikrut
    Payload Team
    12 months ago

    Hey @paper-krane — thank you for this report and for your compliments regarding Payload! We're pumped you found us and we have lots more to come.

    So, your understanding is correct. payload.authenticate will work for any collection (not just the one that is used to sign in to the admin UI.

    I recreated your test environment and I found that your login route actually was not working. I needed to add router.use(express.json()) immediately after the payload.authenticate middleware, at which point, it now works.

    However, I'm not able to test the full frontend admin UI workflow, because I don't have your login or account views.

    So I am thinking that the above addition of express.json() works, then awesome, but otherwise, this is probably something related to csrf protection. Maybe try and add your frontend site URL to the csrf array.

    Docs here:
    https://payloadcms.com/docs/authentication/overview#csrf-protection

    I'm going to convert this to a discussion but am happy to help further!

    1 reply
  • default discord avatar
    paper-krane
    12 months ago

    I feel like a complete dunce but after testing your solution and digging through all of my configurations, I realized with both of my user configs I was requiring email verification and for my dummy user, I never verified the email. This is so embarrassing and I am so sorry to bring up a potential bug over my petty mistake.

    Everything is working perfectly and I can't believe I spent almost 2 weeks missing something so obvious. You guys have built a solid CMS and I am so excited to see what you come up with in the future!

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

Star

Connect with the Payload Community on Discord

Discord

online

Can't find what you're looking for?

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