Current dev work is almost complete for implementing authorisation with JWT token for all resources! This will be part of the upcoming Beta release.
The ticket can be viewed in Gitlab.
This will replace the existing alpha version of a custom token and token TTL for each user in the user table.
It is quite important to note, before we move on, that JWT tokens are a different thing to oauth2, implicit grant, explicit grant, application grant and PKSE authorisation flow. JWT is only a standard for tokens. If you need to implement oauth2 or other similar workflows this is separate from the JWT implementation.
The problem
The problem with the former approach, was that resource requests had to make DB calls to the user, user_roles, roles, account and application tables in order to verify user permissions to that particular resource, FOR EVERY API CALL. This obviously negatively impacted performance for API calls.
This also meant that authorisation was not easily scalable to authorisation servers for enterprise implementation, because the implementation of the token and authorisation for API calls was tightly coupled to the ApiOpenStudio database and several of its tables.
The solution
Although the former approach was stateful (it maintained login state, so users could login and out), the stateless JWT token approach means that the token does not need to be stored in the database. The downside of stateless JWT tokens, is that there is no logout state. So if a user’s access is revoked, they will still have access to resources until their current token goes stale.
However, this can be mitigated by making the JWT token lifetime short in the ApiOpenStudio configuration.
Each JWT token contains custom claims for user ID and all roles that that user has. So when the initial request is received by ApiOpenStudio, it just decrypts the token and validates the user’s roles against the resources account/application and permissible user roles (i.e. Does the current user have the required role access to the account & application?).
Knock-on effects
The following processors have been retired:
Nearly all core resources have been updated use the new processors:
- generate_token (generate a valid JWT token for a user, with custom claims: uid, user roles).
- validate_token (validate the Authorization token as a valild JWT token).
- validate_token_roles ((validate the Authorization token as a valild JWT token and also validation the user has the correct role permissions for the resource).
- bearer_token (not used by core atm, but preserved for any processors that need access to the bearer token).
Processors have been optimised, now that they do not need to do any pre-validation on who can do what – this is left to the core resource definitions.
Tests are updated to incorporate the changes, and also now have multiple test users with different roles.
The good news
Not only has this significantly improved the API response time, it has now made the API much more scalable for enterprise. We communicated and researched several major 3rd party authorisation services, including auth0, to make sure that the decision to move to JWT tokens and custom claims would still be viable if a 3rd party auth server was used.
Most 3rd party authorisation services implement linking into external databases, so that would take the heat off the api server for token generation, and allow the token generation to be completely decoupled from ApiOpenStudio. This will be the subject of a future post.