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

Hello there,

I’m trying to use Auth0 for an app I’m building which consists of the following components

  1. Central Rest API. Users will call the API to make CRUD operations on different resources.
  2. React SPA. Users will login using Lock and call the Rest API (1)
  3. React Native App. Users will login using Lock and call the Rest API (1)

This seemed like a really common scenario and I expected that this integration will take ~30 minutes but for the past 2 days I’ve been testing and reading the docs without much success.

Here are my confusions/questions

  1. Do I need to create 2 Clients and 1 API? Or can I use just one Client for everything?
  2. The APIs are in BETA. Should I use them?
  3. 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?
  4. 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.
  5. Having 2 clients I get different “audience” strings. When I validate the token on the server I can specify only one of them.
  6. 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?

Am I missing something really obvious? How should I go about this integration?

Thanks

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

@fady thanks for your answer!

The only part I was missing in my previous trials was that First Party Clients can skip the consent screen only when they don’t run on localhost.

A couple more questions:

  1. Is OIDC-conformance here to stay or just an experiment?
  2. How can I get user’s profile on the API server? Decoding the access_token doesn’t give much info. How can I embed more claims into it? (eg. email, name)

Is OIDC-conformance here to stay or just an experiment?

Yes, it’s here to stay and offers a more spec-compliant implementation and added security benefits. I suggest you read over this document: Applications in Auth0

How can I get user’s profile on the API server? Decoding the access_token doesn’t give much info. How can I embed more claims into it? (eg. email, name)

You can use rules to add custom claims to your access tokens and ID tokens:

context.accessToken'https://acme/claim-name'] = 'claim-value'

@fady

Enabling OIDC-conformance disables rememberLastLogin. Is this temporary or it is against the OICD specs?

@fady I am facing a similar problem, using a react-native App.

Using react-native-lock, and could signup and login successfully, In return Auth0 is sending idToken (in JWT form) & accessToken ( not in JWT form, some string like “f-OYa4fQX-Hp-1V9”)). Don’t know how to verify this accessToken at API side. also react-native-lock doesn’t support creating lock using ‘audience’ parameter. (in order to get accessToken in JWT format )

Will appreciate your help. Thanks.

@andrei , Did you resolve it ?

I am facing a similar problem, using a react-native App.

Using react-native-lock, and could signup and login successfully, In return Auth0 is sending idToken (in JWT form) & accessToken ( not in JWT form, some string like “f-OYa4fQX-Hp-1V9”)). Don’t know how to verify this accessToken at API side. also react-native-lock doesn’t support creating lock using ‘audience’ parameter. (in order to get accessToken in JWT format )

Will appreciate your help. Thanks.

@victor1 “also react-native-lock doesn’t support creating lock using ‘audience’ parameter”

The audience param is the key factor if you want a JWT accessToken. Are you sure you have a similar setup with this? https://github.com/auth0-samples/auth0-react-samples/blob/master/04-Calling-API/src/Auth/Auth.js#L7-L18

Thanks @fady I am trying to use Lock to do user sign-in in my React SPA, same as @andrei. Your comment “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.” sounds great, but the code snippet you reference is a broken link. Please comment the correct link.

I am passing my API audience and responseType: ‘id_token token’ to Lock, and I’m getting both an accessToken and an idToken back. But when I call lock.getUserInfo with the idToken I get a 401 Unauthorized from auth0. How should I fix that?