I’m trying to make up my mind for the following scenario: I have a SPA and a backend API that serves it. SPA authenticates on by backend with implicit flow. Now, I’d like to integrate with 3rd party API, allowing my backend (or the SPA eventually) to interact with the external API. Notice I don’t want to use 3rd party for login.
How should the Authorization Code flow work in this case?
I’m expecting my users to log in to my app using implicit flow from the SPA to my API (i.e. get an access token with my API as audience via auth0). Then, they should probably move to a specific section of my SPA for adding integration to 3rd party API. The goal is to have a refresh token securely stored in my backend so it can get access tokens for the 3rd party api without having the user to login again on it.
I’m not sure how this part should work. auth0 is probably not directly involved, since I don’t need to login on my API with 3rd party credentials. I’m expecting the user agent to be redirected to 3rd party’s authorize endpoint with the required scopes, but what about the following redirect? Should I redirect to my SPA and have it send the authorization code to my backend (seems a no no to me) or should 3rd party redirect directly to my backend, have it check the authorization code by getting a refresh token, store it and redirect my SPA to the results?
Is there any documentation you suggest me to read covering this (common I think) scenario?
For a regular authorization code grant the assumption is that you have some type of server-side web application that can maintain secrets and as such act as a confidential client. Native applications can do a modified version of it using PKCE, but that does not seem relevant to the discussion at hand.
You have a SPA and a back-end service API; from these two, the SPA gets automatically ruled out for the possibility to handle an authorization code grant. In addition, the approach of having the SPA handle the first part of the grant (receive the code) and then pass it to the back-end service API seems brittle because in practice you have an OAuth2 flow being handled by what should be two independent components.
I would consider exposing two endpoints in the back-end API; these endpoints instead of responding with data always respond with HTTP redirects:
- the first endpoint allows an authenticated actor to trigger the initiation of the authorization code grant for the third-party API in question.
- a request to this endpoint must include a parameter that represents the URL that the user will ultimately be redirected after the whole process completes (in your case this would be an URL handled by the SPA).
- a response from this endpoint is an HTTP redirect to the third-party API OAuth2 authorization endpoint.
- the second endpoint handles the third-party API redirect response containing the authorization code.
- request to this endpoint are only made from the third-party API as part of the initiated authorization grant.
- a response from this endpoint is an HTTP redirect to the originally provided URL.
The way the second endpoint knows the correct URL to respond with is by maintaining some notion of state which could be tied together using the OAuth2 state parameter that the third-party API as an OAuth2 provider must support.
This almost allows a complete decouple of the SPA and the back-end API in terms that this could work if you had multiple SPA’s; they would just provide a different URL when starting the process. I say almost, because even though the initial endpoint requires authentication you could also consider worthwhile to implement a white-list of URL’s that can be provided which means that your back-end API would have to have some sort of knowledge of all the SPA’s that exist.
If this seems complicated is because it really is and I don’t think there’s much to do about it. In relation to existing documentation, it’s only available for certain third-party API’s that have built-in support within Auth0. These are referred as client addons and for the available ones the complexity to obtain a token valid for that API would significantly decrease when compared to a process based on what was described above.
Thanks for the detailed answer. While it is not strictly related to auth0, I didn’t find any proper discussion board on the net or examples covering this scenario. But I think it is very common: SPA + backend for sure is, and most of the time you also want to integrate with facebook or spotify etc. Probably it is worth an article on Auth0’s blog or documentation.
Another question: is auth0 (as a service - aside from client addons) involved in any way / can be leveraged in any way? It seems to me the answer is NO, unless the 3rd party service is used for linked/social login too, right?
You may not find much online as in general the SPA’s (even when there’s a back-end in the equation) may choose to go with the implicit flow in order to get access to the third-party API because the need for access is associated with user actions.
Only when you need offline access, for example. to perform updates not directly triggered by user actions does this more complex flow where the SPA associated “back-end” needs to have refresh tokens while still having to deal with HTTP redirects is required. In relation to your question I would say it’s restricted to client addons or social logins.