I have an Auth0 Native application, used by a React Native mobile app, for which Auth0 provides credentials with an encrypted accessToken and an idToken. I can use the access token to call the /userinfo endpoint. And I can decode the ID token to see the user’s details. The mobile app communicates with a backend over HTTP. I can send the ID token to the backend and verify it using JWKS, checking that the iss and aud claims are correct for the Native application.
All this works fine but I have two concerns:
I don’t know how to generate an ID token for testing purposes, to allow me to call my backend during development with cURL or Postman.
I have read in multipleplaces that ID tokens should not be used to call APIs – and yet this is exactly what I am doing.
On my development tenant, I made an application that uses the implicit grant type and I pull the token from the search bar. Do not do this in a production environment.
The token you should be using to call APIs is the access token. The access token tells the API what the user is allowed to do. The id token says who the user is.
That’s correct, you shouldn’t be using an ID Token to make calls to an API - The ID Token represent Authentication and not Authorization.
Are you able to elaborate on your test case a bit? Is there a reason you are using the ID Token rather than the Access Token received in the login flow? Again, you should be using an Access Token here.
Thanks for your replies. Please bear with me because I really want to understand why it is insecure to use the ID token:
isn’t the fact that my frontend and backend communicate over HTTP an implementation detail? If my app was fully server-rendered – or fully client side – there would be no API.
Conversely, an API expects a token with the aud value to equal the API’s unique identifier. Therefore, unless you maintain control over both the application and the API, sending an ID token to an API will generally not work. Since the ID token is not signed by the API, the API would have no way of knowing if the application had modified the token (e.g., adding more scopes) if it were to accept the ID Token.
I do control the mobile application and the HTTP API. I can verify that the aud of the token matches the client ID of the application and I can verify that the token was signed by Auth0.
My application doesn’t require roles or scopes: every user has the same permissions, but only over their own data. Therefore authentication is all that is needed.
I’ve got it working now with an access token. For anyone else who comes here:
You need to create a separate Application and API in Auth0.
Then in your mobile app, you set it up with the client ID of the Application but also pass the Identifier (not Id) of the API as the audience. For the react-native-auth0 package I couldn’t find this documented anywhere and I had to trawl through the source code to find the correct way to do it:
Now the accessToken is an unencrypted JWT rather than the opaque JWE that you get by default. But it still doesn’t have any useful information in.
In order to get user details in the access token you have to create a Rule in Auth0. Rules are bits of custom JavaScript that run in Auth0 and modify your tokens before issue.
I would still really like to understand why it’s not OK to use the ID token for authentication in an API.
Awesome @tamlynfm happy to hear everything is functioning as expected, and thanks for following up with the community
I dug into this a bit deeper and technically the use of ID Token may be acceptable if the API actually represents the backend of your app that is not a logically separate service from the frontend. Otherwise, if the API is considered a separate entity from security point of view then an Access Token should be used. Regardless, Auth0 recommends using an Access Token against any sort of API across the board.