How to persist logged in user without going back? - reactjs

I'm currently working on a web platform using React Js. I have stored backend token into my local storage but once the user signed in successfully then he should not go back with browser back arrow click. He should persist in the same page so how can I do it in react js? can I use useEffect hook there? Or I have to write any conditions for that? Only by clicking Logout button he should come back not with browser coming back arrow. Some people did it using componentDidMount but I'm in functional component so I used useEffect but It was not working. I tried multiple ways but unable to find solution. How can I achieve it in react js?
Thanks in advance.

You can use a user context, where upon login the user information is stored in localStorage and in the context api.
const storeUser = ({user, token}) => {
localStorage.setItem('user', JSON.stringify(user));
localStorage.setItem('token', token);
setUserState((prevUserState) => ({ ...prevUserState, user, token}));
};
then your data will be persisted throughout the website as long as you implement your user context correctly. To be clear, if you implement the context correctly, pressing back won't clear the localStorage or user state.
I'm afraid that if you try and implement it in a functional component by itself, the data will be wiped on re-render.
If you want to check whether or not a user has signed in then you can modify your site to allow access only to users that have signed in, by either coding it inline
{user.singedIn ? (<h1>Hello user</h1>) : (<h1>please sign in</h1>)
or in your routes
<Route path='/' element={!user ? <Navigate replace to='/login' /> : <Home />} />

Related

Difficulty in Authorization part in Reactjs

Having Difficulty in Authorization part in Reactjs.In my app.js got permissions from backend and passed permissions to all components via context api . my main problem arise when user go to usercrudauthorisation.js ,and toogle the switch on / off then Permission value changes accordingly But my context api provides value i.e "u_create": 1,"u_delete": 1 at loading app.js component.The changed toogle switch button value will load when i reload the whole comoponent and re-render the app. I have supplies modulepermissions value according to module_name and what user can perform CRUD in that module via context api. i think route changes doesnot re render the app.js while route changes so that it provides module permissions accordingly? how to solve it? what will be best way to achieve it?
**app.js**
const getPermissions=()=>{}
above function return permission={"id": 1,"module_name": "Product","role": "users","u_create": 1,"u_delete": 1,}
that i have Passed to all components via context api shown in below code
let curr_module=routes.filter(route=>{
if(window.location.pathname===route.path){
return true;
}
return false
})
let curr_module_permission={}
if(curr_module&&curr_module.length>0 ){
let curr_permissions=permissions&&permissions.filter((p)=>{
if(p["module_name"].toUpperCase()=== "PRODUCT" ) {
return true
}
return false
})
if(curr_permissions.length>0){
curr_module_permission=curr_permissions[0]
<UserContext.Provider value={{ permissions : curr_module_permission}}>
**Usercrudauthorization.js**
Two toggle switch button i.e create ,delete i.e ON/OFF

Handling signin flow in React

I'm trying to implement Last.fm signin in React. After the user logins to Last.fm, they are redirected to
http://localhost:3000/loginlanding/?token=${token id goes here}
How do I capture the url using React Router?
So far, I have tried all these:
path="/loginlanding/?token:id"
path="/loginlanding/:id"
path="/loginlanding/?:id"
None of these seem to work.
Basically, I need to capture the access token and store it in global state.
specify route
<Route path="/loginlanding/:token_id" component={LoginLanding} />
pass token
<Link to=`/loginlanding/${token_id}` />
get token
this.props.match.params.token_id
**you can store your token in the localstorage and access it from there whenever needed.
Or if the token is available in the parent component you can access it as a prop like this.
**
{match:{params:{id}}} //<<<< This can be accessed in the react-router

Redirecting after successful action

I am currently working on a authentication project within React Native using the react-navigation package. So far so good, I have 3 Navigators setup, one for loading, one for auth and one for the application.
I have also got the navigation setup with redux so I can access it from any component via a prop, which is exactly what I wanted to do.
However, I have a question. I have done some research and can't seem to figure out the best way to do this.
I am dispatching an action from a press of a button attemptLogin() the attempt login then does what it says on the tin, it attempt to login.
After a successful login, I store the access_token in SecureStore using expo.
Now, upon the successful login I need to navigate away from the current stack onto the new one.
What would be the best way to do this, can you return a promise from a redux action? If so would the best way to be inside of the component and then inside of the component do something like
this.props.login(username, password).then(() => { this.props.navigation... });
Or would you do it inside of the action?
A recommended way as below:
componentDidUpdate(prevProps) {
if(this.props.loggedInSuccessfully && !prevProps.loggedInSuccessfully) {
this.props.navigation.navigate....
}
}
onLoginButtonPress = () => {
const { username, password } = this.state;
this.props.login(username, password);
}
Upon successful logged in, update a state loggedInSuccessfully in your reducer and implement logic in componentDidUpdate. This way is the clearest for whoever gonna maintaining your code, in my humble opinion
you can also navigate from redux action or everywhere you want.
read the official docs about navigation service.

React : How to safely display a component according to user role

I am trying to display an admin Dashboard in react and Meteor only if the current user is an admin.
I am calling a server method that checks the user permission and rendering the admin component only if this method returns true.
This server call is asynchronous and thus the component is not rendering, usually I manage this asynchronous call with state, but I don't want to expose anything in state here (wouldn't like someone to change the state and access the admin dashboard).
Here is the code:
export default class AdminChecker extends Component {
isItAdmin() {
// Get the id of current user
const userId = Meteor.userId();
if (userId) {
// call a server method which returns true if current user is Admin
Meteor.call('checkAdminId', userId, (err, authorized) => {
if (err) {
console.log(err);
return null;
}
return (authorized) ? <AdminDashboard /> : null;
});
}
}
render() {
return (
<div className="admin-temp-container">
{this.isItAdmin()}
</div>
);
}
}
I think I can have this logic in a parent component and send the result of isItAdmin to adminDashboard as a prop (the adminDashboard component would display information only if its props is true).
But I am insure if this is safe. Could one change the props with Chrome react developer tools or something like that?
Thanks a lot
I think there are two parts to this (and the comments are hinting at both):
First, you should not expect to be able to enforce security on the client. You must implement access control logic on the server (i.e., any API that performs an admin action must check that the user performing the action is an admin).
Once you've done that (and perhaps you already have), then you likely need to use props or state to store whether or not the user is an admin (just like you would store any other data in your app).
The key point is that once you enforce security on the server, then it doesn't really matter if a user manipulates the state to get to the admin dashboard: the server will not let the user view any real data or take any actions anyway.
This is completely unrelated to server-side rendering. You can most certainly build a secure admin dashboard without server-side rendering, as long as the APIs used to fetch the admin data and perform admin actions are implementing their own access control checks.

React/Redux Where to save State

I am having trouble understanding some ReactJS and Redux principles,
In Redux we have a store and a set of reduceres that give your final state ( this part I get).
A Component receives props from their parent component, in case of Redux it passes the full state down with the Provider Component.
Now, lets assume this use case, I have my app state something like this :
auth : { name,id, ..etc} -> this is actually a JWT Token with a set of claims...
I am building a Container (Page) to be able to edit user profiles, the catch here , and where I am having trouble, I also want this page to handle a arbitrary user edit (in case admin is editing a account).
I am rendering my Page by using redux-router like this :
<Route path="/user" component={RequiresAuth(UsersPage) } >
<IndexRoute component={RequiresAuth(UsersOverview) }/>
<Route path="/user/overview" component={UsersOverview} />
<Route path="/user/account" component={AccountManagement} >
<IndexRoute component={RequiresAuth(AccountManagement) }/>
<Route path="/user/account/:userid" component={AccountManagement} />
</Route>
So reading the docs, I assume my props will have a userid which will override my default user if present.
Questions:
Is this approach correct? The Route Handling?
If I pass a userid param on the route, how do I proceed to load the user info and where? The way I see it, I need to dispatch an action, but I am not sure where to set the state , if on the store, or the component.
Also, Where would I load my user information? (constructor comes to mind)... or should it be in WillMount/WillReceiveProps?
Thank you.
If you really have a hard time to understand React/Redux principles i suggest you to try this tutorial :
https://github.com/happypoulp/redux-tutorial
It helped me a lot when i first started with React/Redux. By the way it's a bit hard to really answer your question because you re asking specific questions on a really specific case :)

Resources