I have an Identity service that handles everything related to authentication – registration, confirmation, issuing JWT tokens, etc. Implemented using Microsoft Identity framework with EF Core stores. Supports refresh token functionality. Bearer tokens expire in 1 hour, refresh tokens – in 30 days.
There are multiple services that require authorization, they consume tokens.
Now I need to implement a simple permission system. There are multiple permission scopes, every one of which has multiple permissions, e.g., Article scope with permissions to Post, Review, Edit, Publish an article, etc.
Implementing permissions using claims seems to be very easy. Just add a corresponding claim to a user and ask them to sign out and in again (or just wait till their token expires) and that's it. Everything is done inside a single service (Identity) and all other services will know about the change from the new token.
But as far as I can see there's no way to revoke a permission without maintaining some sort of database of revoked tokens. Since simply removing the claim from a user would not invalidate their current token, every service would have to have access to the said database and validate every single request, even though a revoking of permission is a rare event. Seems like a waste of resources and a potential single point of failure.
Implementing permissions with simple database records (UserId – PermissionScore – Permissions (bitstring)) is harder, because adding or revoking a permission would require Identity service to send a message to all interested services, so that they can add/modify/delete a corresponding record in their own databases (so that validating whether a user has a necessary permission or not does not require a communication with the Identity service – just a simple db query instead).
So how should I do it? Maybe there are some other options?
Should I just use claims and hope that nobody would maliciously use this "permission revoked but not quite" time window? I mean, claims are kind of for this exact purpose, right? There's always a nuclear option of invalidating a signing key, if necessary.