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>
);
登录页面组件.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 };
单击 SSO 按钮后,需要验证用户并需要重定向到 Userhomecomponent.jsx 页面。
我已将
http://localhost:5173/home
配置为 azure 中的redirectUri。我还添加了范围 openid、电子邮件和个人资料。我还启用了访问令牌和 id 令牌
我尝试在我的 React 应用程序中使用 MSAL 和 azure 配置 SSO。但是,当单击 sso 按钮时,它会重定向到 /home 页面,并在几秒钟内返回到 /signin。我还可以看到令牌没有在网络选项卡中生成。请帮助解决这个问题
我通过在 LoginPageComponent 中添加以下代码解决了该问题。
登录后我成功重定向到主页。
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]);
以下是Loginpage组件的完整代码。
登录页面组件.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 };
我使用了以下 ProtectedRoutes 确保只有经过身份验证的用户才能访问某些路由。
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 };
输出:
单击登录按钮后,我成功重定向到主页并能够看到访问令牌。