How to correctly store secret keys on React App? - reactjs

I was happy lasts days using **.env **file with the npm dotenv package and saving there some secret keys i use on my React App...
On my first test opload I noticed that my webbApp runs ok EVEN without specifying the .env secret keys on the sever...
So then, was obious to feels like the secret keys are anywhere on the public files (and yes)
I was looking what im doing wrong, and found many documentation (official) that says literally:
WARNING: Do not store any secrets (such as private API keys) in your React app!
Environment variables are embedded into the build, anyone can view them by inspecting your app's files.
official doc here if anyone is looking for more info
After 3 or 4 heartAttacks I write this to ask for help on this concept problem.
Anyone knows some documentation where i can read and understant HOW to correctly save sercret keys on this kind of apps (react apps) ?
why the hell is not like all time backend .env files ?
Some info I found, says something about to serve the secret key ontime from another server.
And... sounds stupid for me, i mean: Ok, i can do that but.. its just stupid cause then:
or server will serve the sercret keys "free" vía GET or something like this without no-login-needed.
or webbApp would need a secret_login_key to login and get the secret key <- in this case, where to store that secret_login_key ? its a infinite bucle ? XD
So:
it is posible.. (of course it is) so TRULY store secret keys on React App ? but where and how ?xD
what's the way you store the secret keys on ur react App and u are proud of it?
of course the login typing from keyboard user/pass its the "easyway" to have or not have access tho private information but.. what if i need this to be automatic from my webApp ?
Thanks.

For automatic access to your webapp from the frontend (React), you need a bearer token that is stored in localstorage (bad idea) or as a cookie of the user's browser. Popular example of bearer token is JWT token.
This is how you generate a bearer token on the user's browser: by using Universal Login (login with Google/Fb/Github/Twitter etc) to a provider like Auth0.
React has to communicate with Auth0, Auth0 will authorise the user and return a bearer token that is stored in localstorage (bad idea)/cookie of the browser.
This is what you are trying to do:Call a protected API from React
This is the walk through example of how to do it: Basic Authentication Quick React Setup
Here are some example use cases with different application architecture scenarios:Application Architecture Scenarios
React's documentation is correct, secrets should not be used directly in the React project. But the problem is how to ensure only authorised users get access to protected paths. One way is to use username and password login but you said its the "easyway" and you need it to be automatic. So another way is to ensure authorisation by bearer token stored in localstorage(bad idea)/cookie of the user's browser - this creates a new problem: how to generate a bearer token to allow access. The solution is to use universal login by Auth0 (or Oauth, or OpenID, or Google Authenticator, or some other token generator that the user can possess (like a mobile app (Google Authenticator) or a hardware token)).

Sensitive data should not be on the frontend, you can use env for information like API_URL but not for tokens and passwords
Here is the possible ways to get sensitive data in the frontend
Http call to the backend where secrets are hashed
Http call to an external secret management tool like HashiCorp Vault
Use of httpOnly cookie that they couldn't be read from the frontend
If you are scripting user and password, you should try a tool like jscrambler to secure your build js files

When API calls are made from the frontend (i.e. your react app) anyone using your app can see the request that was made (with tokens, keys, etc.). You should always secret vars to an .env file and keep this file only on your local machine.The best way to handle this, in my opinion, is to use a framework like next or remix that allow you to create functions/api routes that run on the server. This way your frontend makes a request (no sensitive info there) to your server that has access to your keys/tokens. The real call to an external API will be made from the server (so users won't have access to any sensitive data). Not sure if this is something you're interested in but I feel like it's the best way to deal with API calls.

I suggest creating a ".env" to store all your secret keys.
In your ".env" file you can make this one
Eg:
REACT_APP_API_KEY=5155645fdsffsdfs
And in your component, you'll call it
Eg :
const apiKey = process.env.REACT_APP_API_KEY

Related

Authorization and authentication in web application with ASP.NET Core backend and React frontend?

I have a web application, where the frontend is built with react.js and typescript and the backend is build with ASP.NET Core 3.1 and connected to a SQL Server. The SQL Server is used for saving data, which I can enter in the frontend.
Now I want to implement a custom authentication system, where I can protect different endpoints with an authorization. I know there are several ways to go for, but I don't want to use a service / library, where a user could login with his google account for example.
Jwt seems in my Opinion a good way to go here, but I really don't understand the whole system.
This article helped me already a lot: Implementing authentication and authorization with React hooks, .NET Core Web API, and SQL Server .After reading this, I don't understand the relationship between logging in and how my backend knows, that a user is logged in (for protecting my endpoints).
Of course I already read many articles about authentication and authorization for ASP.NET Core. I've read about different services like:
Auth0 (seems not a good idea, because you can login with google etc.)
IdentityUI (seems good, I've seen a few youtube tutorials but they are all using another project structure, where the frontend and backend isn't separated. So they are using the razor pages like Login.cshtml, but I don't want to render any pages in the backend, only in the frontend)
For authorization for my controller in the backend, I planned to use the following:
[Authorize] // to protect endpoint
[HttpGet]
public async Task<IEnumerable<>> GetData()
{
// some code
}
But as I already said: I don't know / understand how my backend knows if a user is logged in (and how to check it).
Could somebody provide me an appropriate tutorial or an article, where is explained, how to manage authorization and authentication for frontend and backend? Or maybe somebody knows, how to use the IdentityUI with a frontend build with react + typescript and a backend, which shouldn't render any pages.
Thanks for your attention :)
Well... for detailed flow how they work, here is RFC 6749, this is a pretty comprehensive collection of knowledge related to the topic and the easiest approach would be wiki page in general.
But to simplify the process, just get to know these things:
What is JWT
Jwt just a string that was generated by some algorithm from a public/private key pair(don't even care how it works, just give it a key pair, some lib on every language would do the rest). This JWT often contain all the information that needed to specify who the user is(big word right ? but actually, userId is enough for simple case).
It contain 3 different parts Header, Payload and Signature, and the string assured it cannot be interrupted(or just modify it as we wish, and the validation process would failed).
Further detail here.
What happen on server side?
The most basically flow was send user, password to server for validate who we are and our account exists. Then, server side would take some necessary info out of it to generate the JWT token. The server which generate JWT token was normally refer to Identity Provider.
Then that token was send back to client, and client save it somewhere for later use.
Client side use token to request other resource
Normally, Identity Provider would provide a .wellknow endpoint that contain all necessary info for other resources to gather for validation process.
Now, client side send a http request to these resources with the JWT token. They use info gathered from .wellknow endpoint to validate was the JWT valid. If it is, we are who we claim we are, authentication process success.
The end.
Over-simplyfied flow imagination in your specific case
React Client => Request login => Identity Provider => Jwt Token send back => React client save it somewhere.
React Client => Request some resource over http with the JWT token => Resource server validate it (through info from .wellknow endpoint) => Authentication success or fail => normal process => send response back to client.

What is the best way to store an admin API token in Next.js ? Feel like storing it client side as http only cookie is risky

I'm working on a e-commerce using next.js and sylius API and the API admin routes are secured using JWT. So in order to fetch products (for example), i need to login to the API, get the token and then fetch the products using the token. The most common method to be able to send the token on every new requests to the API is to store it in a HTTP-only cookie.
As the pages are generated statically, i feel i don't need (and want) to expose the API token to the client. So i'm wondering the best way to store the token ?
Here the different options i have in mind right now:
store the token as a http only cookie and use it server side (with a proxy using next js API pages) in order to call the sylius API. Like i said, i'm not confortable to store the API token into the client, it seems risky to me, as it will be exposed to everyone, and with that token you can access the admin API.
configure the API in order to prevent the token from expiring, and store it in the next js app as an environnement variable (.env.local), so that it's not exposed to the client and can be used for fetching the api when generating static pages. The official ecommerce theme of Next.Js seems to use that method (https://github.com/vercel/commerce/blob/f770ad7a91059a2ecfbb9de1bac111dfe7016124/framework/bigcommerce/api/index.ts#L82)
store the token somewhere in the next js structure but not as an environnement variable (maybe a config file?), so that it can be replaced if necessary (if the token expires etc).
get the token and store it in the react state as is it will be used once only for generating all static pages. On each build the token will be asked again by the API and then used for fetching the API for exporting the static pages with the content. It don't need to be saved more time than the building step.
For me the last option seems better but i feel i'm missing something there, i'm kinda new to next, so i'm not sure exactly if its a good solution.
Thanks :)
I get a great answer from a reddit user ("supermaguireray"), so i post it as an answer here:
"First of all, in any session management mechanism the correct information needs to live on the correct domains, what I mean is that your client can only have access to a identification information, but never to data used in the server, these can be applied to a server-side session, when a ID for the user data stored on the server is sent to the client (preferably encrypted), or in a JWT where a encrypted string is sent to the client (identification), and decrypted on the server (Data).
With that said, the only reason you should send the API token to the client is if you need to fetch data directly from a browser. Storing as a httpOnly cookie is the most secure way.
In case you only need the cookie fetch data to the next backend, to render your SSG or ISR pages, there is no need to send a cookie to the client. Just store the token in your server. I would store it as env variable. Use next.config.js->runtime-configuration.
Or, you can keep a expiration date for the token, and store the credentials, maybe even in a DynamoDB or FaunaDB app."

Securely storing auth token in React Frontend

I am currently working on a single page react app. This app will not require any login and it will be publicly available.
I am making a POST request to a webhook of another API that I do not have access to and that I do not maintain. This API required me to send an authentication token via the POST. I wonder how I can securely store this token so that it does not get out in the world. I need to send it as is so storing it in a cookie that a backend provides is not an option. Storing in in JWT will not work as I can decode that without the secret.
Is there even a way to store the token without exposing it to the world?
I hope the issue is clear, if not let me know and I'll explain better.
Thank you all for your time!
I would usually have a local Express server running and proxy the request through that.
You would set up a route in your Express app that you would POST to from your React front-end, this Express route handler then makes the call to the external API from the server side which has the token to put in the header. Then the response is returned to your React front-end without it knowing anything about the external API or tokens.
You can't store the token in front-end. either you need to use
cookies/session to store the token. If you want to store the token you
need to encrypt it and store it will be the better option.
Please check here to understand the JWT token mechanism
if the web app doesn't have a login. you can't generate token without user details.
The token should be passed in the header of the request for best practices.
If you're using create-react-app to instantiate your React project, have you looked into using an environment variable to store the token? It's not 100% safe and secure, check here for the cons, but can be a quick fix without a separate proxy request. You can make an .env file (make sure to add it to your .gitignore if using git) in the root of your directory and define variables there. They need to start with REACT_APP, like REACT_APP_SECRET=1234 and can then be referenced where you need them in your app with process.env.REACT_APP_SECRET.
Read more about environments in React here.

Using Multiple Angular App and Session Management

I have 4 angular applications one is a landing app which asks user to login and has to redirect the user according to its type
to one of the other 3 applications. I am unable to figure how to should i achieve that.
Have the three apps running on different subdomains. Upon login backend send a redirect response, figuring out what type of user it is?
But this leads to cors Error. Also i am not sure whether the cookie which i am setting will be accessible in all the subdomains or not.
Is there a way out?
You can do a redirect, but it seems like an unnecessary step (and kind of convoluted for this type of application).
Instead of returning a redirect based on login, it seems more straightforward to just return the address you want to redirect to in the response. Trigger a lookup to determine which app you should be directing to (however you're doing that) and then return the address of the app in the response data. From within Angular, you can extract the address from within response.data in $http. (see angular docs). The nice thing here is you also keep routing control and knowledge of state within Angular itself.
As for the apps themselves--instead of a subdomain, you can simply put the apps into different folders on your domain. This deals with CORS and the cookie issue.
Otherwise, you'd need to set a CORS header. You would do this on whatever backend you're sending the requests to--there's usually some sort of library to make it easy, for example, Flask CORS for Flask. If you need to share cookies in this case, this StackOverflow answer discusses one way of doing it (using an intermediary domain).
Generate a security key for the user session with some TTL in an authentication table when you authenticate the user with your App1
Redirect the user to any other app in any domain with this security key where they can query the authentication table and verify the user.
Let these other applications work on their own (in the front end) and communicate with the back-end with the security key when necessary.
Lot of PHP frameworks has built-in support for this mechanism. My favorite is Silex.

How to authenticate requests to images in an angularJS app using an access_token

I have an angularJS application whose authentication system is made with an access_token and communicating with a backend server written in Go
Therefore to authenticate the user, I have to add the access_token to each request ?access_token=SomeTokenHere or via a header Access-Token: SomeTokenHere
It works great.
The issue is that my backend serves protected images, and I cannot put the access token in the image src for some security reasons(If the user copy/paste the link to someone else, the access_token would be given too ...)
What I'd like to do is to inject a header containing my access token, but since the request is made from the browser it doesn't possible.
This could probably be possible with a cookie, but I'd to avoid using a cookie especially because the angularApp and the backend are not on the same sub-domain.
Another idea would be to create a directive that would get the raw data, and set the data to the image. First I don't know if this is possible and is it a good idea for hundreds of images in the webpage ?
If you have any idea, I'd be glad to hear from you !
Thanks
It is typical problem, and fortunately it was already solved - for example on Amazon S3.
Solution idea is simple: instead of directly using secret key - you can generate signature with access policy, using that key.
There is good algorithm designed especially to generate signatures for this purpose - HMAC
You can have one secret key on your server and use it to sign every image URL before it would be sent to client, also you can add some additional policies like url expiration time...

Resources