I am currently building an application that uses the Spotify API to work with a user's playlists. My frontend is a Flutter app, which is connected to the backend, that is built with Node.js. Currently my backend handles the logic of implementing the [Authorization Code flow1 by using the spotify-web-api-node package. I implemented the auth flow in my app as follows:

After setting up the SpotifyWebApi object (provided by the package) on the backend, my frontend makes a request to retrieve an authorization URL which is used to allow the user to login through Spotify in a WebView. After granting the app permission to access the user's data, Spotify redirects the WebView to a callback on the backend, which generates the access token and finally redirects the frontend to an URL with the token embedded as an query parameter (e.g.: res.redirect('../auth/callback?token=${token}')). Once the WebView in the frontend reaches the URL with the token, it is stored on the frontend for future requests and the WebView is closed. Thus the user has logged in successfully and the frontend can now make requests to the backend to access the playlist data, by adding the stored token in an authorization header.

Now I have a few questions regarding my implementation:

  1. Is it safe / a good practice to pass the access token to the frontend through a query parameter during a redirect after authorizing / logging in?
  2. Does it make sense to handle all auth logic on the backend or should some of it be handled by the frontend? I am asking this since i have seen a few examples provided by Flutter auth packages (e.g. flutter_appauth), which seem to indicate that the authorization process could also be handled in the frontend. However I would then need to store some of the secrets from the backend (like client_id and client_secret to authenticate the application with Spotify) in the frontend, which seems odd to me.
  3. Is there maybe another way to structure this auth flow in a secure way, which is different from the way I currently implemented it or from the way I mention in the second question?
  • It is the responsibility of an Auth provider to generate the access_token - is there any reason to generate a second token in your backend? If you want to handle Auth Code flow from a browser-based UI app then consider using PKCE to avoid the need for a client_secret. (and indeed avoid any involvement in your backend anywhere in the process aside from calls into the provider's own API, since I assume the purpose of the token is to get the client's authorisation). Feb 20, 2022 at 12:00
  • @BenCottrell Regarding your first question: I may have worded it badly, but I meant to say that the access_token is generated through use of the SpotifyWebApi object which happens in the backend. I just call the objects method which returns the access_token. I place the token in a JSON Web Token which is then embedded in the query parameter of the redirect as mentioned above. Would you say it is a good idea / best practice to avoid any involvement of the backend in the auth process and instead just let it handle the requests to the Spotify API?
    – mic-ray
    Feb 20, 2022 at 14:13
  • I'm afraid I don't really understand why that object is generating the token or why you have to create a JWT yourself -- the provider should be doing all of that, so the access_token (a JWT) should simply be returned in exchange for the Auth code. I'd recommend going back to the provider's documentation and looking into other OAuth2 docs. Feb 20, 2022 at 20:29
  • No there is nothing wrong with using the backend. Both of the Auth Code flows are good, but they exist for different scenarios - The Auth Code flow with PKCE is intended for use within a client UI app (i.e. a situation where you wouldn't want to use a client_secret) which as far as I can tell is the scenario you're really trying to work with and it seems like the backend is adding some extra complexity or confusion; however if you use the PKCE flow then there simply wouldn't be any need to involve the backend Feb 20, 2022 at 20:38
  • Thanks a lot for your feedback @BenCottrell! I will take a look at the documentation of the provider again and try to find out whether I need the additional JWT wrapper. Currently I am not using the PKCE flow, however my UI app doesn't use the client_secret anyways. Thus I think I'll stick to the backend flow for now.
    – mic-ray
    Feb 24, 2022 at 22:29


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.