skip to Main Content

I have created a web application in azure and tried to configure sso using MSAL react library. But while clicking on the sso button it is redirecting and within seconds it is coming back to the login page.

I have created the following files:

Authconfig.js

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

LoginButon.js

import React from 'react';import { useMsal } from "@azure/msal-react";

const LoginButton = () => {const { instance } = useMsal();

const handleLogin = () => {instance.loginPopup().catch(e => {console.error(e);});};

return (<button onClick={handleLogin} style={styles.button}>Sign in with SSO</button>);};

const styles = {button: {padding: "10px 20px",backgroundColor: "#0078d4",color: "white",border: "none",borderRadius: "5px",cursor: "pointer",},};

export default LoginButton;

App.js

import React from 'react';import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';import LoginButton from './components/LoginButton';import Home from './components/Home';

function App() {return (<Router><Routes><Route path="/" element={<LoginButton />} /><Route path="/home" element={<Home />} /></Routes></Router>);}

export default App;

index.js

// src/index.jsimport React from 'react';import ReactDOM from 'react-dom';import App from './App';import { PublicClientApplication } from "@azure/msal-browser";import { MsalProvider } from "@azure/msal-react";import { msalConfig } from './authConfig';

// src/index.jsconst msalInstance = new PublicClientApplication(msalConfig);

msalInstance.handleRedirectPromise().then(response => {if (response) {console.log('User successfully logged in');}}).catch(err => {console.error(err);});

ReactDOM.render(<MsalProvider instance={msalInstance}><App /></MsalProvider>,document.getElementById('root'));

Home.js

// src/pages/Home.jsimport React from 'react';

const Home = () => {return (<div>

export default Home;

After clicking on SSO button it needs to validate the user and needs to redirect to Home.js pageAzure:

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

2

Answers


  1. Chosen as BEST ANSWER
    Can you help me to modify the below code
    
    it is a normal login code i wanted to implement sso in this.
    
    main.jsx
    
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { PricingComponent } from './PricingComponent.jsx';
    
    import { RouterProvider, createBrowserRouter } from 'react-router-dom';
    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 './index.css';
    import { ProtectedRoutes } from './utils/ProtectedRoutes.jsx';
    
    
    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>
       
        <RouterProvider router={router} />
        
      </React.StrictMode>,
    )
    
    
    Logincomponent.jsx
    
    import React, { useContext, useState } from "react";
    import { FaKey, FaUser } from "react-icons/fa";
    import { useNavigate } from 'react-router-dom';
    import loginimage from './assets/loginimage.svg';
    import { AuthContext } from "./utils/AuthContext";
    
    export const LoginPageComponent = () =>{
      
      const [username, setUsername] = useState('');
      const [password, setPassword] = useState('');
      const [error, setError] = useState(null);
      const navigate = useNavigate();
      //const {setUser} = useContext(AuthContext);
      const {login} = useContext(AuthContext)
      const [isModalOpen, setIsModalOpen] = useState(false);
      const baseUrl = import.meta.env.VITE_REACT_APP_BACKEND_BASE_URL;
    
    
      const handleSubmit = async (e) => {
          e.preventDefault();
          setError(null);
      
    
      try {
        // Replace with your API endpoint
        const response = await fetch(`${baseUrl}/buildNowJenkins/ldap/`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ username , password})
        });
    
        const data = await response.json();
        console.log(data);
        if (response.status === 200) {
            login(data);
            navigate('/home');
        } else {
            setError(data);
            setIsModalOpen(true);
        }
    } catch (err) {
        setError('An error occurred. Please try again.');
        setIsModalOpen(true);
    } 
    };
    
    const closeModal = () => {
      setIsModalOpen(false);
      setError(null);
      setUsername('');
      setPassword('');
    };
    
      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>
                <form onSubmit={handleSubmit} >
                <div className="mt-3">
                <div className="flex gap-3 mt-1 mb-3 whitespace-nowrap max-md:flex-wrap max-md:px-5 max-md:mt-10">
                <div className="mt-6 mr-1">
                <FaUser />
                </div>
                <input
                  className="w-96 px-8 py-3 mt-1 mb-3 rounded-lg font-medium bg-gray-100 border border-gray-200 placeholder-gray-500 text-sm focus:outline-none focus:border-gray-400 focus:bg-white"
                  type="text" value={username} onChange={(e) => setUsername(e.target.value)}  placeholder="Ntid" />
                  </div>
                                    
                  <div className="flex gap-2   mt-3 whitespace-nowrap max-md:flex-wrap max-md:px-5 max-md:mt-10">
                  <div className="mt-10 mr-1">
                  <FaKey />
                  </div>
                <input
                  className="w-96 px-8 py-2 rounded-lg font-medium bg-gray-100 border border-gray-200 placeholder-gray-500 text-sm focus:outline-none focus:border-gray-400 focus:bg-white mt-5"
                  type="password" value={password} onChange={(e) => setPassword(e.target.value)}  placeholder="Password" />
                  </div>
                <button type="submit"
                  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>
                {error && (
              <div className="fixed z-10 inset-0 overflow-y-auto">
              <div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
                <div className="fixed inset-0 transition-opacity" aria-hidden="true">
                  <div className="absolute inset-0 bg-gray-500 opacity-75"></div>
                </div>
    
                <span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
    
                <div className="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
                  <div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
                    <div className="sm:flex sm:items-start">
                     
                      <div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
                        <h3 className="text-lg leading-6 font-medium text-gray-900" id="modal-title">
                        
                          <p>Invalid username or password</p>
                          <p>Login failed. Please try again.</p>
                        </h3>
                        
                      </div>
                    </div>
                  </div>
                  <div className="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
                    <button onClick={closeModal} type="button" className="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
                      Close
                    </button>
                  </div>
                </div>
              </div>
            </div>
          )}
                </div>
                </form>
                  {/* <div className="flex gap-1 justify-center mt-5 mb-5 text-base whitespace-nowrap max-md:flex-wrap">
                  <div className="shrink-0  my-auto max-w-96 h-px bg-white border border-white border-solid w-[100px]" />
                  <div className="">OR</div>
                  <div className="shrink-0  my-auto max-w-96 h-px bg-white border border-white border-solid w-[100px]" />
                  </div> */}
                {/* <button
                  className="w-96 px-8 py-3 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">
                  <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 With SSO
                  </span>
                </button> */}
              </div>
            </div>
          </div>
          </div>
      );
    }
    
    
    protectedroutes.jsx
    
    import React, { useContext } from 'react';
    import { Navigate, Outlet } from 'react-router-dom';
    import { AuthContext } from './AuthContext';
    
    export const ProtectedRoutes = () => {
        const {user} = useContext(AuthContext);
    
        return user ? <Outlet/> : <Navigate to ="/signin"/>
    }
    
    Authcontext.jsx
    
    import React, { useState } from 'react';
    
    const AuthContext = React.createContext();
    
    const AuthProvider = ({ children }) => {
        const [user, setUser] = useState(() => {
            const storedUser = localStorage.getItem('user');
            return storedUser ? JSON.parse(storedUser) : null;
        });
    
        const login = (userData) => {
            setUser(userData);
            localStorage.setItem('user', JSON.stringify(userData));
        };
    
        const logout = () => {
            setUser(null);
            localStorage.removeItem('user');
        };
    
        return (
            <AuthContext.Provider value={{ user,setUser,login,logout }}>
                {children}
            </AuthContext.Provider>
        );
    };
    
    export { AuthContext, AuthProvider };
    
    
    
    Authconfig will be same as before
    

  2. The Error your facing is because of misconfiguration of redirect URL in Azure App Registration.

    The Redirect URL defined in authConfig and Azure App Registration URL Should be same as shown below.

    Azure App Registration -> Authentication ->Single-Page application -> Add URI -> Save.

    enter image description here

    authConfig.js:

    export const msalConfig = {
        auth: {
          clientId: "<client_ID>", 
          authority: "https://login.microsoftonline.com/<tenant_ID>", 
          redirectUri: "http://localhost:3000/home",
        },
        cache: {
          cacheLocation: "sessionStorage", 
          storeAuthStateInCookie: false, 
        },
      };
      export const loginRequest = {
        scopes: ["openid", "profile", "email"],
      };  
    

    Below Is complete code for to configure sso using MSAL react library.

    LoginButton:

    import React from 'react';
    import { useMsal } from "@azure/msal-react";
    import { loginRequest } from '../authConfig';
    const LoginButton = () => {
      const { instance } = useMsal();
      const handleLogin = () => {
        instance.loginRedirect(loginRequest);
      };
      return (
        <button onClick={handleLogin} style={styles.button}>
          Sign in with SSO
        </button>
      );
    };
    const styles = {
      button: {
        padding: "10px 20px",
        backgroundColor: "#0078d4",
        color: "white",
        border: "none",
        borderRadius: "5px",
        cursor: "pointer",
      },
    };
    export default LoginButton;
    

    index.js:

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { PublicClientApplication } from "@azure/msal-browser";
    import { MsalProvider } from "@azure/msal-react";
    import App from './App';
    import { msalConfig } from './authConfig';
    import { BrowserRouter } from 'react-router-dom';
    
    const msalInstance = new PublicClientApplication(msalConfig);
    const handleRedirect = async () => {
      try {
        await msalInstance.handleRedirectPromise();
      } catch (error) {
        console.error('Login error:', error);
      }
    };
    handleRedirect().then(() => {
      const root = ReactDOM.createRoot(document.getElementById('root'));
      root.render(
        <BrowserRouter>
          <MsalProvider instance={msalInstance}>
            <App />
          </MsalProvider>
        </BrowserRouter>
      );
    });
    

    App.js:

    import React, { useEffect } from 'react';
    import { useMsal } from "@azure/msal-react";
    import { Routes, Route, useNavigate } from 'react-router-dom';
    import LoginButton from './components/LoginButton';
    import Home from './components/Home';
    function App() {
      const { instance, inProgress } = useMsal();
      const navigate = useNavigate();
    
      useEffect(() => {
        const handleRedirect = async () => {
          if (inProgress === "none") {
            try {
              const response = await instance.handleRedirectPromise();
              if (response) {
                console.log('User successfully logged in:', response);
                navigate('/home');
              }
            } catch (err) {
              console.error('Login error:', err);
            }
          }
        };
        handleRedirect();
      }, [instance, navigate, inProgress]);
      return (
        <Routes>
          <Route path="/" element={<LoginButton />} />
          <Route path="/home" element={<Home />} />
        </Routes>
      );
    }
    export default App;
    

    Home.js:

    import React from 'react';
    const Home = () => {
      return (
        <div>
          <h1>Welcome to the Home Page!</h1>
          <p>You are successfully logged in.</p>
         
        </div>
      );
    };
    export default Home;
    

    After Successfully running, I got below page.

    Output:

    enter image description here

    enter image description here

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