我正在开发一个单页应用程序(SPA),它根据Azure AD中用户登录的角色设置,授予对应用程序中特定路径的访问权限。根据这个https://github.com/Azure-Samples/ms-identity-javascript-react-tutorial/tree/main/5-AccessControl/1-call-api-roles
这是我的'authConfig.js‘文件-你可以看到redirectUri
const clientId = window.REACT_APP_CLIENTID
export const msalConfig = {
auth: {
clientId: clientId,
authority: window.REACT_APP_AUTHORITY,
redirectUri: 'http://localhost:3000/todolist/', // You must register this URI on Azure Portal/App Registration. Defaults to window.location.origin
postLogoutRedirectUri: "/", // Indicates the page to navigate after logout.
navigateToLoginRequestUrl: false, // If "true", will navigate back to the original request location before processing the auth code response.
},
cache: {
cacheLocation: "sessionStorage", // Configures cache location. "sessionStorage" is more secure, but "localStorage" gives you SSO between tabs.
storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
},
system: {
loggerOptions: {
loggerCallback: (level, message, containsPii) => {
if (containsPii) {
return;
}
switch (level) {
case LogLevel.Error:
console.error(message);
return;
case LogLevel.Info:
console.info(message);
return;
case LogLevel.Verbose:
console.debug(message);
return;
case LogLevel.Warning:
console.warn(message);
return;
}
}
}
}
};
/**
* Add here the endpoints and scopes when obtaining an access token for protected web APIs. For more information, see:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/resources-and-scopes.md
*/
export const protectedResources = {
apiTodoList: {
todoListEndpoint: window.REACT_APP_APIENDPOINT+"/api/v2/support/list",
scopes: [window.REACT_APP_APIENDPOINT+"/access_as_user"],
},
}
/**
* Scopes you add here will be prompted for user consent during sign-in.
* By default, MSAL.js will add OIDC scopes (openid, profile, email) to any login request.
* For more information about OIDC scopes, visit:
* https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes
*/
export const loginRequest = {
scopes: [...protectedResources.apiTodoList.scopes]
};
export const appRoles = {
TaskUser: "TaskUser",
TaskAdmin: "TaskAdmin",
TrialAdmin: "Trial.Admin",
GlobalAdmin: "Global.Admin"
}这是App.jsx文件(我认为这里需要做一些修改)。当路径“todolist”被访问时,您可以看到呈现组件{TodoList}的“todolist”。
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { MsalProvider } from "@azure/msal-react";
import { RouteGuard } from './components/RouteGuard';
import { PageLayout } from "./components/PageLayout";
import { TodoList } from "./pages/TodoList";
import { appRoles } from "./authConfig";
import "./styles/App.css";
const Pages = () => {
return (
<Switch>
<RouteGuard
exact
path='/todolist/'
roles={[appRoles.TaskUser, appRoles.TaskAdmin, appRoles.TrialAdmin, appRoles.GlobalAdmin]}
Component={TodoList}
/>
</Switch>
)
}
/**
* msal-react is built on the React context API and all parts of your app that require authentication must be
* wrapped in the MsalProvider component. You will first need to initialize an instance of PublicClientApplication
* then pass this to MsalProvider as a prop. All components underneath MsalProvider will have access to the
* PublicClientApplication instance via context as well as all hooks and components provided by msal-react. For more, visit:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-react/docs/getting-started.md
*/
const App = ({ instance }) => {
return (
<Router>
<MsalProvider instance={instance}>
<PageLayout>
<Pages instance={instance} />
</PageLayout>
</MsalProvider>
</Router>
);
}
export default App;因此,就我的理解而言,路径“todolist”是使用列出的角色访问的,并呈现组件。
登录后,顶部的导航栏将在身份验证()之后使用登录请求呈现。它呈现了按钮,带有一个'href's to the path '/todolist‘的单击函数。
import { AuthenticatedTemplate, UnauthenticatedTemplate, useMsal } from "@azure/msal-react";
import { Nav, Navbar, Button, Dropdown, DropdownButton} from "react-bootstrap";
import React, { useState, useEffect } from "react";
import { loginRequest } from "../authConfig";
import { InteractionStatus, InteractionType } from "@azure/msal-browser";
import "../styles/App.css";
import logo from "../public/images/logo.jpg";
export const NavigationBar = (props) => {
const { instance } = useMsal();
const { inProgress } = useMsal();
const [isAuthorized, setIsAuthorized] = useState(false);
//The below function is needed incase you want to login using Popup and not redirect
const handleLogin = () => {
instance.loginPopup(loginRequest)
.catch((error) => console.log(error))
}
/**
* Most applications will need to conditionally render certain components based on whether a user is signed in or not.
* msal-react provides 2 easy ways to do this. AuthenticatedTemplate and UnauthenticatedTemplate components will
* only render their children if a user is authenticated or unauthenticated, respectively.
*/
return (
<>
<Navbar className="color-custom" variant="dark">
<a className="navbar-brand" href="/"><img src={logo} className="navbarLogo" alt="TODDOLIST1"/></a>
<AuthenticatedTemplate>
<Nav.Link as={Button} id="signupbutton" variant="dark" className="signupNav" href="/todolist"><strong>List</strong></Nav.Link>
<Button variant="warning" className="ml-auto" drop="left" title="Sign Out" onClick={() => instance.logoutRedirect({ postLogoutRedirectUri: "/" })}><strong>Sign Out</strong></Button>
</AuthenticatedTemplate>
<UnauthenticatedTemplate>
<Button variant="dark" className="ml-auto" drop="left" title="Sign In" onClick={() => instance.loginRedirect(loginRequest)}>Sign In</Button>
</UnauthenticatedTemplate>
</Navbar>
</>
);
};下面是基于角色/授权呈现的RouteGuard.jsx组件。
import React, { useState, useEffect } from "react";
import { Route } from "react-router-dom";
import { useMsal } from "@azure/msal-react";
export const RouteGuard = ({ Component, ...props }) => {
const { instance } = useMsal();
const [isAuthorized, setIsAuthorized] = useState(false);
const onLoad = async () => {
const currentAccount = instance.getActiveAccount();
if (currentAccount && currentAccount.idTokenClaims['roles']) {
let intersection = props.roles
.filter(role => currentAccount.idTokenClaims['roles'].includes(role));
if (intersection.length > 0) {
setIsAuthorized(true);
}
}
}
useEffect(() => {
onLoad();
}, [instance]);
return (
<>
{
isAuthorized
?
<Route {...props} render={routeProps => <Component {...routeProps} />} />
:
<div className="data-area-div">
<h3>You are unauthorized to view this content.</h3>
</div>
}
</>
);
};我希望应用程序直接转到'/todolist‘并呈现其中的组件。我的重定向不起作用。当我使用所需的角色登录时,它总是按照RouteGuard文件呈现“您未经授权查看此内容”。URI是/signuplist/但仍然没有呈现子道具。只有当我单击按钮'Todolist‘(按照NavigationBar.jsx)时,它才会正确地呈现子道具。重定向不像预期的那样工作。我想让它直接转到/todolist并呈现页面,子组件有什么建议吗?
发布于 2022-12-02 01:42:59
您能尝试从onload方法签名中删除异步吗?
发布于 2022-12-02 22:39:39
您是否在Azure门户上注册了“http://localhost:3000/todolist/”作为一个有效的重定向uri。您可以根据角色拥有多个重定向uri,但所有uri必须在应用程序下的Azure门户上注册。
重定向URI是Microsoft平台重定向用户客户端并在authentication.Is
之后发送安全令牌的位置
发布于 2022-12-02 23:30:15
如果我最后的评论是为你准备的,让我把它写成一个正式的答案,这样它就可以被记录下来。
基本上,
定义: const {实例、帐户、inProgress }= useMsal();
然后尝试在inProgress !==‘登录’时重定向。
https://stackoverflow.com/questions/74649973
复制相似问题