Auth0 Home Blog Docs

Scopes vs Permissions confusion

I’m new to Auth0 and getting a bit confused about scopes and permissions and how they relate.

A lot of the documentation implies that scopes are permissions, and that you should create scopes such as “read:messages” and “write:messages”.

But when you create Permissions in the API, and then request an Access Token from the front-end, these appear in a “permissions” claim but not in the list of scopes.

However if you create Permissions through the Authorization Extension, then they do appear as scopes in the Access Token and not as a Permissions claim.

How is this supposed to work and why is there this difference between the Authorization Extension and the way the main one works?

3 Likes

Hi @chrisj2,

here are some related threads on this:

1 Like

Thanks for those links. Reading them has made me even more confused, what is the correct behaviour supposed to be?

If I’m writing an API, do I need to check both the Permissions claim and the Scopes claim to determine permissions, because Auth0 might set them in one or the other depending on configuration?

The documentation is not clear about this, and seems to state that the Scopes claim has the permissions in it, whereas in reality the Permisions claim does.
For example, the sample code on this page:

doesn’t work for me because the permissions are not actually in the Scopes claim?

I’m trying to understand how things are supposed to work and what Auth0’s official position on this is?

2 Likes

Gonna +1 this. I am fighting with the same thing in the documentation right now. There is no clear guidance on what you’re supposed to do here.

I’m also using the ASP.NET Core API Quickstart, and it simply doesn’t work as written. First, it neglects to mention that you need to turn on RBAC and the option to include permissions in the access token. Finally got that done, but the HasScopeHandler class is specifically looking for the scope claim, where these come across as permissions.

What’s the correct path here?

3 Likes

+1 this as well, i am having exactly the same confusion.

1 Like

+1 from me too. I am also incredibly confused. That first thread provides a solution for the poster’s specific scenario, but doesn’t make clear the distinction between scopes and permissions. The behaviour seems really inconsistent.

I am back into this today trying to figure it out also. I tried to email support and didn’t ever get a clear answer. Trying to get an API that can validate the permissions of a M2M app and a user seems like such a simple requirement for Auth0 to fulfill, but it doesn’t work without major hoops to jump through.

I think the answer is to modify their code to first check for permissions, then move on to checking for the scope like they demonstrate. This seems to be working for me. Whether this is the correct approach, I have no idea since they won’t give a clear answer or update example. I’ll keep messing with this.

public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement)
    {
        // First check for permissions, they may show up in addition to or instead of scopes...
        if (context.User.HasClaim(c => c.Type == "permissions" && c.Issuer == requirement.Issuer && c.Value == requirement.Scope))
        {
            context.Succeed(requirement);
            return Task.CompletedTask;
        }

        // This is the Auth0 version, which only checks for scopes instead of permissions.
        // If user does not have the scope claim, get out of here
        if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
            return Task.CompletedTask;

        // Split the scopes string into an array
        var scopes = context.User.FindFirst(c => c.Type == "scope" && c.Issuer == requirement.Issuer).Value.Split(' ');

        // Succeed if the scope array contains the required scope
        if (scopes.Any(s => s == requirement.Scope))
            context.Succeed(requirement);

        return Task.CompletedTask;
    }
}
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.