I’m trying to create a second user collection called
customersbut I’m having some issues getting it working. I’m following the auth example in the GitHub and it works fine when I’m logged into an admin user.
My use case is I’d like to gate content based on subscription tier, and I don’t want to include customers in my main user collection where my editors and admins are. The customers should be able to follow a different login flow and shouldn’t have access to the admin panel.
Has anyone implemented something like this?
The way I'd normally approach this is a single user collection that contains a
rolefield (e.g.
admin,
customer).
I'd then make sure to set the
adminaccess control to only allow the
adminrole to access the CMS (
https://payloadcms.com/docs/access-control/collections#admin)
This means if a
customerrole logs in through your custom login flow (or for some reason at
/admin/login) and then attempted to visit
/admin, they would be shown an unauthorized screen.
If you definitely want to have separate collections, could you elaborate on what isn't working for you? It should be possible.
I suppose I could have the customer role and then an option tier select when role is customer, but that does keep everything together in the same collection, which I don’t love.
What’s not working: I think the user isn’t persisting after hitting the login route. I can create a user, and I see the new customer in my collection, but when I try to login with that user, it returns null. Looking at the auth example, there is a
useStatethat sets user and returns user. When I log the customer after the api is hit, I get the customer info, but when I try to log
userafter using
setUserit returns null.
When I have my auto login set with an admin user, I can see and access all the account info im rendering on the front end, but after I disable that and try to login with a user from my customers collection, I just get stuck in a loop of “you must login to see your account”
For easy reference, here’s the auth example:
https://github.com/payloadcms/payload/tree/main/examples/authsome things are dated in it (like types from payload/auth), but I’ve fixed all that.
The auth example does use the user collection, but I updated all references to my Customer type and api routes
I’ve been thinking about how you said you’d handle this and I think that might be the best approach. My primary concern was that one collection with many customers mixed in with admins would be too much to manage. Do you see that as an issue? I could always setup a custom component to filter each role in the table view if I really wanted to.
Maybe I’m overthinking why I’d want a second user collection
I wonder if you could easily customize the collection filter component to add a toggle button for admins and customers, then it won't feel so tied together.
I'm starting to think that my approach actually wasn't wrong and the way auth is done in the example isn't working right. I switched everything back to be a single user collection and I still can't login. I can create no problem, though.
I'm not sure if you're looking for something like this:
https://www.youtube.com/watch?v=AEyR91PSpoISeems the same use case
Hey. I'm not an expert, I came here mostly to read rather than write but I implemented something similar and had a similar problem during development. In my case, the issue occurred because the payload for both collections returned an httpOnly cookie called
payload-token. I don't remember my exact flow, but in some cases, a token was generated for the wrong collection.
For example, if you log in to the admin panel (UsersCollection) and then try to access /api/customers/me (CustomersCollection), it won’t work. To resolve this, clear your cookies before logging in or log out from the admin panel before attempting to log in to the customers collection.
I'm not sure what your configuration is, but as far as I understand, you have two auth collections. One of them is the users collection, which is assigned to the admin.user property in your payload.config, and the other is CustomersCollection, which is imported into the collections array like this:
export default buildConfig({
admin: {
user: UsersCollection.slug,
// ...
},
// ...
collections: [
UsersCollection,
CustomersCollection
]
});If you don’t want CustomersCollection to have access to the admin panel, simply add
admin: () => falsein the access configuration of the collection. Check out my CustomersCollection config:
export const CustomersCollection: CollectionConfig = {
slug: 'customers',
auth: {
tokenExpiration: 60 * 60 * 12, // 12h
maxLoginAttempts: 30,
lockTime: 60 * 60 * 1, // 1h
},
access: {
admin: () => false, // Disables admin panel for this collection
create: () => true, // Allows registering users
},
admin: {
// ...
},
fields: collectionFields,
};Make sure that if you want to log in as a customer, you need to call /api/customers/login. If you’re using fetch to make API calls, remember to add
{ credentials: "include" }to your requests, like in this example:
fetch("/api/customers/login", {
method: "POST",
credentials: "include", // <- this
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: "user", password: "pass" })
});If you don’t include this, the cookie won’t be saved. As a result, when you later call collection APIs, your user will not be visible in req.user within hooks and access control functions.
Then, if you want to verify whether a customer has access to the requested resource, you can check the user collection in req.user, like this:
async ({ req }) => {
if (!req.user || req.user.collection === 'users') return true;
console.log(req.user.collection); // should print 'customers'
if (userHasAccess) return true;
return false;
};It's definitely got to be something with cookies then. I'm able to login to only a single account in Chrome, but nothing in Safari where I've done the majority of my development. Opening incognito windows don't help, though, which is strange.
I'll check the video out and see if it helps me understand what I'm doing wrong here.
this is actually exactly how I wanted to do this. Thank you for sharing!
Mentioned the wrong person, oh well 😂
Star
Discord
online
Get dedicated engineering support directly from the Payload team.