-
Notifications
You must be signed in to change notification settings - Fork 830
Update permission creation steps and clarify org: prefix behavior #2645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Are you comfortable mentioning this feedback to the team? Let them know we'd have to update all of the docs, so we want to be sure what terminology we're going with - but advocate that "Custom permissions" seem more user friendly/intuitive. |
Yes, done: https://clerkinc.slack.com/archives/C06FGDX7MRD/p1759250794885609. Let's see! |
@alexisintech Seems like the consensus is to keep it as custom permissions, but to make it a lowercase thing, aka it's not a feature name. just a descriptor. Here is the slack context: https://clerkinc.slack.com/archives/C06FGDX7MRD/p1759250794885609 . Changes here: Refine post dashboard convo |
Permissions grant users privileged access to resources and operations, like creating and deleting. Clerk supports two types of permissions: **system permissions** and **custom permissions**. | ||
|
||
> [!IMPORTANT] | ||
> In the Clerk Dashboard, permissions appear in the format `<feature>:<permission>`. However, the `org:` prefix is automatically applied under the hood for all organization-scoped permissions. This means that when checking permissions in your code, always include the full key with the prefix (`org:<feature>:<permission>`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need to pass the org:
prefix in code when checking perms! was there somewhere that you got this information from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed it with @royanger, but also, it's in our docs code examples too.

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gotcha! its not required when checking perms, but it is required in other places, like when passing params to certain methods and what not. here's the relevant slack discussion: https://clerkinc.slack.com/archives/C07JG7SCWCD/p1759437155781849
the solution we settled on is to just go ahead and add the orgs:
prefix everywhere (docs and dash) to minimize confusion
docs/guides/billing/for-b2b.mdx
Outdated
|
||
Permission-based authorization checks link with feature-based authorization checks. This means that if you are checking a custom permission, it will only work if the feature part of the permission key (`org:<feature>:<permission>`) **is a feature included in the organization's active plan**. For example, say you want to check if an organization member has the custom permission `org:teams:manage`, where `teams` is the feature. Before performing the authorization check, you need to ensure that the user's organization is subscribed to a plan that has the `teams` feature. If the user's organization is not subscribed to a plan that has the `teams` feature, the authorization check will always return `false`, even if the user has the custom permission. | ||
> [!IMPORTANT] | ||
> Permission-based authorization checks link with feature-based authorization checks. This means that a permission check will only work if the feature part of the permission key (`org:<feature>:<permission>`) **is a feature included in the organization's active plan**. For example, say you want to check if an organization member has the custom permission `org:teams:manage`, where `teams` is the feature. Before performing the authorization check, you need to ensure that the user's organization is subscribed to a plan that has the `teams` feature. If not, the authorization check will always return `false`, even if the user has the custom permission. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this isn't true, because you can assign a feature permission to a role, and give a user that role, and they will have that permission - regardless of if the organization pays for a subscription plan/feature or not.
i can try to help rewrite this - let me draft something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a messaging that was already there - I just made it into a callout. But from my discussion with @royanger, I understood the above to be true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
naurrr, that may be only if billing is enabled?
i have a fresh app, enabled orgs, and then assigned a custom permission to a role, and that role to a user. then i did a has()
check for it, and it worked.
no billing / plans required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so i've played around with this - i have a custom permission invoices:create
. i enabled billing, created an organization plan, added the invoices
feature to it. i have one user whose active organization is subscribed to the plan, so they have that permission because their org plan has that feature. i have one user whose active organization is not subscribed to the plan, but they have the permission through their role. and i'm not getting any issues with authorization checks. so maybe this information doesn't ring true anymore? i see that @mzhong9723 added it in this PR: https://github.com/clerk/clerk-docs/pull/2263/files - maybe she can give us some insight on why she added it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
naurrr, that may be only if billing is enabled?
Yes, this is in the billing guide, so I'm guessing this limitation only applies when billing is enabled. But yeah interested to hear your thoughts @mzhong9723 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The correct behavior if billing is enabled should be that the features that an organization member receives should only come from the active organization plan.
i have one user whose active organization is not subscribed to the plan, but they have the permission through their role.
So this scenario seems like a bug 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just set up the following scenario:
- user is an
admin
in two organizations:testorg
andtestorg2
- billing is enabled,
testorg
has active planexpensive_org
.testorg2
has planexpensive_org_copy
expensive_org
doesn't have any features,expensive_org_copy
has two features:teams
anddashboard
- role
org:admin
has permissions for theteams
anddashboard
features
Here's what I see from the user's org memberships:
testorg
org memberships only has system permissions
testorg2
org membership permissions shows the teams
and dashboard
permissions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but the callout is talking about if you do a permission check, it will fail even if the user has the permission if the user's organization is not subscribed to the plan that has the feature
If not, the authorization check will always return
false
, even if the user has the custom permission.
but that's not true from what i tested o.O
…ckauthorization method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is good to go for now!
feel free to merge 😸💖 |
🔎 Previews:
What does this solve?
Linear: https://linear.app/clerk/issue/DOCS-10913/permissions-info-in-docs-outdated
The Dashboard has changed significantly since many of the docs around permissions were first written.
org:
prefix, which is still used in code and docs. But also,org:
gets added automatically now, so users don't need to enter the required format oforg:<role>
for e.g.What changed?
org:
prefix vs what's in the actual code when checking permissions.Note: One thing I'm unsure about is the docs mention "Custom permissions"; but on the Dashboard, it is now called "Feature permissions". I had originally changes all the "custom" for "feature", but I feel like custom permissions is so much more user friendlier to understand, especially compared to system permissions.
Checklist