Auth0 Home Blog Docs

Why do I need to configure a custom API?

Hi guys,

I got a problem with understanding some basic thing about auth0, probably someone can help me out.

In the tutorial [SPA + API one of the first lines in the TDLR is this:

Both the SPA and the API must be configured in the Auth0 Dashboard

I dont understand why I need to configure the API on Auth0. My code seems to work so can anyone help me understand if I do something wrong or what the advantages are if I actually add my API in my dashboard.

Setup

  • SPA (React)
  • Auth0
  • REST API

What I do

On the Auth0 dashboard I added a SPA application and configured it.

I login on my SPA through Auth0 and get a JWT (google token).

After that I send the JWT as authentication bearer in my calls to the REST API. This works.

On the backend REST API I verify the JWT token with a JWK provider using the Auth0 url mydomain.eu.auth0.com/.well-known/jwks.json. This seems to work too.

In my Auth0 dashboard I never added a custom API and I dont know why this would be important. Can somebody help me understand this?

The token you mention is likely an ID token which is defined in OpenID Connect as a JWT. If you define an API in Auth0 it’s then possible to also obtain access tokens that can be used to call that API. At this time, access tokens issued by Auth0 for API’s you created in the dashboard are also using the JWT format and this is usually where confusion arises.

I think the best way to tackle your question is to ask some follow-up questions, in particular:

  • in your API are you validating the audience of the received JWT token? You should so this moves to the next point.
  • what’s the audience value that you’re expecting in terms of validation?

Thanks for your answer.

Yes it is an ID token. What I do (and probably this isnt right and I didnt understand it correct) at the moment is the following:

this.auth0 = new WebAuth({
    clientID: process.env.REACT_APP_AUTH_CLIENT_ID,
    domain: process.env.REACT_APP_AUTH_DOMAIN_ADDRESS,
    responseType: 'token id_token',
    redirectUri: process.env.REACT_APP_AUTH_REDIRECT_URL,
    scope: 'openid email profile',
});

After logging in I receive an id token in jwt format, right? I use this and send it as authentication bearer to my REST API (Kotlin / ktor).

There I tried to follow the ktor documentation and use an Authentication feature of them which uses a JWK Provider Builder:

val jwkIssuer = "https://mydomain.auth0.com/"
val jwkProvider = JwkProviderBuilder(jwkIssuer)
var audience = "MYCLIENTID"
            .cached(10, 24, TimeUnit.HOURS)
            .rateLimited(10, 1, TimeUnit.MINUTES)
            .build()
install(Authentication) {
    jwt {
        verifier(jwkProvider, jwkIssuer)
        validate { credentials ->
            if (credentials.payload.audience.contains(audience)) JWTPrincipal(credentials.payload) else null
        }
    }
}

So I guess this verifies the domain based on the keyset of the .well-known/jwks.json and I expect the audience to be my client id. Is this right?

Now if I would have a custom API I would create the webauth with an audience which represents my custom API identifier and receive an access token in JWT format. After that I would verify this in my backend and expect the audience to be my custom api identifier?

What you described may not be incorrect per se, but the recommendation would indeed be instead of sending an ID token as a bearer token to send an access token. The main reason being it will boil down almost to the same code, but with less considerations.

For example, moving to the access token approach will, like you said, decouple the API from any data specific to the client application. In particular, the API will now validate a token based on an audience value specific to the API; this means that you may introduce other client applications (with different identifier) to the system and they will behave the same as they will request an access token for the API audience and send that one.

Now, the move to access tokens does not come with consideration of its own, for example, user information will automatically be included in ID tokens depending on OIDC scopes like email or profile, but if you want that same information in access tokens then you’ll need to include it explicitly through custom claims or perform additional calls to the user information endpoint (in cases where the access token also allows it).

Nonetheless, the general recommendation would still indeed be for you to make the updates you mentioned; create a custom API, use the audience in the client application to request an access token and then use that in calls to the API.