Strideface / spotify-quiz-app

A web app built with React that offers a quiz based on Spotify tracks and artists.
0 stars 0 forks source link

Where to put client_id? #6

Closed Strideface closed 2 months ago

Strideface commented 2 months ago

@istride Where should I keep my client_id?

It's currently exposed in my code. Where would be the best place to store it or do I need to hide it/encrypt it some how before deploying my app?

https://github.com/Strideface/spotify-quiz-app/blob/adae3ef73df62c26dc05194a15cc9aa3c72b84d9/src/util/spotify-api.js#L20

https://developer.spotify.com/documentation/web-api/tutorials/code-pkce-flow

istride commented 2 months ago

The client id is not a sensitive piece of information because you have to make a GET request with the client id as a query string parameter, which exposes the client id anyway i.e. https://accounts.spotify.com/authorize?client_id=${clientId}....

You may want to consider not hardcoding the client id, that is, being able to change the client id without having to change the app code. That means that the client id would have to be a piece of information that you supply to your app when it starts. How you pass that information in depends on how you deploy your app - which HTTP server (Express, etc...) you use. I'm not very familiar with how this is done in React, so I can't give more concrete advice than this, but I'd be happy to help out, if you can work out the details. In any case, you don't have to do this now, it's just a useful technique that you'll probably have to use at some point anyway.

Strideface commented 2 months ago

Alright, noted. Will ask for help If I get stuck. Thanks

Strideface commented 2 months ago

@istride running into one main problem when trying to use an environment variables library.

*Can't reference the code because I have not committed it

I have tried using:

When using dotenv, I created a config file that react should detect automatically because it is a .env file. It contains:

REACT_APP_SPOTIFY_CLIENT_ID="00e6229ed59a4bd8a0e3e91a99deb1f7" REACT_APP_SPOTIFY_REDIRECT_URI="http://localhost:3000/"

"React enforces EVs to be prefixed with the word REACTAPP to enable the React engine to identify them as custom EVs. Any variable without the prefix is ignored during bundling to prevent you from accidentally exposing a private key on a machine that could have the same name.

React then loads the variables into process.env — a global object injected by Node.js at runtime that represents the state of the environment in which your app is running. Since environment variables have global scope in this environment, you can access them through it." - https://www.architect.io/blog/2022-08-16/react-environment-variables-developers-guide/

I get this error when starting the app (npm start):

`Compiled with problems: × ERROR in ./node_modules/dotenv/lib/main.js 2:13-28 Module not found: Error: Can't resolve 'path' in 'C:\Users\alan\Desktop\Coding\React Projects\Spotify Quiz App\spotify\node_modules\dotenv\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:

I have learnt that it's asking me for 'polyfills' because these are 'native' npm installs that don't work on a browser where my app is running. Explanation here: https://github.com/facebook/create-react-app/issues/12865#issuecomment-1335466680

The workaround seems to be to change the webpack config file so that I can import these 'fallbacks' so it can run on the browser. Problem is, in a create-react-app project, it doesn't allow you to change the webpack config so I'd need to import a libary that allows me to do that. Suggestions are:

it makes me nervous that both these state, "By doing this you're breaking the https://github.com/facebookincubator/create-react-app/issues/99#issuecomment-234657710 that CRA provides. That is to say you now "own" the configs. No support will be provided. Proceed with caution."

The alternatives are to not provide a pollyfill, which seems to me like I'd still need to overwrite the webpack config.

What do you think I should do? I didn't think it would be this convoluted! I'm just concerned that the more I import, the less likely I am to fix something if it goes wrong in future because there will be so many dependencies.

This by the way is only an environment variable solution during development. Haven't looked at what i need to do when hosting on Firebase.

Finally, unrelated to this specific issue but worth mentioning. I will never be able to publish this app and it will have to remain in development mode because Spotify don't allow apps made for quizzes or trivia games :-( I should have checked the terms but that's the reality now. They wouldn't ever extend my quota limit so I'll just have to add any friends I want to use it to the 'allow list' so they access it in development mode. I can still host it on Firebase though and that's something else to learn.

istride commented 2 months ago

I was thinking more along lines of passing props to a component. The client id would be passed into the App component - probably in index.js.

<App spotifyClientId="abc123" />

However, moving the client id to this location is hardly any different from keeping it where it is right now. It's still hardcoded in your app. You need to move it a level up from index.js, which is the public/index.html file. I'm not sure if there is an official, or correct way of doing this, but you could try using global variables. Add the client id to index.html in a script tag, inside the 'head' tag.

<script>
  const spotifyClientId = "abc123"
</script>

Then index.js can become:

<App spotifyClientId=window.spotifyClientId />

Or something like that, I don't know the exact details of the syntax. Anyway, this would take the client id out of your app and into the HTML page where your app is running. At this stage you might be able to use a client id for development and another for, say, Firebase, or wherever you deploy this.

Going further than this, in public/index.html, I can see what look like placeholders for dynamic data e.g. %PUBLIC_URL%. I'm not sure what's going on here, but potentially you can define a new placeholder for your client id. Maybe these placeholders are replaced by values in environment variables when you build your app. You can probably use what you have done already with environment variables.

Worryingly, I can't find very much information about how to do any of this, so I could be barking up the wrong tree with the method above, or perhaps this is just not a very popular thing to do. Hope that helps.

Strideface commented 2 months ago

I went for the workaround and installed all those extra dependencies. Firebase seems to automatically work with the Node.js Process module where you can set environment variables: https://nodejs.org/en/learn/command-line/how-to-read-environment-variables-from-nodejs.

I think I'm almost done. It's hosted on Firebase but I just need to figure out how to get the EV's through Firebase cloud functions.

Will let you know if I get stuck. Thanks.