I'm making an landing page for an nextJS 14 app and using payload as a backend. I'm creating blogs in the payload and access them in the frontend app.
Now is there any way to secure these endpoints currently I'm using cors option in the
buildConfig.ts.
And one option I'm using is custom hook in the collection using
beforeReadhooks: {
afterChange: [revalidatePost],
afterRead: [populateAuthors],
afterDelete: [revalidateDelete],
beforeRead: [
async ({ req, query }) => {
const apiKey = req.headers.get('x-api-key')
// Check if the API key is provided and matches the one stored in the environment variables
if (apiKey !== process.env.PAYLOAD_API_KEY) {
throw new Error('Forbidden: Invalid API Key')
}
return query
},
],
},This approach works but now I've to write this
beforeReadto every collection, Is there any way to do this globally.
I think you should read through these docks
https://payloadcms.com/docs/access-control/overviewand for API access there's already some support built in
https://payloadcms.com/docs/authentication/api-keysI checked these docs but didn't find any solution I'm looking.
For Access Control I need a user but as it is just a landing page getting data from payload (no user is required).
API Key strategy is for third party API integration right (which is not my case)
I tried access control but it didn't worked the api is still accessible from the outside app
What API are you using? De built in ones?
Can you try
access: {
read: () => false,
},And see if it is accessible
By default no APIs should be accessible. Unless you're using the local api. Then everything is accessible but only your server code can use that.
I tried this, but it didn't work as expected
Could you elaborate on how you are accessing the content. Through what API
Can you please explain what local api means here? Because I initialised a payload project and using a separate frontend nextJS app as localhost:3000/api/posts
Right. Using the access control is still the way to go. Could you just confirm that setting the read access to false stops you from being able to access the API (I know that i breaks the admin ui aswell)
No, API is working and admin panel is also working it's not breaking
I can share my files here
Please do
These are my files
collections/posts/index.tsx
You have an "authenticatedOrPublished" access function on your Posts collection
Please have a look here
so this was the issue?
cloning
I've created a separate ApiUser collection. I thinks it's nice to have them separated but you can just use your users if you want. I've added
auth: {
useAPIKey: true,
},This will make allow payload to generate an API key and manage all the auth checking.
Then in your collection you want to check if there is a user. Like this
access: {
read: ({ req: { user } }) => {
if (user) {
return true
}
return false
},
},If there is a user then payload has authenticated someone based on either user / password or API key. Here you can also check what kind of user. You can add roles to the user collection and check them here and then return true / false depending on what your need are
And for your earlier question
API Key strategy is for third party API integration right (which is not my case)
It's not. It's for when you want to use API keys to interact with the payload APIs or any other APIs you use where you might want to leverage their already built auth solution
First or third party does not matter
Also on a side note. The website template is very advanced. It can be really hard to get a grasp on everything and customizing it into what you really need. So my personal suggestion is to never start a project from it. Instead use it for understanding how things can be implemented and cherry-pick the parts that you need and understand
The api-user collection should probably have
disableLocalStrategy: true,aswell to disable username / password login
Thanks, for the help
I cloned the code there was a minor CORS issue for which I had to allow my frontend origin, now If I access API from my frontend it gives 403 error and from admin UI it works as expected
I'm still not able to get it how it'll work?
with all this logic inplace payload will need user/apiKey to authenticate right, in my case my frontend doesn't have any user/apiKey so payload will not authenticated and gives 403 forbidden
Here's video
I think you've missunderstood. The
useAPIKeygoes on a user collection. So that the users can have an API key
If you just want your frontend to be able to get your posts just set read to () => true
And it will always be readable
If you want to have an api key you add the useAPIkey to your users collection and go into the UI and get the key from the user
If you run my demo. Create a few pages and then try to access them from postman / insomnia through the api with an API key and it might become clearer how it works
I created few pages now, I get the data if the read returned value is true (doesn't matter if I check user or explicitly set true). I also enabled the API key and it's value how can I use this so I can send this key in the headers from the separate frontend or postman so that payload authenticates this key
You can use it like this
const response = await fetch('http://localhost:3000/api/pages', {
headers: {
Authorization: `${Users.slug} API-Key ${YOUR_API_KEY}`,
},
})That's the whole point. You own the function. You return true if you want to allow the request and false if not. The logic is all up to you
Thank you so much
Hi
@332241126150897674im hoping you can help me with this. I've added a user called Apiuser and set up a key for it. when i attempt to call a collection i get "You are not allowed to perform this action." Also if i log the key it is shows only the Admin user which is the wrong user?
Can you tell me more? What endpoint are you calling? A built in or custom? How are you logging the key? Can you show some code?
Star
Discord
online
Get dedicated engineering support directly from the Payload team.