Help understanding Auth0: SPA do you need the custom API?

I’m relatively new to Auth0. I’m building a classical SPA app (Angular) with a server (Node).

Authentication is actually working with Auth0, but I don’t understand the roles of the API’s section of the dashboard. Do we need a custom API (currently we have one)?

My understanding is like this:

  • Connections (sources of users)
  • Applications (we have 2, the server and the SPA)
  • Mangement API (control Auth0 related stuff)
  • Authentication API (login and obtain tokens)

But do we need custom APIs - they are part of many of the tutorials?

I noticed that I can login in the SPA without specifying an “audience”, but if I specify the “audience” (the name of the custom API) I get a different token (the access token is longer)?

Can someone help me understand “audience” and “custom API” in this setup?

Thanks so much :slight_smile:

I agree that the docs could make it a lot more clear of the different roles and when to use them. I think I can clarify one thing though. When you specify the audience you get a JWT instead of the “random string” (an opaque token) as token. If you take this JWT and paste it into jwt.io debugger you can see what’s actually “in” the token. The payload/claims. Your custom API can also verify these claims to determine if the user has access to the resources its requesting, check if the token has expired etc.

If you only have an opaque token it’s not much your custom api can do with it. The token only has any meaning when sending it to auth0’s API’s.

Hi @durre - thanks for your answer.

Ok, but what is the purpose of the custom API then? Is it only a question about where you verify the claims?

And in the classical example where would you recommend the server to verify the claims (custom API or Management API or Auth0 auth API)?

I think it’s best if an auth0 employee answer this, as I’m right in the middle of migrating my own service to auth0 (limited knowledge). But my understanding is this:

  • If the only purpose of your token is to send api calls to auth0 to manage your user, then forget about audience & custom api’s.

  • If you have a backend/API that needs to verify the user, maybe get some basic info like user id for each request, then setup a custom api & set it as audience.

1 Like

@konrad.sopala can you maybe help here with your insights - if you have the time :slight_smile: ? In advance - thanks :slight_smile:

This depends on whether you need to send any authenticated requests to a backend. You said you have a Node server. Do you want to make authenticated requests from your SPA to this server? If you do, the custom API is the Node server.

If all the functionality runs on the browser and no authenticated API calls need to be done, you don’t need a custom API (which means no need to specify an audience).

Does that help?

Hi @thameera. Yes I have a Node server, and Im making authenticated requests from the SPA to this server. But on the server I can verify the access_token from the SPA, by just using “/.well-known/jwks.json” endpoint right?

So in practical terms, where does the custom API play a role here?

‘Custom API’ is just a naming convention. If your server accepts access tokens from the SPA and validates them, it’s what we call a ‘custom API’.

Hope that makes sense, but let me know if you’d like further clarifications.

Thanks for taking your time. Ok so in my setup where would I “point” to the custom API - is it only in the SPA, where the Auth0-js SDK is initialized with the audience parameter pointing to the custom API?

If that is the case you could say that a custom API is a way of defining token expiration, “skipping user consent”, signing algorithm etc?

On the server running Node, I don’t “point” to the custom API to validate the tokens. Is that correct understood?

I think there’s still a confusion over the terms, so let me try again.

Custom API == Node server
You set up an ‘API’ in Auth0 dashboard, with an identifier https://example.com. This represents the Node server.

In the SPA, you request tokens from Auth0. You want these tokens to be sent to the Node server, so you request the audience to be https://example.com.

The SPA sends the received access token to the Node server. The server checks the audience of the token, and sees it’s https://example.com, which is what it wants. It also checks other fields like expiry and validates the token.

If the story so far is clear, you’re good.

So to answer your initial question (where would I “point” to the custom API), you do that in the frontend when specifying the audience. The Node server is the custom API. And the API you create in the Auth0 dashboard is a representation of it.

The flow is also described in the diagram here: Solution Overview (SPAs + API)

Thank you so much @thameera for taking your time to write this explanation. Now it makes sense!

Many of the Auth0 articles/documentation is actually really concise and sometimes leaving out interesting information :slight_smile:

So one last statement to verify that I understand the architecture. Would you say the following is correct: “The audience you specify in the client SDK influences the tokens issued, for example influencing expiration_time.”

Thanks for taking your time again :slight_smile:

That’s correct, the audience determines to whom the token is intended (aud claim), expiration time, etc. Audience points to an API you have configured in Auth0 - and each API can have different settings for the tokens.

1 Like

Hey @alexab wanted to touch the general feedback you provided. Would you like to share it in a more detailed and descriptive way so I can effectively pass it to our product team? Feel free to do it here or send it to me over DM.

Whatever you feel works for you! Thanks a lot for the effort!

Hi @konrad.sopala → yes I would love to do that.

So currently there exists an article called SPA + API. This is a good article, but besides SPA/API it also covers Scopes in detail making the article a bit cluttered. So here are my suggestions for this article:

  1. Maybe create 2 different articles on SPA+API, with and without scopes.
  2. Add a link about how to implement dev/stage/prod envs. I know Auth0 has an article about this, but it would be very nice to explicitly mention it here. Otherwise you might start to make dev/stage/prod versions of api/coonection/application, and that really clutters the experience.
  3. Add more descriptions to the configuration chapter. This is really where it would be nice with a better description why we need to create the custom API. If you come from a firebase auth world, this step just seems a bit weird. So maybe discuss what the custom API, the benefits it gives etc.
  4. In the implementation section, add more detailed information about the step “Secure the Endpoints”. I really need the guide to explain me if the token is verified using by going to the Auth0 server or it’s a “ready-to-verify” jwt token that any library can help decode. (I know this is explained in the linked article - I just think it could be written there).
  5. In the client documentation, maybe write something about storing tokens in local storage (since the access_token should not be stored in local storage in a production app, like auth0 mention here). In my opinion it’s important to explain how to configure the service to be production ready, because when you are researching Auth0 API/SPA setup, this is what you are after.
  6. The conclusion is probably where the most improvements could made. Here I think there should be a digram showing where the different Auth0 concepts are in play. I.e. the auth0-js SDK used on the client (configured to use the correct application), issuing a token for the custom API. And then there should be a list of what’s next guides (for a production app):
  • How to setup dev/stage/prod envs
  • Benefits/downsides to setup scopes
  • Where to safely store the access_token
  • How to handle the different error codes
  • What to think about in terms of CI/CD (callback urls etc)

I hope this is what you are looking for :wink:

1 Like

Perfect beautifully thanks for that! :fist_right:t3::fist_left:t2: