设置Microsoft Entra ID应用分配要求后仍允许未授权用户登录的问题咨询
问题原因分析
useIsAuthenticated() 仅验证用户完成了Microsoft身份认证、持有有效ID令牌,不会校验该用户是否被分配到你的Entra ID应用。Entra ID的「需要用户分配」设置并非自动拦截未分配用户获取令牌,而是要求应用端自行完成用户权限校验——这是微软的设计逻辑,将权限管控的主动权交给应用开发者。
你遇到的「未分配用户仍能登录」情况,本质是前端只做了身份认证,没做权限校验;之前修改「允许用户登录」为否仍能登录,大概率是缓存的有效令牌未过期,只有删除应用才彻底切断了令牌签发渠道。
实现仅指定用户访问的方案
以下基于你使用的@azure/msal-browser@4.x和@azure/msal-react@3.x版本实现,无需维护独立用户表,所有权限配置可在Entra ID管理中心完成:
1. 完成Entra ID基础配置
- 确保应用的「需要用户分配」设为「是」,并将允许的10个用户(或对应用户组)添加到应用的「用户和组」列表中
- 将「允许用户登录」设为「是」,后续权限校验由前端完成
2. 前端权限校验(两种可选方案)
方案一:利用ID令牌声明校验(推荐,无需额外API调用)
通过Entra ID配置,让ID令牌携带用户所属组的信息,前端直接解析令牌判断权限:
- 在Entra ID「应用注册」→「令牌配置」中,添加ID令牌的可选声明:
- 选择「ID令牌」,添加
groups声明(若用用户组管理权限)
- 选择「ID令牌」,添加
- 封装自定义权限校验钩子:
import { useIsAuthenticated, useMsal } from "@azure/msal-react"; export const useIsAuthorized = () => { const isAuthenticated = useIsAuthenticated(); const { instance } = useMsal(); const activeAccount = instance.getActiveAccount(); if (!isAuthenticated || !activeAccount) return false; // 替换为你在Entra ID中创建的允许访问的用户组ID const ALLOWED_GROUP_ID = "xxxx-xxxx-xxxx-xxxx"; // 检查用户令牌中的groups声明是否包含允许的组ID return activeAccount.idTokenClaims?.groups?.includes(ALLOWED_GROUP_ID); }; - 在私有路由中替换原判断逻辑:
import { useIsAuthorized } from "./hooks/useIsAuthorized"; const PrivateRoute = ({ children }) => { const isAuthorized = useIsAuthorized(); return isAuthorized ? children : <Navigate to="/unauthorized" />; };
方案二:调用Microsoft Graph API校验
通过Graph API查询用户的应用分配状态,适合需要更复杂权限逻辑的场景:
- 在Entra ID「应用注册」→「API权限」中,添加委托权限
User.Read.All并完成管理员同意 - 实现权限校验逻辑:
import { useMsal, useMsalAuthentication } from "@azure/msal-react"; import { InteractionType } from "@azure/msal-browser"; const CheckAuthorization = () => { const { instance } = useMsal(); const { result } = useMsalAuthentication(InteractionType.Silent, { scopes: ["User.Read.All"] }); const verifyAppAssignment = async () => { if (!result?.accessToken) return false; const response = await fetch("https://graph.microsoft.com/v1.0/me/appRoleAssignments", { headers: { Authorization: `Bearer ${result.accessToken}` } }); const assignments = await response.json(); // 替换为你的应用客户端ID const APP_CLIENT_ID = "your-app-client-id"; // 检查用户是否有当前应用的分配记录 return assignments.value.some(item => item.resourceId === APP_CLIENT_ID); }; // 组件挂载时调用校验,根据结果跳转或渲染内容 useEffect(() => { verifyAppAssignment().then(isAuthorized => { if (!isAuthorized) { instance.logoutRedirect(); } }); }, [result]); return <></>; };
3. 补充注意事项
- 若使用用户组管理权限,确保组ID正确,且所有允许访问的用户已加入该组
- 令牌有效期内,前端校验逻辑会基于缓存的令牌执行,若在Entra ID中移除用户权限,需用户重新登录才会生效
- 建议在后端API调用时也添加一层校验:解析请求中的ID令牌,验证
groups或应用分配状态,避免前端校验被绕过
内容的提问来源于stack exchange,提问作者Ben in CA
相关产品推荐
相关产品推荐

