skip to Main Content

Authconfig.js

export const msalConfig = {auth: {clientId: "client-id",authority: "``https://login.microsoftonline.com/tenant-id``",redirectUri: "``http://localhost:5173/home``",},cache: {cacheLocation: "sessionStorage",  issuesstoreAuthStateInCookie: false,},};

main.jsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import { MsalProvider } from '@azure/msal-react';
import { PublicClientApplication } from '@azure/msal-browser';
import { msalConfig } from './Authconfig';  
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import { ProtectedRoutes } from './utils/ProtectedRoutes.jsx';
import { AboutComponent } from './AboutComponent.jsx';
import { AdminComponent } from './AdminComponent.jsx';
import { BuildComponent } from './BuildComponent.jsx';
import { ContactusComponent } from './ContactusComponent.jsx';
import { FeedbackComponent } from './FeedbackComponent.jsx';
import { LandingPageComponent } from './LandingPageComponent.jsx';
import { LoginPageComponent } from './LoginPageComponent.jsx';
import { ReleasenotesComponent } from './ReleasenotesComponent.jsx';
import { UserHomeComponent } from './UserHomeComponent.jsx';
import { PricingComponent } from './PricingComponent.jsx';
import { UserProfileComponent } from './UserProfileComponent.jsx';
import './index.css';
import { AuthProvider } from './utils/AuthContext';

const msalInstance = new PublicClientApplication(msalConfig);

const router = createBrowserRouter([
  {
    path: '/',
    element: <LandingPageComponent />,
    errorElement: <div>404 not found</div>,
    children: [
      { path: '', element: <AboutComponent /> },
      { path: 'pricing', element: <PricingComponent /> },
      { path: 'releasenotes', element: <ReleasenotesComponent /> },
      { path: 'contactus', element: <ContactusComponent /> },
      { path: 'signin', element: <LoginPageComponent /> },
      { 
        element: <ProtectedRoutes />,
        children: [
          { path: 'home', element: <UserHomeComponent /> },
          { path: 'build', element: <BuildComponent /> },
          { path: 'admin', element: <AdminComponent /> },
          { path: 'userprofile', element: <UserProfileComponent /> },
          { path: 'feedback', element: <FeedbackComponent /> },
        ],
      },
    ],
  },
]);

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <MsalProvider instance={msalInstance}>
      <AuthProvider>
        <RouterProvider router={router} />
      </AuthProvider>
    </MsalProvider>
  </React.StrictMode>
);

Loginpagecomponent.jsx

import React, { useContext, useEffect } from 'react';
import { useMsal } from '@azure/msal-react';
import { loginRequest } from './Authconfig';
import { useNavigate } from 'react-router-dom';
import loginimage from './assets/loginimage.svg';
import { AuthContext } from './utils/AuthContext';

export const LoginPageComponent = () => {
  const { instance } = useMsal();
  const navigate = useNavigate();
  const { login } = useContext(AuthContext);

  const handleLogin = () => {
    instance.loginRedirect(loginRequest);
  };

  useEffect(() => {
    instance.handleRedirectPromise()
      .then((response) => {
        if (response) {
          console.log('Authentication Response:', response);
          login(response.account);
          navigate('/home');
        }
      })
      .catch((error) => {
        console.error('Authentication Error:', error);
      });
  }, [instance, navigate, login]);

  return (
    <div className="bg-white">
      <div className="grid grid-cols-2 justify-center items-center m-20">
        <div>
          <img
            loading="lazy"
            src={loginimage}
            className="self-end max-w-full aspect-square w-[540px]"
          />
        </div>
        <div className="flex flex-col ml-5">
          <div className="flex flex-col p-10 mt-5 w-fit items-center justify-center rounded-lg shadow-sm bg-sky-600 bg-opacity-20 text-zinc-800 max-md:px-5 max-md:mt-10">
            <div className="text-4xl font-black text-sky-600">
              <span className="font-medium">Welcome to</span>
              <br />
              <span className="text-5xl text-sky-600 leading-[62px]">
                buildNow Portal
              </span>
            </div>
            <button onClick={handleLogin} className="w-96 px-8 py-3 ml-6 rounded-lg bg-indigo-500 text-gray-100 border border-gray-200 placeholder-gray-500 text-sm tracking-wide font-semibold hover:bg-indigo-700 transition-all duration-300 ease-in-out flex items-center justify-center focus:shadow-outline focus:outline-none mt-5">
              <svg className="w-6 h-6 -ml-2" fill="none" stroke="currentColor">
                <path d="M16 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
                <circle cx="8.5" cy="7" r="4" />
                <path d="M20 8v6M23 11h-6" />
              </svg>
              <span className="ml-3">
                LOGIN
              </span>
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};
Authcontext.jsx
import React, { createContext, useState } from 'react';

const AuthContext = createContext();

const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(() => {
    const storedUser = localStorage.getItem('user');
    return storedUser ? JSON.parse(storedUser) : null;
  });

  const login = (account) => {
    setUser(account);
    localStorage.setItem('user', JSON.stringify(account));
  };

  const logout = () => {
    setUser(null);
    localStorage.removeItem('user');
  };

  return (
    <AuthContext.Provider value={{ user, setUser, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

export { AuthContext, AuthProvider };

After clicking on SSO button it needs to validate the user and needs to redirect to Userhomecomponent.jsx page.

I have configured http://localhost:5173/home as redirectUri in azure . Also i have added the scopes openid,email and profile.I have enabled access token and id token also

I have tried to configure SSO using MSAL and azure in my react application. But while clicking sso button it redirecting to /home page and within seconds it is coming back to /signin. Also i can see that token is not generting in network tab.Please help to resolve this

2

Answers


  1. Chosen as BEST ANSWER
    Header.jsx
    
    import React, { useContext, useEffect, useState } from 'react';
    import { IoIosArrowDown } from "react-icons/io";
    import { NavLink } from 'react-router-dom';
    import bosch_banner from './assets/bosch.png';
    import bosch_logo_png from './assets/boschlogopng.png';
    import buildNow_logo from './assets/buildNOW_logo.png';
    import { AuthContext } from './utils/AuthContext';
    import { LuUserSquare2 } from "react-icons/lu";
    
    export const Header = () => {
      const { user } = useContext(AuthContext);
      const { logout } = useContext(AuthContext);
    
      const [dropdownVisible, setDropdownVisible] = useState(false);
      const [activeTab, setActiveTab] = useState('');
    
      const toggleDropdown = () => {
        setDropdownVisible(!dropdownVisible);
        if (!dropdownVisible) {
          setActiveTab('dropdown');
        } else {
          setActiveTab('');
        }
      };
    
      const closeDropdown = () => {
        setDropdownVisible(false);
        setActiveTab('');
      };
    
      const activeState = ({ isActive }) => {
        return {
          color: isActive ? "rgb(255, 255, 255)" : "",
          backgroundColor: isActive ? "rgb(75, 136, 189)" : "",
          transition: isActive ? "all .5s ease-out" : "",
        };
      };
    
      useEffect(() => {
        const handleClickOutside = (event) => {
          if (!event.target.closest('.dropdown')) {
            closeDropdown();
          }
        };
    
        document.addEventListener('click', handleClickOutside);
        return () => {
          document.removeEventListener('click', handleClickOutside);
        };
      }, []);
    
      return (
        <>
          <div className='sticky top-0 left-0 w-full z-50'>
            <div className=''>
              <img src={bosch_banner} alt="Bosch-image" width="100%" />
            </div>
            <div className='grid grid-cols-6 border border-b-2 bg-white'>
              <div className='grid grid-flow-col col-span-4 sm:gap-1 md:gap-4 lg:gap-6 m-1 sm:text-sm md:text-md lg:text-lg font-sans font-bold items-center text-center justify-start text-gray-600 rounded-lg'>
                <img className='h-12 m-1' src={buildNow_logo} alt="buildnow" />
                {user ? (
                  <>
                    <NavLink className='hover:bg-blue-100 p-2 rounded-md' to={`home`} style={activeState}>Home</NavLink>
                    <NavLink className='hover:bg-blue-100 p-2 rounded-md' to={`feedback`} style={activeState}>Feedback</NavLink>
                  </>
                ) : (
                  <>
                    <NavLink className='hover:bg-blue-100 p-2 rounded-md' to={`/`} style={activeState}>About</NavLink>
                    <NavLink className='hover:bg-blue-100 p-2 rounded-md' to={`pricing`} style={activeState}>Pricing</NavLink>
                    <NavLink className='hover:bg-blue-100 p-2 rounded-md' to={`releasenotes`} style={activeState}>Release notes</NavLink>
                    <NavLink className='hover:bg-blue-100 p-2 rounded-md' to={`contactus`} style={activeState}>Contact Us</NavLink>
                  </>
                )}
              </div>
              <div className='grid grid-flow-col col-span-2 mr-10 sm:text-sm md:text-sm lg:text-md font-sans font-medium items-center justify-end rounded-lg'>
                <div className="items-center justify-center rounded-lg">
                  <div className="flex flex-col rounded-md text-sky-800">
                    {user ? (
                      <>
                        <div className="relative dropdown w-full min-w-max">
                          <button
                            onClick={toggleDropdown}
                            className={`flex items-center gap-1 rounded-md py-3 px-3 w-full min-w-max hover:bg-blue-100 ${activeTab === 'dropdown' ? 'bg-[#4b88bd] text-white' : ''}`}
                          >
                            {user.userinfo.displayName}
                            <IoIosArrowDown size={20} />
                          </button>
                          {dropdownVisible && (
                            <div className="absolute mt-2 right-0 w-full bg-white border rounded shadow-lg min-w-max">
                              <NavLink
                                to="/userprofile"
                                className="block px-4 py-2 text-gray-800 hover:bg-gray-200 w-full"
                              >
                                User Profile
                              </NavLink>
                              <button
                                onClick={logout}
                                className="block w-full text-left px-4 py-2 text-gray-800 hover:bg-gray-200"
                              >
                                Logout
                              </button>
                            </div>
                          )}
                        </div>
                      </>
                    ) : (
                      <>
                        <NavLink
                          className="flex flex-col items-center gap-0 rounded-md py-3 px-3 pt-0 pb-0 pb-1s mt-1 hover:bg-blue-100"
                          to="signin"
                          style={activeState}
                        >
                          <LuUserSquare2 size={30} className="pt-0" />
                          <span className="text-xs mt-0">Login</span>
                        </NavLink>
                      </>
                    )}
                  </div>
                </div>
                <div className='grid grid-flow-col col-span-1 m-1 sm:text-sm md:text-lg lg:text-xl font-sans font-bold items-center justify-end rounded-lg'>
                  <img
                    loading="lazy"
                    src={bosch_logo_png}
                    className="max-w-[100px] max-h-[50px]"
                  />
                </div>
              </div>
            </div>
          </div>
          {/* Main content here */}
        </>
      );
    };
    
    
    Landingpage.jsx
    
    import React from 'react';
    import { Outlet } from 'react-router-dom';
    import { Header } from './Header';
    import { AuthProvider } from './utils/AuthContext';
    
    
    
    export const LandingPageComponent = () => {
      return (
        <>
         
        <AuthProvider>
        <Header />
        <Outlet />
        </AuthProvider>
        
        </>
        
      )
    }
    
    Loginpage.jsx
    
    import React, { useContext, useEffect } from 'react';
    import { useMsal } from '@azure/msal-react';
    import { loginRequest } from './Authconfig';
    import { useNavigate } from 'react-router-dom';
    import { AuthContext } from './utils/AuthContext';
    export const LoginPageComponent = () => {
      const { instance, accounts, inProgress } = useMsal(); // MSAL instance
      const navigate = useNavigate();
      const { login } = useContext(AuthContext);
      const handleLogin = () => {
        instance.loginRedirect(loginRequest);
      };
      useEffect(() => {
        const checkAuthentication = async () => {
          try {
            const response = await instance.handleRedirectPromise();
            if (response && response.account) {
              console.log('Authentication Response:', response);
              login(response.account);
              navigate('/home');
            } else if (accounts.length > 0) {
              console.log('User already logged in:', accounts[0]);
              login(accounts[0]);
              navigate('/home');
            }
          } catch (error) {
            console.error('Authentication Error:', error);
          }
        };
        if (inProgress === 'none') {
          checkAuthentication();
        }
      }, [instance, accounts, inProgress, login, navigate]);
      return (
        <div className="login-container">
          <div className="overlay">
            <div className="content">
              <div className="text-container">
                <div className="text-4xl font-black text-sky-600">
                  <span className="font-medium">Welcome to</span>
                  <br />
                  <span className="text-5xl text-sky-600 leading-[62px]">
                    buildNow Portal
                  </span>
                </div>
                <button
                  onClick={handleLogin}
                  className="login-button"
                >
                  <svg className="w-6 h-6 -ml-2" fill="none" stroke="currentColor">
                    <path d="M16 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
                    <circle cx="8.5" cy="7" r="4" />
                    <path d="M20 8v6M23 11h-6" />
                  </svg>
                  <span className="ml-3">LOGIN</span>
                </button>
              </div>
            </div>
          </div>
        </div>
      );
    };
    
    main.jsx
    
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { PublicClientApplication } from "@azure/msal-browser";
    import { MsalProvider } from "@azure/msal-react";
    import { RouterProvider, createBrowserRouter } from 'react-router-dom';
    import { msalConfig } from './Authconfig';
    import { PricingComponent } from './PricingComponent.jsx';
    import { AboutComponent } from './AboutComponent.jsx';
    import { AdminComponent } from './AdminComponent.jsx';
    import { BuildComponent } from './BuildComponent.jsx';
    import { ContactusComponent } from './ContactusComponent.jsx';
    import { FeedbackComponent } from './FeedbackComponent.jsx';
    import { LandingPageComponent } from './LandingPageComponent.jsx';
    import { LoginPageComponent } from './LoginPageComponent.jsx';
    import { ReleasenotesComponent } from './ReleasenotesComponent.jsx';
    import { UserHomeComponent } from './UserHomeComponent.jsx';
    import { UserProfileComponent } from './UserProfileComponent.jsx';
    import { ProtectedRoutes } from './utils/ProtectedRoutes.jsx';
    import './index.css';
    
    const msalInstance = new PublicClientApplication(msalConfig);
    
    // Define the router
    const router = createBrowserRouter([
      {
        path: '/',
        element: <LandingPageComponent />,
        errorElement: <div>404 not found</div>,
        children: [
          { path: '', element: <AboutComponent /> },
          { path: 'pricing', element: <PricingComponent /> },
          { path: 'releasenotes', element: <ReleasenotesComponent /> },
          { path: 'contactus', element: <ContactusComponent /> },
          { path: 'signin', element: <LoginPageComponent /> },
          {
            element: <ProtectedRoutes />,
            children: [
              { path: 'home', element: <UserHomeComponent /> },
              { path: 'build', element: <BuildComponent /> },
              { path: 'admin', element: <AdminComponent /> },
              { path: 'userprofile', element: <UserProfileComponent /> },
              { path: 'feedback', element: <FeedbackComponent /> },
            ],
          },
        ],
      },
    ]);
    
    // Initialize redirect handling
    const handleRedirect = async () => {
      try {
        await msalInstance.handleRedirectPromise();
      } catch (error) {
        console.error('Login error:', error);
      }
    };
    
    // Render the app after handling redirect
    handleRedirect().then(() => {
      const root = ReactDOM.createRoot(document.getElementById('root'));
      root.render(
        <MsalProvider instance={msalInstance}>
          <RouterProvider router={router} />
        </MsalProvider>
      );
    });
    
    userhomecomponent.jsx
    import React, { useContext } from 'react';
    import { AuthContext } from './utils/AuthContext';
    import { FaUserCircle } from 'react-icons/fa';
    
    export const UserProfileComponent = () => {
      const { user } = useContext(AuthContext);
    
      const data = {
        name: user.userinfo.displayName,
        ntid: user.userinfo.sAMAccountName,
        mailid: user.userinfo.mail,
        roles: user.memberRoles 
      };
    
      return (
        <>
    
          <div className="min-h-screen bg-gray-100 flex items-center justify-center min-h-[650px] ">
            <div className="bg-white shadow-lg rounded-lg p-6 w-full max-w-[700px] min-h-[500px]">
              <div className="flex flex-col items-center">
                ` `
                <div className="mt-4 text-2xl font-semibold text-blue-500 flex items-center">
                  <FaUserCircle className="mr-2 text-blue-500" />
                  <span>{data.name}</span>
                </div>
                <p className="mt-2 text-gray-900 text-md">Login ID: {data.ntid}</p>
                <p className="mt-2 text-gray-700 text-md">Mail ID: {data.mailid}</p>
              </div>
              <div className="mt-6">
                <h3 className="text-lg font-medium text-gray-900">Membership Roles</h3>
                <ul className="mt-2 space-y-2 text-md">
                  {data.roles.map((role) => (
                    <li key={role} className="text-gray-700">{role}</li>
                  ))}
                </ul>
              </div>
            </div>
          </div>
        </>
      );
    }``
    

  2. I fixed the issue by adding the below code in the LoginPageComponent.

    I was successfully redirect to the home page after logging in.

    export const LoginPageComponent = () => {
      const { instance, accounts, inProgress } = useMsal(); // MSAL instance
      const navigate = useNavigate();
      const { login } = useContext(AuthContext);
      const handleLogin = () => {
        instance.loginRedirect(loginRequest);
      };
      useEffect(() => {
        const checkAuthentication = async () => {
          try {
            const response = await instance.handleRedirectPromise();
            if (response && response.account) {
              console.log('Authentication Response:', response);
              login(response.account);
              navigate('/home');
            } else if (accounts.length > 0) {
              console.log('User already logged in:', accounts[0]);
              login(accounts[0]);
              navigate('/home');
            }
          } catch (error) {
            console.error('Authentication Error:', error);
          }
        };
        if (inProgress === 'none') {
          checkAuthentication();
        }
      }, [instance, accounts, inProgress, login, navigate]);
    

    Below is the complete code of Loginpagecomponent.

    Loginpagecomponent.jsx:

    import React, { useContext, useEffect } from 'react';
    import { useMsal } from '@azure/msal-react';
    import { loginRequest } from '../utils/Authconfig';
    import { useNavigate } from 'react-router-dom';
    import { AuthContext } from '../utils/AuthContext';
    export const LoginPageComponent = () => {
      const { instance, accounts, inProgress } = useMsal(); // MSAL instance
      const navigate = useNavigate();
      const { login } = useContext(AuthContext);
      const handleLogin = () => {
        instance.loginRedirect(loginRequest);
      };
      useEffect(() => {
        const checkAuthentication = async () => {
          try {
            const response = await instance.handleRedirectPromise();
            if (response && response.account) {
              console.log('Authentication Response:', response);
              login(response.account);
              navigate('/home');
            } else if (accounts.length > 0) {
              console.log('User already logged in:', accounts[0]);
              login(accounts[0]);
              navigate('/home');
            }
          } catch (error) {
            console.error('Authentication Error:', error);
          }
        };
        if (inProgress === 'none') {
          checkAuthentication();
        }
      }, [instance, accounts, inProgress, login, navigate]);
      return (
        <div className="login-container">
          <div className="overlay">
            <div className="content">
              <div className="text-container">
                <div className="text-4xl font-black text-sky-600">
                  <span className="font-medium">Welcome to</span>
                  <br />
                  <span className="text-5xl text-sky-600 leading-[62px]">
                    buildNow Portal
                  </span>
                </div>
                <button
                  onClick={handleLogin}
                  className="login-button"
                >
                  <svg className="w-6 h-6 -ml-2" fill="none" stroke="currentColor">
                    <path d="M16 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2" />
                    <circle cx="8.5" cy="7" r="4" />
                    <path d="M20 8v6M23 11h-6" />
                  </svg>
                  <span className="ml-3">LOGIN</span>
                </button>
              </div>
            </div>
          </div>
        </div>
      );
    };
    

    Authcontext.jsx:

    import React, { createContext, useState } from 'react';
    const AuthContext = createContext();
    const AuthProvider = ({ children }) => {
      const [user, setUser] = useState(() => {
        const storedUser = localStorage.getItem('user');
        return storedUser ? JSON.parse(storedUser) : null;
      });
      const login = (account) => {
        setUser(account);
        localStorage.setItem('user', JSON.stringify(account));
      };
      const logout = () => {
        setUser(null);
        localStorage.removeItem('user');
      };
      return (
        <AuthContext.Provider value={{ user, login, logout }}>
          {children}
        </AuthContext.Provider>
      );
    };
    export { AuthContext, AuthProvider };
    

    I used the below ProtectedRoutes ensured that only authenticated users can access certain routes.

    utils/ProtectedRoutes.jsx:

    import React, { useContext } from 'react';
    import { Outlet, Navigate } from 'react-router-dom';
    import { AuthContext } from './AuthContext';
    const ProtectedRoutes = () => {
      const { user } = useContext(AuthContext);
      return user ? <Outlet /> : <Navigate to="/signin" />;
    };
    export { ProtectedRoutes };
    

    Output:

    enter image description here

    After clicking the login button, I was successfully redirected to the home page and was able to see the access token.

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search