The main issue you’re facing and something that our documentation may also contribute to although we’ve been trying to make things more explicit is the overloaded use of JWT.
The reality is that when it comes to authentication and authorization the tokens/assertions passed from one entity to the other cannot be reduced to just the format used to represent them.
In the situation I believe you are, you have a client application (SPA) that performs the business logic by invoking a resource server (API) and wants to do so on behalf of an end-user. This is the textbook example for the use of OAuth 2.0 as the means for the client application to obtain an access token (forget about the format used for the representation of that access token) that it can then use to call the resource server. The resource server will validate the access token and through that validation process obtain the end-user that originally granted this access token.
In the above scenario there is absolutely no processing of the access token by the client application; it’s treated as an opaque token that gets received from the authorization server (in this case Auth0 service) and then sent to the resource server (your API).
Having said that, as part of the process to obtain the access token it’s highly likely that the end-user had to complete an authentication step so that the authorization server knows for whom to associate the access token. However, your client application can also express the desire to know about this end-user (this is where the OpenID Connect specification comes in) and in this case the identity provider/authorization server can issue not just an access token, but also an ID token that contains information about the completed authentication process. By specification the ID token will always be a JWT so here’s where both terms can start to get used interchangeably when they should not.
- an ID token is meant to be consumed/decoded and validated by the client application and it will always be represented using the JWT format.
- an access token is delivered to a client application, but the client application must treat it as an opaque value. In addition, the format used to represent access tokens is an implementation detail between the authorization server and the resource server to which they are meant to.
Sidenote: When you configure your own resource server in the APIs section of the dashboard and then request an access token for that resource server then currently the format being used is also a JWT, but have in mind that other formats may be supported in the future.
Further relevant reading: