What is the right setup for Lock + SPA + Native + Rest API?

You raise some good questions and it seems that you have the right idea for most of them. I’ll answer your questions which will hopefully help clarify some of the confusion.

  1. Do I need to create 2 Clients and 1 API? Or can I use just one Client for everything?

You will need to create 2 clients: 1 for your React SPA and 1 for React Native mobile application. However, you will only need to create a single API.

To give you a better understanding of why you need 2 Clients, I’ll explain how the flow would work at a high level:

Your SPA will likely use the Implicit Grant which is described here to obtain an access token and/or an ID token. (We’ll get to the part of validating the access token further down, so hang in there.)

This access token (which will actually be a JWT given that you pass an audience parameter when calling the /authorize endpoint) will be used to call your API. Once your API receives this access token, it can validate it using the appropriate method.

Have a look at the React Quick Start and it will give you a pretty good walk through for everything from a simple login to calling your API from your React SPA and implementing authorization via scopes: GitHub - auth0-samples/auth0-react-samples: Auth0 Integration Samples for React Applications

Similarly, your React Native application will be represented by it’s own Client and there are 2 sets of Quick starts that can help you get up and running:

Just as you did in the SPA, you will call the API with the access token you received which will be validated by your API and respond accordingly.

  1. The APIs are in BETA. Should I use them?

Absolutely, they’re quite stable at this point and a lot of our users are already using them.

  1. The “access_token” I get from Lock is an opaque token. In order to validate it I need to make an additional HTTP request on the server witch doesn’t seem performant at all. How can I get a JWT instead?

You can request to receive an access token that is a JWT by passing the audience parameter to the authorize call or as a parameter in Lock. (See this code snippet for how it’s done in React with Lock.)

To clarify, the access token should be validated at the API and should be treated as opaque at your Client (your SPA) regardless of whether it’s a JWT or an opaque token.

Now, once the token is received by your API, it can validate it using your API’s signing secret if you created an API with an HS256 signing algorithm or via the JWKs URI: https://{AUTH0_DOMAIN}/.well-known/jwks.json. If you’re not familiar with doing the latter, you can check out this sample here on how to validate a token signed with RS256.

  1. Even though the docs recommend not to use “id_token” to call an API, it would solve my issue. I will not make the additional HTTP request anymore and I will get the user id in the “sub” claim. So, I validate the token and I can id the user.

You can request both an access token and an ID token, however only the ID token should be used at your client and not your access token. The access token should be opaque to your Client and should only be understood by your API (the intended audience).

You can review some additional information about the different types of tokens here: Tokens

  1. Having 2 clients I get different “audience” strings. When I validate the token on the server I can specify only one of them.

Since you have a single API, it’s identifier will be your audience. Therefore you will only have one audience in this case and the clients are simply representing your React SPA and React Native Mobile app specifically (since they require different flows).

  1. If I specify the API’s audience inside Lock’s options (auth → params → audience) the ux flow changes. After I login there is a new step where I need to authorize the API to use my data. How can I skip this step?

This ties into the point I made earlier. By specifying the audience parameter or enabling OIDC-conformance for a Client, it will automatically use the API Auth flows which require that your users authorize the API to access their data.

However, you can skip this consent screen for First Party Clients by toggling the switch under your APIs settings.

I hope I managed to answer some of your questions. I know it could be quite a bit of content to take in initially, but we have a lot of information in our docs, specifically the API Auth ones which pertain to what you’re trying to accomplish.

Cheers,

Fady - DSE