What is your best practice guidance for a Rails API - use an opaque or JWT-based access token?

Hi @declan,

Thanks for posting your questions!

The short answer is if your SPA is using your own custom API, then the Access Token you receive from Auth0 during authentication will be a JWT.

When you provide an audience with the authentication request, then Auth0 will provide you with a JWT Access Token so that your custom API can access helpful metadata such as expiration and any custom claims, etc. If you do not provide an audience, then the Access Token consumer is your Auth0 tenant’s /userinfo endpoint. This API happens to use opaque tokens, but this may or may not change.

Here is a good explanation from a similar topic:

  • When it says “applications” is it referring to the JS SPA application only (ie. not the Rails API part of the stack)? For surely the Rails API necessarily must attempt to decode them (assuming they are JWTs in this case)?

Yes, just the SPA Application only. Whether the Access Token is intended to be used to access data from your custom API or your Auth0 tenant’s /userinfo endpoint, the SPA does not need to analyze the token. It will simply send the Access Token with requests as a bearer token.

  • Or is this line saying that the best practice is that the JS SPA application should send opaque access tokens (instead of JWT access tokens) to the Rails API?

It is best practice and follows OIDC protocol to use JWTs for ID tokens, but as far as Access Tokens, it just depends on the contract between the authorization server and the resource server (the API in this example).

It might help to know about the background behind ID Tokens and Access Tokens. OAuth2 is a protocol that serves as an authorization layer that allows users to grant access to applications (the SPA in this case) to use their protected resources (data managed by the API in this example) through an authorization server (Auth0). If following OAuth2 alone, authorization can be granted to the client (the SPA) without the user ever exposing their identity.

OIDC is an identity layer built on top of OAuth that allows applications actually to authenticate. This is where the ID Token comes into play.

When the user authenticates with Auth0, Auth0 will provide an Access Token and an ID Token. The client (the SPA) can validate the ID Token and use it to ensure that the user successfully authenticated with the authorization server (Auth0). Since the ID Token is always a JWT, the client can decode it to get data about the user.

However, as far as the Access Token goes, the client (the SPA) does not care about it since it is between the Resource Server (the API) and the authorization server (Auth0). It can simply pass it along with API requests.

Similarly, the resource server (API) does not have to be concerned with who the user is. It simply needs to ensure that the Access Token aligns with its agreement with the authorization server (Auth0).

Here is a diagram of the OAuth2 Authorization Code flow with PKCE:

  • The big question is - once the Rails API receives a JWT-based access token (and validates the access token and, optionally, calls a user info endpoint) is there anything else it needs to do before it begins to use information in that access token? To me, the wording in the docs above is ambiguous/confusing in this regard.

Validating the token and following the example in the Ruby on Rails QuickStart should be sufficient.

Auth0 issues JWTs when you provide an audience to your custom API. Opaque and JWT Access Tokens follow the protocols. (As long as the ID Token is a JWT)

Auth0 will provide a JWT in this scenario.

Hope that helps answer your questions!

Stephanie

2 Likes