React check authentication on startup - reactjs

I have a React website right now that requires a login. When you load the page, react needs to check whether you are logged in (by calling the webserver).
If the user is logged in (isAuthenticated = true) the user is shown the website and if (isAuthenticated = false) the login page is shown.
isAuthenticated = false by default so when the if the user is logged in the user briefly see the login page before user can be checked to be logged in.
How do other websites handle this issue? It looks like Facebook is able to know on startup whether you are logged in or not.

It sounds like you have the authentication set up already, you're just trying to prevent authenticated users from seeing the log-in page flash onscreen on initial load.
If that's the case, you could initially set isAuthenticated to a non-boolean value (null or undefined), show a loading component while authentication is occurring, and render the app only when ready.
For example, in your main App file, you could use something like:
render() {
// use strict equality check
return isAuthenticated === null ? <IsLoading /> : <App />
}
Where <IsLoading /> is a loading spinner and <App /> is the component you're currently rendering from the start.

Related

How to secure a component in Reactjs?

I have created two React components, Login, and Secure. Login hosts the FacebookLogin component found in this package: https://www.npmjs.com/package/#greatsumini/react-facebook-login, and I get a successful response from Facebook by the login attempt when the button is pressed. This is supposed to navigate to the Secure page when successful.
The problem is that I can just navigate directly to the Secure component in the URL, (I'm using react-router-dom package for this), but I want any attempt to navigate to a secure page to be redirected to the Login page.
How can I do this?
According to that component's documentation, you can get the login status in code:
FacebookLoginClient.login((res) => {
// "res" contains information about the current user's logged-in status
});
So in any component that needs to know the status, simply reference the library:
import { FacebookLoginClient } from '#greatsumini/react-facebook-login';
And use that FacebookLoginClient.login to check the user's logged-in status. If the status doesn't meet the criteria you define, redirect the user. (For example, you can check this in a useEffect when the component first loads, or perhaps on every render if you're paranoid about it.)
For more detail on rendering the target component, since useEffect occurs after the initial render, you can rely on additional state to check. For example, consider this structure:
const [canRender, setCanRender] = useState(false);
useEffect(() => {
FacebookLoginClient.login((res) => {
// check the status and call "setCanRender" accordingly
});
}, []);
if (!canRender) return <>Checking authentication...</>;
// your existing return for the component goes here
The idea here is to default the component to a kind of "loading state" and only render the "secure" content after the authentication has been verified.

redirecting not signed in user in react and firebase

I've seen this solution:
firebase.auth().onAuthStateChanged(user => {
user ? history.push("/dashboard") : history.push("/login");
renderApp();
});
from How to redirect to Login page when users not logged in the application
the issue with this is that when the user reloads the page (they will still be signed in, but it redirects them to the dashboard page and wipes everything from the url)
How can i solve this?
You have a couple options:
1. Not redirect them if they are logged in
You could just do nothing onAuthStateChanged if the user is logged in.
That could look something like this:
firebase.auth().onAuthStateChanged(user => {
user ? null : history.push("/login");
renderApp();
});
The benefit of this is that the user may enjoy not being forced to navigate on login so this solves that. But he downside is that if there is a reason that in certain cases that you want them to be redirected, nothing will happen.
2. Use a function to conditionally redirect if they are logged in
If the user is on a page with something in the url you may not want to redirect them. Maybe they are on a page for a certain shop item (or any page) and the url is .../shop?item=7987 and you don't want to lose where the user was. But there may be other pages such as a general info or login page where you do want the user to be redirected.
If this case you could call a function like this:
firebase.auth().onAuthStateChanged(user => {
user ? conditionallyNavigate() : history.push("/login");
renderApp();
});
And then inside the conditionallyNavigate() function you can decide what you want to do based on other factors. For example, you could change the behavior based on data stored in state, or you could check the route they are on or the URL parameters and determine if they should be redirected this way. For example:
const conditionallyNavigate = () => {
if ( onCertainPage() ) {
history.push("/dashboard")
}
}
This gives you the benefit of control over when they should be redirected or when you think they are on a page they would like to stay on.

MERN How to show modal or toast ONLY when user has just logged in or registered an account

Someone new visits my web app and decides to sign up. When they sign up they are taken to the dashboard. Upon visiting the dashboard for the first time Id like to welcome them with a toast message or a modal.
I am using passport local and passport google oauth2.0. which always sends back a req.user object with properties.
I am not sure how to set up a useEffect to trigger this message when they visit the dashboard. Do I do something like
const useEffect(() => {
// show toast or modal
},[// based on cookie time? or some req.user prop?])
You can simply use LocalStorage or cookies to know if user is logged in or not then in your useEffect you can do something like this.
useEffect(()=>{
//don't store any user info in local storage only flag
const isLogin=localStorage.getItem("flag")//you can also use cookies
if (isLogin==true)
{
showModal(true);
}
},[showModal])
//in your return
return(
showModal==true?<Modal/>:<></>
)

How do I make my web app's main page look different depending on whether the user signed in

I'm creating a full stack application using reactjs and spring boot. My main page has a login button, which when you click it takes you to the login page. (I'm using React Router.) Ideally, i would like that when someone logs in successfully, they are rerouted back to the main page- which now has additional features. (like saying "Hi (username)") I'm not sure how I would do this, please help!
...
state = { isSignedIn: false }
render() {
<div>
{this.state.isSignedIn ? <div>Stuff to show if signed in</div> : <div>Stuff to show if not signed in</div>}
</div>
}
...
In your login handler call setState on isSignedIn to toggle it to true.

Best way to reload a ReactJS component to read from localStorage

Context: I have a <Header /> component that has a button which redirects the user to a <SignIn /> component. The <Header /> component is always displayed, however when the user is signed in, the Login button disappears and replaced by the user's name.
I will not go in detail about the authentication mechanism, but let's just say it is based on a JWT that is stored in localStorage. I have the following piece of code in <Header /> in order to read the cookie and determine whether to show the login button or not:
componentDidMount() {
const token = localStorage.getItem("token");
if (token) {
this.props.fetchUser();
}
}
...
However this only works on a browser refresh or if I use the native JS window.reload(). If I use react router redirections, the Login button in the <Header /> component is not refreshed and still displays (although the cookie is set).
I am wondering what is the best practice, and avoiding the whole page refresh...
So it is super pseudo code, but hopefully that would be enough :)
class App {
const handleLoggedIn = () => {
const token = readFromLocalStorage()
if (token) {
this.setState({token})
}
}
<Header token={this.state.token} />
<Login onLogin={this.handleLoggedIn}
}
class Login {
// After loging in and setting your token to your local storage:
this.props.onLogin()
}
class Header {
if (this.props.token)
<User />
else
<Login />
}
So once you are logged in and set your token to the local storage, you just call the parent function handleLoggedIn which will try to retrieve the token from your local storage. If it is set, it will re-set it as your App state, which will refresh your Header component as one of its props has been updated
(But that mainly depends on how you've implemented the rest of your code and how easily you can access the parent function from your login flow as pointed by Dubes)
Two possible scenarios I can think of:
Scenario 1
You've someway of hooking into the flow when user signs in. For e.x. maybe your auth system is setting a success flag in header/query or perhaps the component which writes the jwt to the localstorage is in your control/tree.
In that case, you should be derive that information and be able to set a prop which your header component can use.
Scenario 2
You don't have any way of hooking into your auth workflow and can only read the localstorage item. For e.x. a user has signed on with SSO and you want to reflect that without having to refresh the entire page.
I think you can use a setInterval to read the state of the cookie and set a state in your header component. As long as you are not doing intensive calculations in your setInterval code, it should not be an overhead. Do remember to clearInterval on unmount.
Take a look at this example in official docs for inspriration.

Resources