Is claims based authorization appropriate for individual resources

When you are talking about roles and permissions then you are talking about authorization.

Claims are typically not for authorization. (Identity)Claims are there to model the identity of the user: who is the user? The claims on itself do not tell anything about authorization. A user can have a role claim, but this doesn’t tell the application what the user is allowed to do.

Authorization is done by the application, based on who the user is. Think of authorization as a set of rules, like:

  • 18+: allow when user is older than 18 (DateOfBirth).

  • Use car: allow when user has a drivers license.

Or something like that.

Roles are a bit confusing, as they are often misused for authorization. Please read this article for some background information.

The problem with roles IMO is that these are not universal. I can be a Doctor in one hospital, while I’m a Patient in another. And I can be Admin for one tenant, but a User for another tenant. So they have only meaning within a certain context.

The only reason to include roles as claim is that you won’t need to lookup this information as it is already present. But given the previous remark, you actually can’t include this information. And it will only give you headaches when you do. Because you can’t do simple things like update or change permissions or profile settings, until the user logs in again.

So as a rule of thumb: keep authorization close to the resource (api / website). Because that is the place where the business rules are implemented. And that’s the place where you can store and update permissions, etc.

Keep a seperation of concerns when it comes to authentication and authorization. Authentication tells you who the user is, and authorization tells you what the user is allowed to do. Don’t mix these two.


Translating this to your wiki application:

Create a seperate context where you store authorization information like roles and permissions. You can manage this in a central resource (for multiple applications) or use the context in your application. I would not mix this context with the business context.

Add a user in the authorization context and add a role content_contributor. Within the application read the permissions (from the central API, the local authorization context, a settings file, or anything that suits best) for that user (based on the sub claim). Cache it to speed up performance, and apply the rules to determine whether the user is allowed to access the resource.

You can extend this with resource-based authorization. Save the value of the sub claim in the content record to identify the owner. When the current user matches the sub claim value, then the current user is the owner.

You can use the same approach for teams. Add a teams table to the business context and link the user to one or more teams. Directly using the sub claim value or indirectly, using a Users table, also in the business context, where the user is linked to the sub claim value. You can add name, etc. in case you want to show this information (like in a report).

You can save team id and / or user id or sub claim value (owner is member of the same team as current user) in the content record in order to determine the allowed access for the user.


My setup would be like this:

Identity context: users + userclaims. For authentication only. Application independent.

Authorization context: users (id = sub claim) + per application: roles, permissions, etc. In seperate ‘local’ databases or in a central database. For authorization only.

Business context: users (Id, Name, ‘foreign key’ sub claim, without the actual database relation as the table is outside the context) + teams, profile, settings, etc. Linked to the sub claim value when users table is omitted.

In order to keep the users table in the business context up-to-date, periodically refresh the values. You can for instance update values when the user logs in after x time. Or once in a while query the Identity Context (using the API) to request user information (using the identities User Info endpoint).

In all contexts there can be a users table, but they all have a different meaning and contain other information. So there is no redundant information.

Authorization takes place inside the application and is based on the business rules (policies) and authorization information from the authorization context.

As a final remark, when the current system requires role claims (like for User.IsInRole() or [Authorize("role")]) then you can read (from cache) the role / permissions on each call and add these to the claims collection of the current user (claims transformation).

Leave a Comment