Cookie is not set in production but works in local

default discord avatar
generator101
2 months ago
62

I am setting up basic authentication using the example repo and the cookie is set in frontend when on local host but when I deployed it to render.com, it no longer sets the cookie.


auth: {
    tokenExpiration: 28800, // 8 hours
    cookies: {
      sameSite: 'none',
      secure: true,
      domain: process.env.COOKIE_DOMAIN,
        },
    },

in my .env for local, cookie domain is set to

COOKIE_DOMAIN=localhost

and in production, I changed it to

.onrender.com

but still not able to store the cookie.

  • default discord avatar
    notchr
    2 months ago

    @generator101 Hmm, I didn't have to pass the domain in, interesting



    Did you set CORS/CSRF settings too?



    Also, may not be necessary but, in my server.ts, I manually specify the cors config and also pass credentials: true



    app.use(
      cors({
        origin: [
          "http://localhost:4200",
          "https://www.example.com",
        ],
        credentials: true,
      })
    );


    Are you using credentials: 'include' in your request on the frontend?

  • default discord avatar
    generator101
    2 months ago

    in the config files, I have this



    cors: [
            process.env.PAYLOAD_PUBLIC_SERVER_URL || '',
            process.env.PAYLOAD_PUBLIC_SITE_URL || '',
        ].filter(Boolean),
        csrf: [
            process.env.PAYLOAD_PUBLIC_SERVER_URL || '',
            process.env.PAYLOAD_PUBLIC_SITE_URL || '',
        ].filter(Boolean),


    In frontend, I used this



    import { cookies } from 'next/headers'
    
    const me = await fetch(
      process.env.PAYLOAD_PUBLIC_SERVER_URL + '/api/users/me',
      { headers: { Cookie: cookies().toString() } }
    ).then((r) => r.json())


    method: 'POST',
        credentials: 'include',
        headers: {
        'Content-Type': 'application/json',
         .....
    },


    Any help with this will be greatly appreciated 😅



    @denolfe any help with this? thanks



    cant figure out why cookie is not working in production

  • default discord avatar
    notchr
    2 months ago

    @generator101 is this based off a payload next template repo?

  • discord user avatar
    denolfe
    Payload Team
    2 months ago

    I'm not the best to answer here. Maybe @jarrod_not_jared or @jacobsfletch can weigh in.

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    I am guessing that PAYLOAD_PUBLIC_SERVER_URL is not defined in prod. Check out this GH discussion, let me know if it clears things up for you!



    https://github.com/payloadcms/payload/issues/1654#issuecomment-1403972303
  • discord user avatar
    jacobsfletch
    Payload Team
    2 months ago

    @generator101 also check that the prefixed period in your cookie domain isn’t the problem. I would expect this value to be

    onrender.com

    and not

    .onrender.com

    .

  • default discord avatar
    generator101
    2 months ago

    @jarrod_not_jared I tried adding

        serverURL: process.env.PAYLOAD_PUBLIC_SERVER_URL || 'http://localhost:8000',

    but still did not work,



    @jacobsfletch that didnt help too, it still does not set the cookie. Have you guys tested that nextjs auth in production environment? thanks

  • discord user avatar
    jacobsfletch
    Payload Team
    2 months ago

    @generator101 I think what @jarrod_not_jared is suggesting is to ensure your variables are not undefined in production for some reason like incorrect dotenv config, etc

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    Yeah I would console log one of em above your payload config file in your prod environment and see what they log. Undefined or the env var?

  • default discord avatar
    generator101
    2 months ago

    @jarrod_not_jared I just did

    payload.logger.info(`Public Server URL: ${process.env.PAYLOAD_PUBLIC_SERVER_URL}`)

    and it loaded the url I added in env variables



    Jul 12 06:30:48 PM [22:30:48] INFO (payload): Starting Payload...


    Jul 12 06:30:52 PM [22:30:52] INFO (payload): Admin URL: localhost:8000/admin


    Jul 12 06:30:52 PM [22:30:52] INFO (payload): Public Server URL: MY URL FROM ENV


    Jul 12 06:30:54 PM Your service is live 🎉





    this is what I see in the console log of the server

    image.png
  • discord user avatar
    jacobsfletch
    Payload Team
    2 months ago

    Open you browser’s Application tab in the inspector console and take a look at the cookie that was set.



    From there you can inspect the domain property being used, etc

  • default discord avatar
    generator101
    2 months ago

    I cant even login to backend





    my user collection



    import type { CollectionConfig } from 'payload/types'
    
    import { admins } from './access/admins'
    import adminsAndUser from './access/adminsAndUser'
    import { anyone } from './access/anyone'
    import { checkRole } from './access/checkRole'
    import { loginAfterCreate } from './hooks/loginAfterCreate'
    import { protectRoles } from './hooks/protectRoles'
    
    export const Users: CollectionConfig = {
        slug: 'users',
        auth: {
            tokenExpiration: 28800, // 8 hours
            cookies: {
                sameSite: 'none',
                secure: true,
                domain: process.env.COOKIE_DOMAIN,
            },
        },
        admin: {
            useAsTitle: 'email',
        },
        access: {
            read: adminsAndUser,
            create: anyone,
            update: adminsAndUser,
            delete: admins,
            // admin: ({ req: { user } }) => checkRole(['admin'], user),
        },
        hooks: {
            afterChange: [loginAfterCreate],
        },
        fields: [
            {
                name: 'firstName',
                type: 'text',
            },
            {
                name: 'lastName',
                type: 'text',
            },
            {
                name: 'username',
                type: 'text',
                required: true,
                unique: true,
                index: true,
            },
            {
                name: 'roles',
                type: 'select',
                hasMany: true,
                saveToJWT: true,
                hooks: {
                    // temp disable this hook
                    // beforeChange: [protectRoles],
                },
                options: [
                    {
                        label: 'Admin',
                        value: 'admin',
                    },
                    {
                        label: 'User',
                        value: 'user',
                    },
                ],
            },
        ],
    }
    image.png
  • default discord avatar
    notchr
    2 months ago

    @generator101 This is likely an issue with your adminsAndUser function. Are you able to access if you set your access levels to true temporarily



    for instance



            read: () => true,
            create: anyone,
            update: adminsAndUser,
            delete: admins,


    Just to narrow down what is causing this

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    Also - what site are you trying to log into? Does the Cookie domain match?

  • default discord avatar
    generator101
    2 months ago

    @jarrod_not_jared I am trying to login to backend and I get unauthorized error, I try to login to frontend and it doesnt set cookie

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    are you logging into

    https://some-domain.com

    and your cookie domain is

    some-domain.com

    (I don't think cookie domain needs to be fully qualified)

  • default discord avatar
    generator101
    2 months ago

    I deployed backend and frontend to render.com, the backend is

    ex-mybackend.onrender.com

    and frontend is

    ex-myfrontend.onrender.com
  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    Right, but what is

    domain: process.env.COOKIE_DOMAIN,
  • default discord avatar
    generator101
    2 months ago

    onrender.com





    I have been trying so many different things and still not working, initially frontend was deployed on vercel



    I moved it to render to have same domain

    image.png
  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    right right



    it has to be something simple, hmmm

  • default discord avatar
    generator101
    2 months ago


    and this is the user in mongo db

    image.png
  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    right, I think this specifically has to do with cookies/csrf

  • default discord avatar
    generator101
    2 months ago
    dotenv.config({
        path: path.resolve(__dirname, '../.env'),
    })
    
    export default buildConfig({
        serverURL: process.env.PAYLOAD_PUBLIC_SERVER_URL || 'http://localhost:8000',
        collections: [Users],
        cors: [
            process.env.PAYLOAD_PUBLIC_SERVER_URL || '',
            process.env.PAYLOAD_PUBLIC_SITE_URL || '',
        ].filter(Boolean),
        csrf: [
            process.env.PAYLOAD_PUBLIC_SERVER_URL || '',
            process.env.PAYLOAD_PUBLIC_SITE_URL || '',
        ].filter(Boolean),
        typescript: {
            outputFile: path.resolve(__dirname, 'payload-types.ts'),
        },
    })


    my config file

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    with render do you get to pick your domain name? do you have that set at your PAYLOAD_PUBLIC_SERVER_URL & PAYLOAD_PUBLIC_SITE_URL envs

  • default discord avatar
    generator101
    2 months ago


    I set the Public site URL to the frontend url



    and server URL to the backend url



    and I did

    payload.logger.info(`Public Server URL: ${process.env.PAYLOAD_PUBLIC_SERVER_URL}`)
    image.png
  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    and it logs correctly huh

  • default discord avatar
    generator101
    2 months ago

    yeah



    😭

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    where did you do the log?



    in the payload config file? what about the server file? (built server file)

  • default discord avatar
    generator101
    2 months ago

    @notchr changing

    read: () => true,

    still doesnt let me login



    @jarrod_not_jared on the server



    const start = async (): Promise<void> => {
        await payload.init({
            secret: process.env.PAYLOAD_SECRET,
            mongoURL: process.env.MONGODB_URI,
            express: app,
            onInit: () => {
                payload.logger.info(`Admin URL: localhost:${process.env.PORT}/admin`)
                payload.logger.info(`Public Server URL: ${process.env.PAYLOAD_PUBLIC_SERVER_URL}`)
            },
        })
  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    I would also add a log above your buildConfig function

  • default discord avatar
    notchr
    2 months ago

    I agree with Jarrod then, likely cors/csrf

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    in both your server file and your config file you are using the same:


    dotenv.config({
        path: path.resolve(__dirname, '../.env'),
    })


    So below that I would log

    process.env.PAYLOAD_PUBLIC_SERVER_URL

    (in each file)

  • default discord avatar
    generator101
    2 months ago

    on server I have this



    dotenv.config()


    on config file I have this



    dotenv.config({
        path: path.resolve(__dirname, '../.env'),
    })
  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    right, all relative to where the env is

  • default discord avatar
    generator101
    2 months ago

    I think I added this one after reading your comment yesterday



    for linking that github issue

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    are your server and config file at the same level in the same dir?

  • default discord avatar
    generator101
    2 months ago


    yes

    image.png
  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    NICE



    so just change your dotenv config in your payload config, thats the issue

  • default discord avatar
    generator101
    2 months ago

    I did the log and it outputs the domain



    Jul 13 10:58:03 AM  > server@0.1.0 build:payload
    Jul 13 10:58:03 AM  > cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload build
    Jul 13 10:58:03 AM  
    Jul 13 10:58:05 AM  CONFIG LOG: domain.onrender.com
  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    Ok, just for clarity, can you change the dotENV in the server file to match the one in your payload config file

  • default discord avatar
    generator101
    2 months ago

    nope, that didnt help either



    I see a lot of these logs







    should I change the

    process.env.COOKIE_DOMAIN

    to

    .onrender.com

    ?

    image.png
    image.png
  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago
  • default discord avatar
    generator101
    2 months ago

    damn, for real? omg



    maybe I can try payload cloud then



    it never occurred to me it can be related to render, I have another payload app with custom domain

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    you mean instead of using their auto generated ones?

  • default discord avatar
    generator101
    2 months ago

    yeah, I setup a custom domain for my other app, maybe I can try setting a custom domain for this one too



    also setting up process.env.COOKIE_DOMAIN as full domain of the backend didnt help



    omg it logged in using custom domain



    https://tenor.com/view/facepalm-really-stressed-mad-angry-gif-16109475
  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    got 2 luv it

  • default discord avatar
    generator101
    2 months ago

    thank you for all your help, I hope I can migrate some side projects to payload cloud when free plan is here

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    Yeah no prob! glad we got to the bottom of it

  • default discord avatar
    generator101
    2 months ago

    @jarrod_not_jared thanks, yeah



    also if I uncomment ``beforeChange: [protectRoles],



    the user role is changed from admin to just user



    I remember discussing this with you



    oh looks like it is updated

    https://github.com/payloadcms/payload/blob/master/examples/auth/cms/src/collections/hooks/protectRoles.ts


    I still think there is a bug in that function, if a user is already admin, it will change it to user if just using

    const isAdmin = req.user?.roles.includes('admin')


    req.user?.roles returns undefined

  • default discord avatar
    generator101
    2 months ago

    yes, are we sure req has users?



    I changed it to

    const isAdmin = data.roles.includes('admin')


    and seems to be working



    but I tried to log

    req.user

    and it gave me undefined

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    right, but that means I could pass formData saying I am an admin and I will become an admin. Whereas admins should only be able to add admins

  • default discord avatar
    generator101
    2 months ago

    I see, yeah that should not happen but with current code, if I am an admin and I login, my role is changed to user



    because

    const isAdmin = req.user?.roles.includes('admin')

    always returns false



    since req.user is undefined

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    when you login, user will attach to the req. So something is amiss in your situation



    if you clone the repo and cd into that examples/auth/cms folder and run

    yarn && yarn dev

    what happens? Can you login?

  • default discord avatar
    generator101
    2 months ago

    so this line that checks for email



      const isAdmin = req.user?.roles.includes('admin') || data.email === 'demo@payloadcms.com' // for the seed script


    works



    but the problem is that if I have bunch of admin users



    I can't check their emails



    if you remove

    data.email === 'demo@payloadcms.com'

    it will not work

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    The email check if only so the first user can be created as an admin. Once you have 1 admin you could remove that portion, and then just check the user roles on the req. But if you clone it down and do what I said above, you are saying that user.roles is undefined?

  • default discord avatar
    generator101
    2 months ago

    yes



    I cloned the repo locally and added my db

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    what if you clone and use a blank db

  • default discord avatar
    generator101
    2 months ago

    I did not try that yet

  • discord user avatar
    jarrod_not_jared
    Payload Team
    2 months ago

    if you do make sure to make the first user with the demo@payloadcms.com email

  • default discord avatar
    generator101
    2 months ago

    if you remove the data.email === ... part you are able to login?

Open the post
Continue the discussion in Discord
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.