ReactJS display components based on authentication - reactjs

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

Related

React Native Storage

A while ago I made an app using React Native and was not able to store data like token and user ID for future use. Currently I am making a Point transaction app in React Native using Expo and was wondering if there is a way of storing required data to all the pages just like the web has a localStorage.
App Functionality:
Users can login to their account and the response has the token, user ID, user Name and member No. On the dashboard it shows points gained, redeemed and points available.
Still on the dashboard it can show the last five transactions and if one is clicked, it navigates to a transaction details page which its API requires the token, user ID and member No.
A profile page to edit user details or logout.
I was able to achieve all that by passing those details as route params but after adding a bottom tab navigation the app crashed since stack Navigator differs from Tab Navigation.
P.S. I have tried Async Storage but the app requires a page refresh to get those data (ie. token, id, memberNo)
If I don't misunderstand what you want is to be able to share the AsyncStorage values with the rest of your application, for cases in which you want to share states (such as tokens or values of a user's identity) use parameters navigation becomes deficient and uncomfortable to use when wanting to send states or state values from a higher level to a lower one, even more so in large applications that already have many layers. For this you have two options, the use of Redux to make it easy to access your data throughout your application, or you can also use the useRef hook which is a quick output that is already plugged into the react native libraries useRef hook

Saving user data in redux but not in localStroage

I have user data which includes Email,Username,Password,ShippingAddress etc..
I am storing jwt token in localStorage, the token is includes :username,id,createdAt..
I want the user data to be persisted to my redux-store but I can't figure out how to do it.
I don't want user info to be in local storage but on the other hand everytime I refresh the page my user data from redux getting deleted, I kinda stuck.
Tried to do simple check that if localstorage(jwt) id is equal to the user that just logged in - store the data in store and it works, but as I said one refresh delete all..
Would like to get some hints\tips from the pros! :)
Using: graphql\apollo, redux toolkit, react.
My best idea was to have requests from the server on every component that I need username \ email \ password ..etc but I think it will be too massy..
React is just JavaScript, and as such, any data that is stored in React will not persist and will be lost when the page is refreshed. Any information that you want to persist after a page refresh will need to be stored somewhere else (i.e. local storage).
There are ways to retrieve information from local storage and store them (non-permanently) in Redux after every page reload. How that solution looks will differ depending on how you are using React.
If you are using functional components and hooks, the useEffect hook can be used to retrieve data from localStorage after every page reload. Click here to read the docs on useEffect. It might look something like this:
useEffect(() => {
const storedData = JSON.parse(localStorage.getItem("storedData"));
// save to component's state or redux here.
}, []);
If that useEffect is placed somewhere in your app component, it will run on every re-render, thereby making it seem like the data is persisting in React because it will always be there.
Normally the flow that you would have should be smth like:
User logs in e.g /api/v1/login,
Sever returns either a temporal token (in case you are using otp codes or 2fa), or the user jwt that will be used for authorizing subsequent requests.
Token is saved in local storage.
When the user refreshes the page you check local storage and use the token on a request to the server (this way you can check it's still valid, normally you can do smth like /api/v1/user to get the user data.
If the token is valid then you can store the user info returned by the API call into the redux store. If not you can redirect user to login page again

Preserving state upon redirect, no redux or react-router

I am creating a React app as a personal project. I am using OAuth with implicit grant flow, which has my user redirect to a different page for auth, then redirects back to my app. Everything is working as I expect, but when the user is redirected, all my state is cleared.
For example, my user finds a specific book from a list of books, this takes the user from the index page to that specific book's show page, and the book's ID is saved in component's state. When the user wants to save this book to their personal account, they log in through OAuth and come back. Now the book is no longer saved in the state and the user needs to search and find it again as a logged in user. I want to avoid using redux and react-router if possible, and the only workaround that I've thought of so far is to save the book ID into localStorage, which I'm not sure is a good practice.
Is there any other way I can get around this?
When you redirect the user to the login page, you can provide a URL param like afterLoginRedirectionUrl that contains the book id, e.g. /books?activeBookId=3
In the log in component, after success, redirect to that url if the param afterLoginRedirectionUrl is present. This way, when going back to /books?activeBookId=3, you can set the initial state of your component to the active book id present in the URL.
About your comment:
I want to avoid using redux and react-router if possible
Redux or react-router won't solve this problem. They store the data in the same way you do it right now, In memory, and as soon as you refresh or close the page all the data will be lost.
About using localStorage: if it is working for you, you can continue using it. It is standard and supported in all major browsers. In case you are dealing with very structured data, maybe it will be good to take a look to IndexedDB too.

Caching User after Authenticating with apollo

I'm quite new with react-apollo, however wasn't sure how to approach this problem. I'm authenticating a user with a mutation but would like to access that same user object, that's returned in other components again (live navbar, to render button options, or a profile button once logged in). Should I just fetch the current logged in user everytime I need it? I.e.
query GetUser {
id
name
role {
name
}
dob
}
Append this at the end of every component that needs it? I'm not sure if the best way might be to just cache it after logging in once versus this Even then how do you specifically cache it? I know inheritently it caches it as well, so its not like i have redundancy in fetching, however i might in code. What are some approaches y'all took.
in react applications to save user data for authentication you have to save user data in storage like local storage and store to your global state of your application like redux and mobx to access from all over the application.
i recommend to you using redux.
note:
every time when start application you have to store data from storage to global state again.
also you can use apollo-cache-persist but i don't tried this!

React and views on registration and confirmation processes

I´m learning React (so understand the why of my question).
I created an API with AWS and the front-end is React+Redux.
To access the API data the visitor has to register. For that, it has to create an account.
Once the visitor created the account, he will receive an email with the confirmation code... Code that he was to provide on my view.
Between the creation view and process and the confirmation view (just and input where user has to enter the code and hit a button), the user can...
Stay in that page (1)
Close that tab (2)
Close the browser (3)
So, and here´s my question: Which is the proper way to NOT render the create user view once the visitor create an account and until he confirms it, in a single page app where the root page renders all the views through conditionals (local state and Redux store).
Initially, I thought in Local state. It worked just for case 1.
Then, I thought… “I can create a localStorage where the key could be user and value the user that we visitor picked. And, until he introduces the code and hit the button, and, consequently remove that item for the localStorage, avoid rendering the create view”.
However, I do want to know you considerations. I´m not a big fan of cookies. Also,
I didn´t want a Session storage since I want to be persistent.
I will appreciate any kind of suggestion.
Thanks for your time.
You can use local state take one new empty state.
Now set the state value when user introduce the code using
this.setState({}) method once you get the code in state you can check the value present in the state or not the time of click event at button. If your state has code then it should go further else you give error message or popup message to user to enter code.

Resources