I’m trying to create a react SPA, using AzureAD/MSAL for authentication. I have a Landing page at /
with a Login button and a separate app Home page on a /home
route. If someone tries to navigate directly to /home
without authenticating, I want to redirect them to the Landing page.
I do this with:
const navigate = useNavigate();
const { instance, inProgress } = useMsal();
const isAuthenticated = useIsAuthenticated();
useEffect(() => {
if (inProgress === InteractionStatus.None && !isAuthenticated) {
navigate('/');
}
}, [inProgress, isAuthenticated, navigate]);
Which seems to work as intended when navigating directly to /home
.
The Issue I have is when the user first goes to the Landing page and logs in, it goes to /home then this redirect still kicks in and takes the user back to the Landing page. On clicking the Login button again, it does go to /home
successfully. Is this because the first time /home is loaded before authentication is fully complete? How do I wait for auth to complete?
Code:
import React, { useEffect } from 'react';
import { BrowserRouter as Router, Routes, Route, Link, useNavigate } from 'react-router-dom';
import { MsalProvider, useMsal, useIsAuthenticated } from '@azure/msal-react';
import { InteractionStatus } from '@azure/msal-browser';
import ReactDOM from 'react-dom/client';
import { PublicClientApplication } from '@azure/msal-browser';
import { msalConfig } from './js/authConfig';
const LandingPage = () => {
const { instance } = useMsal();
const handleLogin = () => {
instance.loginRedirect();
};
return (
<div>
<h1>Landing Page</h1>
<button onClick={handleLogin}>Login</button>
</div>
);
};
const HomePage = () => {
const navigate = useNavigate();
const { instance, inProgress } = useMsal();
const isAuthenticated = useIsAuthenticated();
useEffect(() => {
if (inProgress === InteractionStatus.None && !isAuthenticated) {
navigate('/');
}
}, [inProgress, isAuthenticated, navigate]);
return (
<div>
<h1>Home Page</h1>
</div>
);
};
const msalInstance = new PublicClientApplication(msalConfig);
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<MsalProvider instance={msalInstance}>
<Router>
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/home" element={<HomePage />} />
</Routes>
</Router>
</MsalProvider>
</React.StrictMode>
);
My msalConfig has
redirectUri: "/home",
navigateToLoginRequestUrl: false,
2
Answers
try with setting loading state
From what I can find it seems that this is the correct way to handle this, when the HomePage component mounts, the authentification process should be either in progress or already finished and the user is authenticated unless there is a moment where both are
false
juste beforeisAuthenticated
passes totrue
.you still can try this:
if you cannot handle it this way then what about navigate to the HomePage only when the user is successfully authenticated? just leave the HomePage as it is and on the landing page, when you click the login button, you just login without redirect and set
isAuthCompleted
state totrue
then whenisAuthenticated
istrue
you navigate to the home page, it seems more logical, redirecting the user to the homepage only when he finishes the authentication process:this should solve the issue.