Can react state be tampered with to bypass security measures? - reactjs

I have two components. One component that the user must use to login and one component to show some content.
I was thinking of implementing my application by having one component that has some react state that tells it to render either the login component or the other one.
If I do this, would it be possible for on the client-side to manually set the state so that the login screen is bypassed and the content is shown?
EDIT: Added some example code.
render () {
if (this.state.authorized) {
return <Content />
} else {
return <Login />
}
}
With this code in mind, given that only the <Login /> component is capable of setting the authorized state to true, is it possible for the client-side to simply get around this by manually setting the state somehow? For example through the chrome react dev tools or something?

Client-side JavaScript isn't secure by design, i.e. user has full control over the script that runs in user's browser. Considering that a user has enough access rights locally, the code always can be read and modified. Security measures that are applicable to client-side code only make this process more complicated.
This isn't unrelated to security, as long as the access to sensitive data is controlled by the backend.
It's certainly possible to change component state and show a component that wasn't supposed to be shown. For instance, React dev tools can be used for this demo to set authorized to true:
A user basically ruins own experience with the application. A blank component will be shown without sensitive data because a user skipped backend authentication process.

Related

How do I make my React App secure? As of now I can login using React DOM Tools, what am I missing?

I am currently learning by doing. So I've created the backend using FeathersJS and am authenticating through the endpoint just fine. When the user gets authenticated I set the 'isLoggedIn' state to true and then pass that along to other components to make sure that the user is logged in so they can access that component.
Now when I see and test it using the REACT DOM Tools, I can see that I can just login by clicking on isLoggedIn and it will give me access to my app bypassing the whole login system.
What is the correct way to create a login setup? Can the isLoggedIn state be hidden somehow? Please help!
I've been looking around for information on how to do this but I haven't found anything that useful yet..
Screenshot
You could make use of session cookies. Or I often find myself using Passport.js. But of course this implys that you have control over the server and database.

ReactJS display components based on authentication

I have a ReactJS front-end app mixed with a Laravel back-end app.
I'm facing a problem with auth. I'm authenticating the user with Laravel auth but I have some trouble on displaying components. I have some posts (/posts/1 or /posts/2 etc...) and when the user visits the page, he can modify the post if he is the author.
I'm storing as a state the id of the user and checking like this :
if(this.props.user.id === this.props.posts.id_user) ...
But this is really unsafe since the state can be modified by anyone with the dev tool. By modifying the state, the user could modify a post even if he is not the author because all displayed components managing the edit would be accessible for him.
Is there a "magic" trick to prevent it?
First of all, the state you are talking about is the app state, the one that resides in the browser, if the user change that state, the effects will only be affected by the user itself, in his browser, theoretically, is not changing the data or state in your backend/database, unless you don't implement the same validation you are talking about.
If you do if(this.props.user.id === this.props.posts.id_user) in your front, you absolutely have to do it in your back, that is the place where the real validation counts, that's where the user can't change the user id, because, for example, you will be using the one in the user session that is stored in cookies or a Redis server.
Always validate in the backend

React and Firebase: Show Components only after successful login

I am trying to make an app for my billiards league using React and Firebase. I want to have users log in and THEN be able to see the full app (calculator for determining races, schedules, teams, etc.). I am storing the status of whether someone is logged in or not in the parent component's state (e.g.: this.state = { loggedIn: true }). The Firebase login/logout works just fine, as does the React conditional rendering of components based off the aforementioned state. The state defaults as false and changes to true based on firebase.auth().onAuthStateChanged (which also functions just fine).
The problem I'm having is that there's currently nothing stopping an enterprising individual - one who has no account with my app and is not logged in - from opening the React dev tools and toggling loggedIn to true, and thus revealing all the goodies.
I've viewed a number of tutorials (like this CC-Tricks one) for React and Firebase that say to do exactly that - store the authentication status in the component state. I also think there is an easy way to do what I need my app to do, but I probably am just overthinking/ too noob. Any pointers?

Apollo graphql-connected React component isn't rerendering

I'm working on building an authentication mechanism over graphql, and I'm trying to figure out why a graphql-connected component isn't rerendering after relogin... for example:
At /users I have a react-apollo graphql-connected Users component that requests a list of users.
The server will return an authentication error if no token is provided; the component renders a <Redirect> to the /login route; after successful login, the Login component stashes the token and redirects back.
The Users component wrapper starts the graphql request and renders "loading..." in the meantime. When the graphql request succeeds, it rerenders and the users appear, yay.
If you Sign Out from that page, the Logout component at /logout discards the token then redirects back; the Users component's request gets the authentication error again and sends you to '/login'.
After another successful login, you're sent back to '/users'; again it starts a graphql request to the server (and renders "loading..."), but this time, when the request succeeds, the component isn't updated again.
I can see that the graphql request succeeds (and have watched in Chrome's debugger as the APOLLO_QUERY_RESULT action is handled by react-apollo's reducer and updates the state in the store).
I've tried to find where React is checking to see if the component's props have changed, but I'm enough of a React debugging noob that I haven't figured out where to find that code in the web inspector: maybe something I don't understand about how React is packaged for distribution.
I clear out the ApolloClient's store (by calling resetStore()) on both login and logout, since I don't want to accidentally reuse data from the other authenticatedness; however, removing these calls doesn't get rid of the problem. Interestingly (?), if I force the connection to bypass the cache by providing { options: { fetchPolicy: 'network-only' } } in the graphql() call, the problem goes away. (Not a viable solution - I'd like to benefit from the cache generally.)
I've built a stripped-down example: https://github.com/bryanstearns/apollo-auth-experiment
and you can see it in a CodeSandbox: https://codesandbox.io/s/m4nlpp86j (you'll probably want to access the running example from an independent browser window at https://m4nlpp86j.codesandbox.io/ because the sandbox editor kinda makes the web debug extensions act weird).
To fix this behavior, modify your graphql HOC to include notifyOnNetworkStatusChange in the options.
export const Users = graphql(usersQuery, { options: { notifyOnNetworkStatusChange: true } })(RawUsers);
I don't think you should have to do that -- I think data.loading is supposed to accurately reflect the status of your query regardless of that option being set to true, unlike data.networkStatus but it looks like it's a known bug.
As far as resetStore -- it doesn't actually wipe your entire store, but rather wipes away your store and refetches all your active queries. If you wanted to blow away your store, since you're already integrating Redux with Apollo, the easiest thing to do would be to create an action to do that.
You may also want to consider a session-based authentication mechanism, rather than relying on the client to persist a token. It's pretty simple to implement server-side, would not only involve less work on the client-side (don't have to remember to pass the token in with every request), and would let you keep your user logged in after they navigate away from the page.

Login flow with ExNavigator and Redux?

I'm working a React Native app using ExNavigator and I want to use Redux. I want a basic login flow, by which I mean:
User clicks "Log in" with correct info
Redux does a usual async flow through redux-thunk or something
When the user is logged in/request was successful, move to Profile route
I've done Redux login in the web, but I am sort of confused as to how to move ExNavigator to the Profile route when the login works because the Navigator object seems to be contained completely in the components and not Redux.
Any pointers?
A pattern I use often is detecting state changes in my component's componentWillReceiveProps, and triggering the navigation transition from there.
Let's say your state contains a property isLoggedIn, which you set to true when the login is successful. The property is also passed as a prop to your component. You can then:
componenWillReceiveProps({isLoggedIn}) {
if (isLoggedIn && !this.props.isLoggedIn) {
this.props.navigator.push(nextRoute());
}
}
This might not be the most elegant way of solving the problem, but it works. The React Native Navigator, and consequently ExNavigator built on top of it, does not lend it self easily to the Redux architecture.
React Native team is working on a new navigation API, currently known as NavigationExperimental, which ships with latest versions of RN. It works nicely with Redux (example), but as its name indicate, it's still very much experimental.

Resources