Konubinix' site

What Should I Put Into Those Scopes and Access Tokens Claims?

Evergreen

After making sense of keycloak, openid connect, oauth 2.0, jwt, jws and understanding the creation of an OAuth 2.0/OIDC resource server, I feel that I understand well enough the “is”. I would like to focus on the “ought to”.

In other words, I want to use OAuth 2.0 for real, but I don’t know yet how to design my system. Here, I try to document what I could find in the internet that helped me.

TL;DR: I describe what I understand of how several sources do thing, then I give my opinion on how I would design such a system.

OAuth is very vague in the definition of the access token.

access token is a string representing an authorization issued to the client. The string is usually opaque to the client

https://datatracker.ietf.org/doc/html/rfc6749

It looks like, on top of this very non prescriptive definition, popular implementations have reached a consensus of using JWT/JWS to encode this token.

OAuth tried to catch up with this trend of encoding access token in JWT and finally (late 2021) tried to standardize a bit the JWT claims one could find in this token. It still is very vague. I assume that there are so many use cases that we cannot generalize them well in a standard.

If I understand correctly, the flow, when using OAuth and access tokens encoded in JWT/JWS, looks like this:

  1. an authorization server has access to a database of users1.
  2. a client connects to the authorization server with a scope and gets an access token that contains a set of claims,
  3. the client connects to a resource server with the set of claims. The resource server checks the validity of the token and infer from it which resource can be accessed.

So the question is: what kind of messages would I want to convey in the scopes and in the claims to have a sensible and maintainable system?

In my mind, this topic is particularly hard, because it asks questions at several dimensions (see the three worlds analogy).

  1. it needs to define some ontology at the authorization server side, to map roles/tenants/groups/users to some claims.
  2. it needs to define another ontology at the resource server side, mapping claims to permissions on resources.

Those two worlds need to be in sync and are most likely to be administered by two different kind of teams, with different horizons of focus.

Also, the definitions of those terms rely on the expected use cases of the users. So this definition must be done by a product owner as much as a technical team.

Another reason why this is a complicated subject is that the definitions of scope/users/group/role/tenant/permission/etc are generally a bit vague. Chances are that several appropriate interpretations of those terms lead to pretty different implementations. Due to the loose nature of the standard, one would be able to implement all those interpretations. Then, the choice of using one or another becomes arbitrary.

By looking at the literature, I can have a feeling of several ways of thinking those concepts. I can then pick what suits me.

According to OAuth

OAuth uses the traditional definition of permission and add the definition of privilege.

accessing the house is a permission, that is, an action that you can perform on a resource

[…]

permission becomes a privilege (or right) when it is assigned to someone.

https://auth0.com/intro-to-iam/what-is-authorization/

This definition of privilege supposes that we assign permission directly to users. I don’t agree at all with this and would rather talk about the path going from a user to roles/groups/tenants/claims to permissions. With that model in mind, a privilege would be whether a path exist or not. I don’t see the need (yet ?) to add this notion in the model but I keep it in mind in case that happens.

Afterwards, they define permission as a scope. Here again, I don’t understand the rationale supporting this statement. Maybe do they mean that permission gives access to a subset of the resources? If they don’t want to refer to oauth 2.0 scope, I think the wording was ambiguous.

permission is a scope, that is, the action that the decorator would like to perform at your house

https://auth0.com/intro-to-iam/what-is-authorization/

Then, they define roles as sets of permissions. I disagree with this point of view.

role is nothing but a collection of permissions.

https://auth0.com/intro-to-iam/what-is-authorization/

Actually, by looking at the following example, I think we agree on what should be in a role and that I just disagree on the wording “nothing but a collection of permissions” while I agree with the idea.

system manager would first create a role called “Manager” (or similar). Then, they would assign these permissions to this role and would associate you with the “Manager” role

https://auth0.com/intro-to-iam/what-is-authorization/

Indeed, they separate the step of creating a role and assigning permissions to it, which it exactly what I would expect of modeling a mapping from a role to a set of permissions. This, to me, supports the idea that it is only a semantic debate and that we fundamentally agree.

claims and relation to identity

They define a claim as something related to the identity, but used in a context of granting access. They remind that, for the claim to be useful, it has to be trustfully issued by a trusted third party.

Then, they indicate that this set of claims is actually an access token (more precisely a self-encoded access tokens, but they don’t go that far).

Sometimes authorization is somewhat related to identity.

[…]

In the authorization context, your name is an attribute of your identity. Other attributes are your age, your language, your credit card, and anything else relevant in a specific

[…]

claim, that is, a declaration stating you’ve got that attribute.

[…]

sure of your name because they trust the government that issued your passport.

[…]

boarding pass, along with the proof of identity of consumers, represents a kind of ‘access token’ that grants access rights to jump onto the plane.

https://auth0.com/intro-to-iam/what-is-authorization/

To me, they make the confusion between:

  1. a claim as an attribute about the user identity,
  2. a JWT claim as a key/value given to the resource server to assess whether the access is granted or not,

To me 1. is a subset of 2.. Indeed, you may well find scopes or roles or tenants information in the latter, and I doubt they mean that those belong to “a declaration stating you’ve got that attribute”. Hence, I think by “somewhat related to identity”, they mean 1.

But, when they indicate that the claims must be issued by trusted third party, I think they mean all the claims of 2., not only the claims of 1.

Again, this is a semantic debate and I agree in principle, but making this confusion clear helps me have clear ideas of the concepts and take appropriate decisions.

authorization strategies

They differentiate between several authorization strategies, among those RBAC and CBAC (that they call ABAC).

several different authorization strategies that computer systems leverage during application deployment. The most prominent ones are Role-Based Access Control (RBAC) and Attribute-Based Access Control (ABAC).

[…]

When using ABAC, a computer system defines whether a user has sufficient access privileges to execute an action based on a trait (attribute or claim) associated with that user.

[…]

RBAC, on the other hand, treats authorization as permissions associated with roles and not directly with users.

https://auth0.com/intro-to-iam/what-is-authorization/

Finally, they refer to more complicated strategies, like Relation Based Access Control. I’m still waaay too noob to understand this strategy, but it’s good to know as I might serendipitously come to that later.

Relationship Based Access Control examines the following question in regards to authorization: “Does this user have a sufficient relationship to this object or action such that they can access it?”

[…]

Sometimes a traversal of a graph of groups, roles, organizations, and objects requires exploring many nodes to establish a relationship between a user and what they are trying to do.

https://auth0.com/intro-to-iam/what-is-authorization/

In another document, they vaguely define the scope as a mean to restrict the data.

Scope is a mechanism to let an application request limited access to a user’s data.

https://www.oauth.com/oauth2-servers/scope/defining-scopes/

One important thing to notice here is that scopes are now considered as a mean to inform the resource owner about the kind of access that the client will have.

Therefore, defining scope becomes more a user experience topic rather than a technical topic. It adds to the idea that authorization is at the boundary between handling the user and technology.

challenge when defining scopes for your service is to not get carried away with defining too many scopes. Users need to be able to understand what level of access they are granting to the application, and this will be presented to the user in some sort of list.

[…]

need to actually understand what is going on and not get overwhelmed with information. If y

https://www.oauth.com/oauth2-servers/scope/defining-scopes/

Then, they provide a few examples of typical uses of scopes.

Read vs write access is a good place to start

[…]

Restricting Access to Sensitive Information

[…]

scope that allows applications to have access to private repos.

[…]

scope that allows applications to delete repos, so users can rest assured that random applications can’t go around deleting their repos.

[…]

way for applications to restrict themselves to only be able to edit files in a single folder.

[…]

great use of scope is to selectively enable access to a user’s account based on the functionality needed

[…]

Limiting Access to Billable Resources

[…]

This means applications that need to access the YouTube API won’t necessarily also be able to access the user’s Gmail account

https://www.oauth.com/oauth2-servers/scope/defining-scopes/

To me, it looks like there a plenty of ontologies around scopes. Scopes are not defined according to some technical constraint but rather according to how we want to define users journeys.

No wonder why I could not guess any satisfying teleological definition.

Actually, now I understand better the following quote:

OAuth does not define any particular values for scopes, since it is highly dependent on the service’s internal architecture and needs.

https://oauth.net/2/scope/

They advice to take a look at how google defines scopes for inspiration.

Google’s API is a great example of effectively using scope. For a full list of the scopes that the Google OAuth API supports, visit their OAuth 2.0 Playground at https://developers.google.com/oauthplayground/

https://www.oauth.com/oauth2-servers/scope/defining-scopes/

I took a look at them later in this document.

According to Microsoft windows active directory

They the vocabulary of OAuth 2.0, except that they call the resource server simply resource.

There are two parties involved in an access token request: the client, who requests the token, and the resource (the API) that accepts the token when the API is called

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#claims-in-access-token

I think this is to reflect the notion of resource that we can find in REST.

resource R is a temporally varying membership function MR(t), which for time t maps to a set of entities, or values, which are equivalent

https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

But to me, this is confusing, because apart from the conceptual notion of REST resource, the party that accepts the token is actually the OAuth 2.0 resource server, not the resource itself.

Actually, I think their ontology is a bit confusing, so I would not recommend using it as inspiration. Nonetheless, I find their model quite interesting.

check the user identity

The user is identified with sub and oid JWT claims.

sub
String The principal about which the token asserts information, such as the user of an app. This value is immutable and cannot be reassigned or reused. It can be used to perform authorization checks safely, such as when the token is used to access a resource, and can be used as a key in database tables. Because the subject is always present in the tokens that Azure AD issues, we recommend using this value in a general-purpose authorization system. The subject is, however, a pairwise identifier - it is unique to a particular application ID. Therefore, if a single user signs into two different apps using two different client IDs, those apps will receive two different values for the subject claim. This may or may not be desired depending on your architecture and privacy requirements. See also the oid claim (which does remain the same across apps within a tenant).
oid
String, a GUID The immutable identifier for the “principal” of the request - the user or service principal whose identity has been verified. In ID tokens and app+user tokens, this is the object ID of the user. In app-only tokens, this is the object ID of the calling service principal. It can also be used to perform authorization checks safely and as a key in database tables. This ID uniquely identifies the principal across applications - two different applications signing in the same user will receive the same value in the oid claim. Thus, oid can be used when making queries to Microsoft online services, such as the Microsoft Graph. The Microsoft Graph will return this ID as the id property for a given user account. Because the oid allows multiple apps to correlate principals, the profile scope is required in order to receive this claim for users. If a single user exists in multiple tenants, the user will contain a different object ID in each tenant - they are considered different accounts, even though the user logs into each account with the same credentials.

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#claims-in-access-token

They clearly state that the JWT claims are to be used in the database of the resource server to perform future authorization checks.

check the user group and tenant

To allow multi tenancy, they simply add another JWT claim, the tid.

tid
String, a GUID Represents the tenant that the user is signing in to. For work and school accounts, the GUID is the immutable tenant ID of the organization that the user is signing in to. For sign-ins to the personal Microsoft account tenant (services like Xbox, Teams for Life, or Outlook), the value is 9188040d-6c67-4c5b-b112-36a304b66dad. To receive this claim, your app must request the profile scope.

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#claims-in-access-token

This information is use to check access. For instance, data put by a user is expected to be read only by other users belonging to the same tenant.

Check that the tid inside the token matches the tenant ID used to store the data in your API.

When a user stores data in your API from one tenant, they must sign into that tenant again to access that data. Never allow data in one tenant to be accessed from another tenant.

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#claims-in-access-token

make clear immutable and mutable claims

They warn against JWT claims that may change in the profile of the user, such as the email. Using them to get access to the data is very risky.

  • Do use immutable claim values tid and sub or oid as a combined key for storing for uniquely identifying your API’s data and determining whether a user should be granted access to that data.

    • Good: tid + sub
    • Better: tid + oid - the oid is consistent across applications, so an ecosystem of apps can audit user access to data, for instance.
  • Do not use mutable, human-readable identifiers like email or upn for uniquely identifying data.

    • Bad: email
    • Bad: upn

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#claims-in-access-token

check that the user has appropriate responsibilities

They define roles as “lists of permissions”. I don’t agree with the wording, but I think they mean that the resource server checks the roles to find out whether the token bearer has access to the API. Actually, they use interchangeably “set” and “list” here.

They add two JWT claims to do so : wids and roles.

roles
Array of strings, a list of permissions. The set of permissions exposed by your application that the requesting application or user has been given permission to call. […]
wids
Array of RoleTemplateID GUIDs Denotes the tenant-wide roles assigned to this user […]

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#claims-in-access-token

The resource server is supposed to check the roles to find out whether the token bearer can have access to the resource.

Also, they provide an example of role: “admin”. To me, this corroborates the idea that we agree on what a role is, even though we don’t agree on the wording.

Use the roles and wids claims to validate that the user themselves has authorization to call your API. For example, an admin may have permission to write to your API, but not a normal user

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#claims-in-access-token

Another interesting things to note is that they use role and group as if they were similar concepts.

If you’ve requested the roles or groups claims in the access token, verify that the user is in the group allowed to do this action.

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#claims-in-access-token

In my model, groups are about links between users, where roles are more about responsibilities. I eventually agree that both should be checked to assess resource access.

check that the token has appropriate scope

They encourage to check the scope of the token to ensure you are using a token that is indeed issued to get access to the appropriate data.

To do so, they use the JWT claims scp.

Use the scp claim to validate that the user has granted the calling app permission to call your API

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#claims-in-access-token

It should be noted that they follow the advice of JWT to have small claim keys to keep the token compact.

claim names are only three characters long as JWT is meant to be compact

https://jwt.io/introduction

According to Microsoft azure multinenant documentation

They explain that access control is typically not following one scheme but several in combination. They make the distinction between role/resources and permissions.

typical app will employ a mix of both (Role Based Access Control and Resource based access control). For example, to delete a resource, the user must be the resource owner or an admin

[…]

a good approach is to aggregate all of the user’s role-based and resource-based permissions, then check the aggregate set against the desired operation

https://docs.microsoft.com/en-us/azure/architecture/multitenant-identity/authorize

They use the tenantId JWT claim to ensure the user only has access to resources belonging to pers tenant. Interestingly, they don’t use tid, like in windows active directory. And don’t follow the advice of having as small JWT claim keys as possible.

you must ensure that permissions don’t “leak” to another tenant’s data.

[…]

you can assign someone from another tenant as a contributor

[…]

other permission types are restricted to resources that belong to that user’s tenant

[…]

enforce this requirement, the code checks the tenant ID before granting the permission

[…]

TenantId field as assigned when the survey is created

https://docs.microsoft.com/en-us/azure/architecture/multitenant-identity/authorize

According to some stackoverflow questions

By looking at stackoverflow questions, I could find some other valuable food for thoughts.

permissions and relation to roles and groups

A point of view is to define a role as the link between a set of users and a set of permissions.

On one hand, a Role is a collection of Permissions. I like to call it a Permission Profile. When defining a Role you basically add a bunch of Permissions into that Role so in that sense a Role is a Permission Profile.

On the other hand, a Role is also a collection of Users. If I add Bob and Alice to the Role “Managers” then “Managers” now contains a collection of two Users sort of like a Group.

The truth is that a Role is BOTH a collection of Users and a collection of Permissions put together. Visually this can be viewed as a Venn diagram.

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

This distinguishes roles from groups, that are only groups of users.

Group = Collection of Users

A “Group” is strictly a collection of Users. The difference between a Group and a Role is that a Role also has a collection of Permissions but a Group only has a collection of Users

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

In this point of view, a permission is something that can be done: it is a verb.

What is a Permission

Permission = What a subject can do

What is a Permission Set

Permission Set = A Collection of Permissions

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

Then, Permissions, Permission sets, Users and Groups can be added to a Role.

claims and relation to identity

It is emphasised that claims are intrinsically about the resource owner. It answers the question “What does the token claim about the user that should help decide whether per is allowed or not?”

What Are Claims

Claim = What a Subject “is”

Claims are NOT Permissions. As pointed out in previous answers, a Claim is what a subject “is” not what a subject “can do”.

Claims do not replace Roles or Permissions, they are additional pieces of information that one can use to make an Authorization decision.

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

It is explained that claims are useful to reflect the mutable nature of access granting, were some arbitrary mapping to roles is not enough.

Claims to be useful when an Authorization decision needs to be made when the User cannot be added to a Role or the decision is not based on the association of User to Permission

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

authorization strategies

It is suggested that roles are one particular kind of JWT claim. Therefore RBAC is a specific implementation of CBAC. An example is given to show that sometimes, claims (a.k.a. user intrinsic properties) make more sense than roles.

RBAC vs CBAC

Ok, now, if you ask what is the benefit of Role-based access control or Claim based access control, then, think about this page “ViewImagesOfViolence”. Is not it more intuitive to check for a claim “Adult-over-18years” when determining if you should allow the user to visit that page? In a word, using Claims, you can create more segments within your users comparing roles. In an abstract sense, all roles can be claims too, but claims cannot be thought of as roles.

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

Another example is given with more depth : the nightclub metaphor. If the resource server is a night club, the client is the person that wish to enter the night club and the access token is the driver’s licence, then the bouncer checks the claims of the driver’s licence to assess whether the client can get access to the night club.

In that case, the age of the person, hence an intrinsic property, is used to decide whether the resource can be accessed or not.

@CodingSoft used the night club metaphor in a previous answer, which I’d like to extend. In that answer, the Driver’s License was used as an example that contained a set of Claims where the Date of Birth represents one of the Claims and the value of the DateOfBirth Claim is used to test against the authorization rule. The government that issued the Driver’s License is the authority that gives the Claim authenticity. Therefore, in a night club scenario, the bouncer at the door looks at the the person’s Driver’s License, ensures that it was issued by a trusted authority by examining whether or not it is a fake ID (i.e. must be valid government issued ID), then looks at the Date of Birth (one of the many claims on a Driver’s License), then uses that value to determine if the person is old enough to enter the club. If so, the person passes the authorization rule by virtue of having a valid Claim, not by being in some Role.

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

Moreover, this metaphor is extended to show that adding roles helps crafting a finer grained authorization model.

Now, with that base in mind I’d like to now extend that further. Suppose that the building where the night club is contains offices, rooms, a kitchen, other floors, elevators, a basement, etc. where only employees of the club can enter. Furthermore, certain employees might have access to certain places that other employees may not. For example, a Manager may have access to an office floor above that other employees cannot access. In this case there are two Roles. Manager and Employee.

While visitors’ access to the public night club area is authorized by a single claim as explained above, employees need access by Role to other non-public restricted rooms. For them, a Driver’s License is not enough. What they need is an Employee Badge that they scan to enter doors. Somewhere there is an RBAC system that grants badges in the Manager Role access to the top floor, and badges in the Employee Role access to other rooms.

If for whatever reason certain rooms need to be added/removed by Role, this can be done using RBAC, but it is not a good fit for a Claim.

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

Also, it is proposed to take care of not coupling JWT claims and permissions. This is called: Permission-Based access control.

It describes that the resource server should not directly check the JWT claims but map them to permissions (read, write, update) and assign permissions to the endpoints. That way is supposed to ease modeling and maintaining the access control.

Permission-Based access control is a way of assigning various permissions to various users or various roles or various claims and checking if a user has permission to execute an action from the code in run time. If you assign permission to a role or a claim, then, you would check what are the roles or claims for that logged-in user. And then, you will check what permissions are available for those roles or claims.

[…]

roles can be thought of as claims too. So, you can treat the roles as claims. Then, you can create a table of Claims in your database. Then, create another table for holding the relations where each claim can contain multiple permissions.

[…]

more control of your security logic in your application if you apply permission-based access control.

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

It is recommended not to assign sets of permissions to a users, which is exactly what the model “role == sets of permission” would imply. So I think that this is linked to the semantic debate mentioned earlier and I tend to agree with what is written here.

You can assign a set of permissions directly to a user. But do not do that. It will be tremendously difficult to manage that. Rather, you can assign a set of permissions to a Role Or you can assign a set of permissions to a Claim (Recommended).

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

It is emphasized that the resource server should not assign roles to resources but rather use the intermediate notion of permission.

Coding Roles into the application is a bad idea. This hard codes the purpose of the Role into the application. What the application should have is just Permissions that act like Feature Flags. Where Feature Flags are made accessible by configuration

[…]

This way, there is no hard coding of Roles and the only time a Permission changes is when it is removed or a new one is added. Once a Permission is added to the software it should never be changed. It should only be removed when necessary (i.e. when a feature is discontinued in a new version) and only new ones can be added

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

In the end, a picture is shown to show the big picture with all that in mind.

https://stackoverflow.com/questions/22814023/role-based-access-control-rbac-vs-claims-based-access-control-cbac-in-asp-n#2281988

My opinion

Here, the objective is to find a framework that allows to think authorization and produce meaningful arguments to decide what to put in the self-encoded access tokens.

I decide to use the following definitions :

the token scope
related to the token and used to avoid issuing individual tokens with too much access, limiting its impact on the resources (in case it becomes stolen for example). The ontology of the scope should depend on use cases. If for example, the user is expected to get access to resources of kind X and then use them to update resources of case Y, it makes sense to have a scope “X -> Y” that provides read access to resources of kind X and write access to resources of kind Y. Also, the scope is shown to the user to ask per whether the scope should be granted. That means that the scope name is not only some technical stuff but also a user experience concept. In other terms, the scope is the way for the user to tell the authorization server what access to grant to the client.
the users group and tenant
anything giving information about the social groups the users is in. For instance, a user might be given the right to get access to all the resources of some kind created by all the users of per tenant.
commitment
whatever the user has been committed to get done. This concept is not actually discussed in implementing authorization because we generally only need to know about access to make a decision. Yet, I think it helps to understand why the user needs those access at first.
commitments
sets of commitments the users has with relativity to the resource. People generally call those “roles” (see RBAC) but I think this is an oversimplification of the notion of commitment.
claims
not to be confused with the JWT claim. Intrinsic properties of the user, like the age or some unique identity (see CBAC). For example, resources might be available only to adults (age >= 18 in France).
JWT claim
all the key/value data that are stored in a token encoded using JWT, and might actually convey information about claims, but also roles, scope or groups.
actions
whatever can be done on a resource, like create, read, update, delete.
permission
predicate telling whether an action is granted over a resource

Now, there are a few expectations that are to be met.

The resource server uses JWT claims to define the permissions.

The resource server has to keep track of the association between the created resources and some JWT claims. This will be needed to decide future permissions. For instance, imagine you create a resource server where all users of the same tenant share the same resources. When a user from tenant T creates a resource R, the resource server must record the association T->R. Then, when another users from the same tenant T claims access to the available resources, the resource server must return R.

This means that the resource server “pollutes” its database with some concepts that come from the authorization server. I am ok with this.

Also, this means that the mutability of the JWT claims must be very clear, as changing some JWT claims values might break the links in all the resources servers. For example, using the email JWT claim in the resource server to check access might be dangerous in case the email is subject to change.

Side note about how I reason about roles

Another popular definition is that roles are actually sets of permissions. I don’t like it because it hides the more traditional meaning of role as commitment. May be this is because I consider myself a gtd practitioner, in my opinion, roles are particular cases of area of focus.

For instance, being a technical lead, I know the difference between

  1. my role that implies stuffs that I need to maintain, like, among other things
    1. train the newcomers,
    2. ensure the CI still works,
    3. ensure coding best practices are known,
  2. and the permissions that I am granted that should allow me fulfil that role
    1. access to the collaborative tools administration console,
    2. permission to take time not working on the code to prepare training materials,

Also, I think we all are confronted, one day or another, with sets of permissions that don’t allow us to correctly fulfil our roles. In that case, we have to clarify both and ensure that either the role is renegotiated or some other permissions are granted.

Therefore, I assume we all agree that the concept of role cannot be reduced to a set of permissions in real life.

Hence, to ease reasoning with the concept of role in authorization delegation, I think it is more appropriate to reflect those real life concepts and consider that roles can be associated to sets of permissions.

Of course, I don’t mind people taking the shortcut of considering a role as a set of permission. To me, both are is equivalent with respect to the objective of controlling access. I’m just arguing that I won’t.

Actually, by digging into the examples, I think that we end up thinking of the same thing, but with different words, and that this is more of a semantic debate. In the end, it is mostly a matter of taste.

Make the authorization server aware of the data?

In all the literature I read, only the resource servers knew about the resources. The authorization server does not know whether the resources will be X or Y and in particular does not know about specific instances, like X1, X2…Xn.

Also, a part of the authorization server ontology transpires into all the resource server as they have to keep track of JWT claims.

This means that changing the authorization strategy in the authorization server implies to migrate the data in all the resource servers. Imagine you have a single tenant application and decide to make it multi tenant. You first have to go to all the resource servers to add the tenant id column and migrate the data. This might be cumbersome.

To mitigate this, some might be tempted to inverse the logic and make the authorization server aware of the resources. That way, the resource server only knows about the resources and migrations of strategies only impact the authorization server. This means that the authorization server database should be big enough to store the order of magnitude of the resource servers time the amount of data in each resource server. This looks pretty cumbersome as well. Also, the authorization would have to convey resource information to the resource servers. In the case of using self-encoded access tokens, this would lead to pretty big tokens, which is contrary to OAuth 2.0 initial idea.

I guess that there is no ideal solution and a compromise needs to be done.

Actually, I feel like making the authorization server resource aware looks the worst. Plus, no popular implementations I read does this hence it might be harder to find food for thoughts in the literature. Finally, it looks the least compatible with the OAuth 2.0 idea of separating the authorization server from the stack. If one would really want to do it, I would advice looking for others authorization delegation standards than OAuth 2.0.

Some definitions of scopes in well known implementations

To me, scopes are one of the most tricky concept to implement, because they are at the frontier between user experience and security.

Let’s see how some popular implementation defined them, to get some food for thoughts.

OpenID Connect

OpenID connect is mostly about getting access to the resource owner’s data. Hence, it looks natural that its scopes are about several kind of information based on the nature of the data.

OpenID Connect defines the following scope values that are used to request Claims:

profile
OPTIONAL. This scope value requests access to the End-User’s default profile Claims, which are:
  • name,
  • family_name,
  • given_name,
  • middle_name,
  • nickname,
  • preferred_username,
  • profile,
  • picture,
  • website,
  • gender,
  • birthdate,
  • zoneinfo,
  • locale,
  • updated_at.
email
OPTIONAL. This scope value requests access to the email and email_verified Claims.
address
OPTIONAL. This scope value requests access to the address Claim.
phone
OPTIONAL. This scope value requests access to the phone_number and phone_number_verified Claims.

https://openid.net/specs/openid-connect-core-1_0.html

slack

Slack’s scopes are more about separating the kinds of actions and resources and the permissions on them. They also let the roles transpire into the scope.

When a user is responding to your OAuth request, the requested scopes will be displayed to them when they are asked to approve your request

[…]

Slack uses scopes that refer to the object they grant access to, followed by the class of actions on that object they allow (e.g. ). Additionally, some scopes have an optional perspective which is either user, bot, or admin, which influences how the action appears in Slack (e.g. chat:write:user will send a message from the authorizing user as opposed to your app).

https://api.slack.com/legacy/oauth-scopes

google

Google appears to follow a same similar strategy, but they also have scopes gathered into namespaces that convey the names of the products.

They remind that scopes are not a tiling of possibilities, hence better use a scope without accesses that you don’t need.

Many scopes overlap, so it’s best to use a scope that isn’t sensitive

https://developers.google.com/identity/protocols/oauth2/scopes

Here are a few example of scopes found at google. We can see a mix of namespaces, permissions, functions and resources.

https://www.googleapis.com/auth/cloud-platform.read-only

https://www.googleapis.com/auth/tagmanager.readonly

https://www.googleapis.com/auth/youtube

https://www.googleapis.com/auth/youtube.channel-memberships.creator

https://www.googleapis.com/auth/youtube.upload

https://developers.google.com/oauthplayground/

We can appreciate that this mixes the nature of the resource, the responsibilities of the user and user expected journeys.

One interesting example is at google drive.

https://www.googleapis.com/auth/drive.appdata
View and manage its own configuration data in your Google Drive
https://www.googleapis.com/auth/drive.file
View and manage Google Drive files and folders that you have opened or created with this app2

https://developers.google.com/identity/protocols/oauth2/scopes#drive

Those scope clearly reflect a classical use case of storing app data without disturbing the user’s data. This reflects the fact that scopes are mostly driven by expected user journeys.

fitbit

Fitbit uses scopes to tile the kind of data to consider.

scope: A space-delimited list of data collections requested by the application

[…]

“scope”: “social settings heartrate nutrition sleep activity profile location weight”

https://dev.fitbit.com/build/reference/web-api/developer-guide/authorization/

Here, the scope is quite simple: a tiling of the resources by nature.

Notes linking here


  1. We can imagine that those users can be gathered in groups and assigned to roles

     ↩︎
  2. but those will be visible by the end user ↩︎