Hi. I'm experimenting with the new Next.js server actions trying to use it for auth purposes. I'm making a simple fetch request to my
Users
endpoint to login to the application. The problem I'm facing is it doesn't set the cookie automatically after successful login. I tried to create it manually using
next/cookies
and pass the token as a value but it seems the token in expired and can't be used for authorization.
"use server"
const password = data.get("password")
const email = data.get("email")
const res = await fetch(`${process.env.PAYLOAD_CMS_URL}/api/users/login`, {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
email,
password
}),
})
const resData = await res.json()
cookies().set({
name: "payload-token",
value: resData.token,
// expires: new Date(`${resData.exp * 1000}`),
path: "/",
httpOnly: true,
secure: true,
sameSite: "lax"
})
I also have added right
csrf
domains in payload config. But it doesn't seem to work.
@aamdmn Morning!
You've added both the cors / csrf allowed urls?
I see you've added credentials: "include", that's good
Do you get any messages in your dev console?
@notchr Hi thank you for your respond. Yes both cors and csrf should be added correctly.
You mean in the payload console or next dev console? 😄
You shouldn't need to manually set a cookie
Ah sorry, browser console
Let's check out the request it makes on logic
login*
And inspect the set cookies in your developer tools
(if any)
There is no set cookie header unfortunately.
I'm using server actions. Maybe that's the problem
But the returned token should be correct right?
Well
You can paste the token into jwt.io
And check that it has the correct info
I recall a similar issue to this posted recently, I can search threads in a tiny bit
But basically, the fetch request should be auto setting a cookie that includes the token
That is, if you've logged in via the /login endpoint
It depends on how you're expecting the auth to happen
your request looks correct
i checked the token and it's correct but it seems I can't use it. It always returns a
You are not allowed to perform this action
.
Can you share the access control on the admin collection
what's even weirder is if I log in to the cms, the cookie updates automaticaly in my FE.
On your user/admin collection, lets check the access control
Also out of curiosity, what do you mean that the token says "you are not allowed to perform this action"
like when you do subsequent requests?
Yeah, the access control is pretty straightforward. I have two collections Users and Orders. Each user has it's role(admin, cleaner, customer). Admins and cleaners can see all orders and customers can only see orders assigned to them.
This is orders access control:
access: {
read: isAdminOrHasOrderAccess('id'),
create: isAdmin,
},
import { Access } from "payload/config"
export const isAdminOrHasOrderAccess = (orderIDFieldName: string = 'order'): Access => ({ req: { user } }) => {
if (user) {
if (user.role === 'admin' || user.role === 'cleaner') {
return true
}
if (user.role === 'customer' && user.orders?.length > 0) {
return {
or: [
{
[orderIDFieldName]: {
in: user.orders
}
},
{
[orderIDFieldName]: {
exists: false
}
}
]
}
}
}
return false
}
After successful login every user should see their orders.
it says in further requests using the returned token in authorization header.
Well
By default the cookies should manage the auth state
I'm wondering, since your access logic is a little complex
If you comment out that access and set it to true so that its unrestricted
do you still have issues?
I would start there
yes, there are no issues. it show the orders normally.
sorry for late respond
Ah okay, well then we know the source of the issue! Were you able to resolve?
I am wondering how this will work since you are trying to auth server to server. How do you know the domain that makes the request to whitelist?
I feel like you would need to use payloads local api to login 🤔
Another way is to parse a jwt on a server, so that you can verify it came from a specific source
I think, there are no problems with the access control, the problem is with the cookie on the FE. You see, if I log in on the FE and set the cookie manually (because it won't set up automatically) it won't let me thru
You are not allowed...
. Then if I log in to the CMS, it updates or changes my cookie on the FE with the right expire date, right token and all that stuff and if I refresh it show the orders as expected. I don't understand why 😄 And also, why is the token returned from the
users/login
invalid?
Do you have any examples how can I implement the local API to my Next app? I'm using the new
app
router. Do I need to have monorepo to be able to use the local api?
I think I have similar problem to this thread:
https://discord.com/channels/967097582721572934/1123857321030856714@aamdmn How do you know it's invalid?
Did you verify it with a jwt parser?
When I'm trying to refresh it with
/refresh-token
it says
jwt expired
yes
Okay, I was able to fix it. It was pretty simple actually. I just switched the hole login process to the client. It now sets the cookie like it should. Thank you @notchr @jarrod_not_jared for the time and help!
Nicely done!
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.