How to protect/hide your userId and web token in react? - reactjs

I'm developing simple CRUD app in react and express. Now, When user SignIn, I store the userId(from database) and JWT(web token) in localstorage and I use this userId and token to check isSignin() and isAuthenticated() for future API calls. Now, If I deploy or make production build of this application, the user info will be clearly visible in my localstorage and it can be threat to my security. Can anyone please tell me how to hide this information and implement these mathods in production ready app? I want deploy it on AWS. Because, I've seen on so many website, we cannot see our own userId other credentials in our own localstorage.
here my methods. The req are coming from front end in react and as soon as I am getting response to front-end my react code is storing that in localstorage.
exports.isSignedIn = expressJwt({
secret: process.env.SECRET,
userProperty: "auth"
});
exports.isAuthenticated = (req, res, next) => {
let checker = req.profile && req.auth && req.profile._id == req.auth._id;
if (!checker) {
return res.status(403).json({
error: "ACCESS DENIED"
});
}
next();
};

Randall Degges gave a very detailed explanation about why you shouldn't use localstorage to store sensitive data. I will point out the main part.
If you need to store sensitive data, you should always use a
server-side session. Sensitive data includes:
User IDs, Session IDs, JWTs, Personal information, Credit card information,
API keys, And anything else you wouldn't want to publicly share on
Facebook If you need to store sensitive data, here's how to do it:
When a user logs into your website, create a session identifier for
them and store it in a cryptographically signed cookie. If you're
using a web framework, look up “how to create a user session using
cookies” and follow that guide.
Make sure that whatever cookie library your web framework uses is
setting the httpOnly cookie flag. This flag makes it impossible for a
browser to read any cookies, which is required in order to safely use
server-side sessions with cookies. Read Jeff Atwood's article for more
information. He's the man.
Make sure that your cookie library also sets the SameSite=strict
cookie flag (to prevent CSRF attacks), as well as the secure=true flag
(to ensure cookies can only be set over an encrypted connection).
Each time a user makes a request to your site, use their session ID
(extracted from the cookie they send to you) to retrieve their account
details from either a database or a cache (depending on how large your
website is)
Once you have the user's account info pulled up and verified, feel
free to pull any associated sensitive data along with it
This pattern is simple, straightforward, and most importantly: secure.
And yes, you can most definitely scale up a large website using this
pattern. Don't tell me that JWTs are “stateless” and “fast” and you
have to use local storage to store them: you're wrong!
Source/Read more: Please Stop Using Local Storage

Related

How to correctly store secret keys on React App?

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

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.

Next.js Authentication Strategies

I've been trying to implement a reliable authentication flow for a Next.js project but I'm completely lost now. I've already seen the examples repo of Next.js. But I have a lot of questions for a complete solution.
I have a express.js API and a separate Next.js frontend project. All the data and the authentication is handled by the API. Frontend just renders the pages with SSR. If I would just create a monolith project, where rendering the pages and all the data is handled by a single server (with a custom server option for Next.js I mean), I would just use express-session and csurf. It would be a traditional way to manage sessions and create security against CSRF.
Express.js API is not a requirement. It is just an example. It could be a Django API, or a .Net Core API. The main point is, it is a separate server and a separate project.
How can I have a simple, yet reliable structure? I've examined some of my favorite websites (netlify, zeit.co, heroku, spectrum.chat etc). Some of them use localstorage to store access and refresh tokens (XSS vulnerable). Some of them use cookies and they are not even HTTPOnly (both XSS and CSRF vulnerable). And examples like spectrum.chat use the way I mentioned above (cookie-session + preventing csrf).
I know there is the giant hype around the JWT tokens. But I find them too complex. Most of the tutorials just skips all the expiration, token refreshing, token revocation, blacklisting, whitelisting etc.
And many of the session cookie examples for Next.js almost never mention CSRF. Honestly, authentication is always a big problem for me. One day I read that HTTPOnly cookies should be used, next day I see a giant popular site not even using them. Or they say "never store your tokens to localStorage", and boom some giant project just uses this method.
Can anyone show me some direction for this situation?
Disclaimer: I am a maintainer of the free open source package below, but I think it's appropriate here as it's a common question there isn't a great answer for, as many of the popular solutions have the specific security flaws raised in the question (such as not using CSRF where appropriate and exposing Session Tokens or web tokens to client side JavaScript).
The package NextAuth.js attempts to address the issues raised above, with free open source software.
It uses httpOnly cookies with secure.
It has CSRF protection (double submit cookie method, with signed cookies).
Cookies are prefixed as appropriate (e.g. __HOST- or __Secure).
It supports email/passwordless signin and OAuth providers (with many included).
It supports both JSON Web Tokens (signed + encrypted) and Session Databases.
You can use it without a database (e.g. any ANSI SQL, MongoDB).
Has a live demo (view source).
It is 100% FOSS, it is not commercial software or a SaaS solution (is not selling anything).
Example API Route
e.g. page/api/auth/[...nextauth.js]
import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'
const options = {
providers: [
// OAuth authentication providers
Providers.Apple({
clientId: process.env.APPLE_ID,
clientSecret: process.env.APPLE_SECRET
}),
Providers.Google({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET
}),
// Sign in with email (passwordless)
Providers.Email({
server: process.env.MAIL_SERVER,
from: '<no-reply#example.com>'
}),
],
// MySQL, Postgres or MongoDB database (or leave empty)
database: process.env.DATABASE_URL
}
export default (req, res) => NextAuth(req, res, options)
Example React Component
e.g. pages/index.js
import React from 'react'
import {
useSession,
signin,
signout
} from 'next-auth/client'
export default () => {
const [ session, loading ] = useSession()
return <p>
{!session && <>
Not signed in <br/>
<button onClick={signin}>Sign in</button>
</>}
{session && <>
Signed in as {session.user.email} <br/>
<button onClick={signout}>Sign out</button>
</>}
</p>
}
Even if you don't choose to use it, you may find the code useful as a reference (e.g. how JSON Web Tokens are handled and how they are rotated in sessions.
I've had to think about this as well for my current project. I use the same technologies: an ExpressJS API and a NextJS server-side-rendered front-end.
What I chose to do is use passport.js in the ExpressJS API. TheNetNinja on YouTube has a really good playlist of this with 21 episodes. He shows you how to implement Google OAuth 2.0 in your API, but this logic transfers to any other strategy (JWT, Email + Password, Facebook authentication etc.).
In the front-end, I would literally redirect the user to a url in the Express API. This url would show the user the Google OAuth screen, the user clicks on "Allow", the API does some more stuff, makes a cookie for the specific user and then redirects back to a url in the front end. Now, the user is authenticated.
About HTTPOnly cookies: I chose to turn off this feature, because I was storing information in the cookie that I needed in the front-end. If you have this feature enabled, then the front-end (javascript) doesn't have access to those cookies, because they are HTTPOnly.
Here's the link to the playlist I was talking about:
https://www.youtube.com/watch?v=sakQbeRjgwg&list=PL4cUxeGkcC9jdm7QX143aMLAqyM-jTZ2x
Hope I've given you a direction you can take.
EDIT:
I haven't answered your question about CSURF, but that's because I'm not familiar with it.
I've finally found a solution!
Now I'm using csrf npm package, not csurf. csurf is just turns csrf into an express middleware.
So, I create a csrfSecret in the getInitialProps of _app. It creates the secret, sets it as a httpOnly cookie. Later, it creates a csrfToken and returns it with pageProps. So, I can access it with window.NEXT_DATA.props.csrfToken. If user refreshes the page, csrfSecret remains the same, but csrfToken gets renewed.
When I make a request to the proxied "/api/graphql API route, it first gets the csrf token from x-xsrf-token header and verifies it with the csrfSecret cookie value.
After that, it extracts the value of authToken cookie and passes it to the actual GraphQL API.
API is all token based. It only needs a non-expiring access token. (BTW, It doesn't need to be JWT. Any cryptographically strong, random token can be used. Which means a reference/opaque token.)
CSRF check is not needed for the actual API, because it doesn't rely on cookies for authentication. It only checks authorization header.
Both authToken and csrfSecret is httpOnly cookies. And I never even store them in client-side memory.
I think this is as secure as I could get. Now I'm happy with this solution.

Persisting authentication token in AngularJS

I'm building an AngularJS application that interacts with an API that uses authentication tokens to authenticate users. Everything seems to be working fine, but I'm struggling with a way to properly persist the authentication token between requests.
At the moment, when a user logs in with correct credentials an authToken is returned, and I'm setting that on $rootScope.authToken. I'm also sending that auth token for future requests, but if I do a hard reload reload the webpage with F5 $rootScope gets cleared and I have to authenticate again.
I'm aware I can store the authToken in a cookie, but would that be the most secure way? Am I better off using local storage to store the token? If local storage is used, would that not get cleared when the user restarts their browser? I'd ideally like the login to persist for a few days.
Firstly, I'm not sure what the format of your authToken is but localStorage should not be used for any sensitive data. Using localStorage works great (and survives browser restarts) as long as your authToken is relatively tamper-proof either through some form of encryption or nonce.
Essentially, you should be careful that since the value is "visible" to all client-side users it should be assumed to be possible to modify or increment.
Have you thought about revocation of login sessions? For example, if you want to log out all active sessions of your application, how would you do it? Since the authToken is stored client-side, you may need to add a timestamp (or some other unique value) to it that can be checked server-side.

backbone securityissues

What are the possible security risks one may face while developing a backbone app.Can someone tell me the best practices to mitigate such risks.
as in the router any users can find out the services being called
The secret to securing a Backbone app, or any other client, is that you don't rely on client-side validation. Be sure to validate on the server.
For example, if you were building a banking app, you wouldn't use Backbone to transfer $100 between a user's accounts and then send back to the server the new account balances as model updates. You would instead send to the server the user's intent to transfer $100 and let the server send back the new balances. This way the server can safely determine the user's authorization to make such a transfer between accounts, determine if sufficient funds exist, etc..
Client-side validation is nice to help reduce round-trips and give immediate feedback to the user, but it shouldn't be thought of as a method for securing an app. E.g. Validate the format of an email address or the strength of a password on the client before sending it to the server (where it should be validated again server-side) is a good example of client-side validation.
As for web services, there are different ways to protect them. You can use HTTPS or token-based authentication just for example.
Another issue might be that you expose too much data. For example: don't return a full user record (to populate your models) but instead only return the data actually required for your application.
I've seen examples where (hashed) passwords were sent to the client.
Something to consider when you are securing a backbone app is the access to the app itself.
Build an authentication page where the user enter his login/password then if the authentication is verified, set a cokkie session ID.
For example if you have a main view rendered on http://mydomain.com/app, you have to secure the access to the "/app" by using a cookies validation.
Example if your back-end is nodejs :
app.get('/app', function(req, res, next){
if(!loggedIn(req,res))
sendError(res);
else
next();
});
what loggedIn will fo is basically check if you have a sessionID in your cookies. If yes it will allow you to access your app otherwise an "unauthorised access" message will be prompted to the user.
As mentioned earlier, client side validation is important but you have to re-enforce it by using server side validation.
HTTPS for the web services is also important.

Resources