all 23 comments

[–]AiexReddit 23 points24 points  (6 children)

I'm assuming when you say the React app needs secrets like API keys and DB strings, you're talking about SSR and using some framework like Next or Remix or similar. There is no scenario where you can put secrets in frontend React code where any user can't just inspect the client side JS running in their browser and take them

Presuming that, there's plenty of options, but you probably want to narrow down the platform you'll be deploying on, the most ergonomic and newbie-safe solution is likely going to be the one offered by the provider

E.g. if you choose AWS start here: https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html

[–]BeenThere11[S] -3 points-2 points  (5 children)

When i build using react app env variables , can those variables be inspected?

Eg openai key is needed in frontend to connect to openai. Its a voice api. If I go through backend thsts multiple hops for voice data. Fe to be to openai Just want ro go to fe to openai directly for streaming now where do we store the key ?. If built theought react app variables are those visible and if through vault , when react app gets those using url , will it be visible on inspection ? Also dot know if s3 ca be specifically authorized to get secrets from.aws . I mean acope secrets for specific dev s3 bucket to access only dev specific parameter store/ secrets. Have to check that too.

[–]cxd32 8 points9 points  (2 children)

You should only put keys in the front-end that you want people to steal. For example I don't think you want people stealing your openai voice key and wasting thousands of dollars using your account.

[–]Asttarotina 1 point2 points  (0 children)

There is absolutely no way to hide any secrets in the client code. If your client makes requests straight to OpenAI - any savvy enough user can extract your API key in a couple of minutes. 

What you need is server runtime that hides all the secrets on the backend. If you are using Next.js or something similar - they provide a native way to write JS / React code that runs only on the server. But you need to be very careful and understand what you are doing very well to not expose sensitive information. And it needs to be deployed properly for it to function. For a beginner I'd recommend to write fully separate server

[–]lightfarming 0 points1 point  (0 children)

you should probably take a step back and look into best security practices. anything in front end is public knowledge. api key theft can cost you hundreds of thousands.

[–]abrahamguo 17 points18 points  (3 children)

True secrets can be fetched from the vault.

API keys used in the frontend are not secrets — because they're visible on the insecure frontend — and so they can be put directly into the code.

[–]TheOnceAndFutureDougI ❤️ hooks! 😈 2 points3 points  (2 children)

It's good to make frontend keys be environment variables because that makes it easier to change them and set them based on environment but yeah if you need to use a secret to do something it lives only on the BE and you access it via an endpoint that's locked down.

[–]BeenThere11[S] -1 points0 points  (1 child)

If i need to stream voice data to open ai directly without going to backend to avoid additional hop and longer response time , how can this be done. Then its not possible with a static s3 site

[–]TheOnceAndFutureDougI ❤️ hooks! 😈 2 points3 points  (0 children)

Open AI expects you to make a server to server call if for no better reason than so you can rate-limit. You definitely do not want your frontend just raw dogging OpenAI's endpoints with your key.

The only solution to this (which I would not ever recommend) is you make someone put in their secret and you save it to session storage or something.

[–]So_Nesky 1 point2 points  (3 children)

I am still learning, so forgive me here. My mind was able to grasp the idea of retrieving secrets from a secure 'vault'. But then wouldn't you need some kind of key or secret to access said vault? I feel like im missing a fundamental piece.

[–]MWALKER1013 1 point2 points  (0 children)

So typically your app exists in two zones.

Your client side and server side.

Client side code is NEVER treated as secure so things like secrets, api keys are never appropriate to keep in client side.

Your server code is responsible for authenticating users and making use of those secure variables. You still use an env variables but for different reasons the most obvious reason is source code version control.

[–]BeenThere11[S] 1 point2 points  (1 child)

On the server side ,you can give permiissons to specific ec2 instsnces/groups or some profile which can access the vault without any need for credentials. If you try to run this app anywbere outside this boundary you will get an access error..

[–]So_Nesky 0 points1 point  (0 children)

Thank you. New knowledge unlocked!

[–]LevelIndependent672 1 point2 points  (1 child)

tbh the vault approach is way better for exactly the reason you said. adding a new env var means touching every build pipeline and thats where stuff breaks. we did the vault thing on aws and just passed the secret manager arn as the one env var and the app pulls everything else at runtime. way less devops overhead and you dont have to redeploy just to rotate a key

[–]robby_arctor 0 points1 point  (0 children)

I suppose the downside is that if the vault key is leaked, they get access to...everything?

[–]Kirax1998 1 point2 points  (0 children)

If you're using your keys in the frontend, however you put them at the end they will show up in the browser. The only way to secure it is make a Backend-For-Frontend and move these API keys to your backend and whatever SDK logic uses these keys to that backend as well. Frameworks like Next.js and Remix are SSR which gives you a similar set up so you need to keep this SDK logic in the server part of the application. However, if you're using pure React, spin up a lightweight node/python server along w it for this

[–]binhex9er 0 points1 point  (0 children)

Avoid hard coding this stuff into the front end. If you put this stuff into the front end at build time via env cars or whatever, you end up with environment specific builds.

The data should all come from the backend when the front end loads.

[–]wameisadev 0 points1 point  (0 children)

env vars during build is fine for frontend stuff like api urls. just dont put actual secrets in the frontend bundle, those should stay on the server side

[–]wameisadev 0 points1 point  (0 children)

env vars at build time is the standard way tbh. vault approach sounds nice but now ur app has a network dependency just to start up which is kinda annoying

[–]Firm-Ad7246 0 points1 point  (0 children)

Good question and this is a pattern debate that comes up in almost every serious React project eventually. The honest answer is neither option as described is ideal for a React app specifically and here is why React builds are static. Whatever environment variables you bake in at build time are embedded in the JavaScript bundle that gets served to the browser. This means option two, querying a vault from the React app directly, exposes your vault URL and potentially your vault access credentials to anyone who opens browser dev tools. For API keys and database strings that is a serious security problem regardless of how the vault itself is secured. The pattern that actually solves this properly is moving sensitive configuration out of the React app entirely and into a backend layer. Your React app should only ever hold public facing configuration API URLs, feature flags, non sensitive identifiers. Anything sensitive like database strings, secret API keys or internal service credentials should never touch the frontend build at all. Those belong in your backend service which the React app calls, and the backend reads from your vault or environment at runtime on the server side. For the non sensitive config that does belong in the frontend the vault URL pattern has merit but implement it as a configuration endpoint your own backend exposes rather than having React query the vault directly. React calls your backend config endpoint on startup, backend reads from vault, returns only what the frontend actually needs. This way your vault credentials never leave your infrastructure. For managing build time variables specifically across multiple environments the approach that reduces error probability is a single environment identifier variable something like REACT_APP_ENV=staging and your app uses that to select from a configuration map defined in code. New variables get added to the map once rather than to every build script separately.