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.
@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?
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
@generator101 is this based off a payload next template repo?
I'm not the best to answer here. Maybe @jarrod_not_jared or @jacobsfletch can weigh in.
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!
@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
.
@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
@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
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?
@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
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
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',
},
],
},
],
}
@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
it is exact copy of this one
https://github.com/payloadcms/payload/blob/master/examples/auth/cms/src/collections/access/adminsAndUser.tsAlso - what site are you trying to log into? Does the Cookie domain match?
@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
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)
I deployed backend and frontend to render.com, the backend is
ex-mybackend.onrender.com
and frontend is
ex-myfrontend.onrender.com
Right, but what is
domain: process.env.COOKIE_DOMAIN,
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
right right
it has to be something simple, hmmm
and this is the user in mongo db
right, I think this specifically has to do with cookies/csrf
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
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
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}`)
and it logs correctly huh
yeah
ðŸ˜
where did you do the log?
in the payload config file? what about the server file? (built server file)
@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}`)
},
})
I would also add a log above your buildConfig function
I agree with Jarrod then, likely cors/csrf
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)
on server I have this
dotenv.config()
on config file I have this
dotenv.config({
path: path.resolve(__dirname, '../.env'),
})
right, all relative to where the env is
I think I added this one after reading your comment yesterday
for linking that github issue
are your server and config file at the same level in the same dir?
yes
NICE
so just change your dotenv config in your payload config, thats the issue
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
Ok, just for clarity, can you change the dotENV in the server file to match the one in your payload config file
nope, that didnt help either
I see a lot of these logs
should I change the
process.env.COOKIE_DOMAIN
to
.onrender.com
?
seems like it might be a render thing:
https://community.render.com/t/setting-cookies-onrender-com/7886damn, 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
you mean instead of using their auto generated ones?
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
got 2 luv it
thank you for all your help, I hope I can migrate some side projects to payload cloud when free plan is here
Yeah no prob! glad we got to the bottom of it
@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
did you also make this change:
https://github.com/payloadcms/payload/blob/master/examples/auth/cms/src/collections/Users.ts#L46yes, 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
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
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
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?
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
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?
yes
I cloned the repo locally and added my db
what if you clone and use a blank db
I did not try that yet
if you do make sure to make the first user with the demo@payloadcms.com email
if you remove the data.email === ... part you are able to login?
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.