环境:
两个 Azure AD:公司、客户
公司发布了一个名为Portal的 ASP.NET5 Web 应用程序,该应用程序设置为 Multi-Tenancy 。
客户有 2 个用户:user(只是用户)和 admin(目录中的全局管理员)。
门户最初设置为请求 1 个应用程序权限:读取目录数据
-
这是我经历的流程,我相信 Azure AD 在多个步骤中行为不当。如果我遗漏了什么,请指出。
- 我打开网络应用,首先尝试以管理员身份登录
- 我必须同意读取目录数据权限,所以我这样做了
- 应用程序出现(我还没有分配角色,这很好)——到目前为止一切正常。
- 我在新的隐身 session 中重新打开网络应用,并尝试以用户身份登录
- 现在,我得到 [
AADSTS90093:此操作只能由管理员执行。注销并以管理员身份登录或联系您组织的一位管理员。
] -- 管理员已经同意了,那为什么我会收到此消息? - 我转到公司 AD 并更改应用程序权限以包含读取和写入目录数据
- 我前往客户 AD 检查应用门户,仪表板已显示列出的新权限。无需任何人同意!即使在下次登录时,管理员也看不到任何更改。 这怎么不是一个安全漏洞?
我对https://msdn.microsoft.com/en-us/library/azure/dn132599.aspx的理解是应用程序权限并未被弃用。
更新
我在 WebApp 中的配置:
app.UseOpenIdConnectAuthentication(options =>
{
options.ClientId = Configuration.Get("ActiveDirectory:ClientId");
options.Authority = String.Format(Configuration.Get("ActiveDirectory:AadInstance"), "common/"); //"AadInstance": "https://login.windows.net/{0}"
options.PostLogoutRedirectUri = Configuration.Get("ActiveDirectory:PostLogoutRedirectUri"); //"PostLogoutRedirectUri": "https://localhost:44300/"
options.TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
{
// The following commented-out line should work according to
// http://stackoverflow.com/questions/29317910/why-does-the-role-claim-have-incorrect-type
// But, it does not work in ASP.NET5 (currently), so see the "Hack." down below
// RoleClaimType = "roles",
ValidIssuers = new[] { "https://sts.windows.net/a1028d9b-bd77-4544-8127-d3d42b9baebb/", "https://sts.windows.net/47b68455-a2e6-4114-90d6-df89d8468abc/" }
};
options.Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = (context) =>
{
// This ensures that the address used for sign in and sign out is picked up dynamically from the request,
// which is neccessary if we want to deploy the app to different URLs (eg. localhost/immerciti-dev, immerciti.azurewebsites.net/www.immerciti.com)
string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
context.ProtocolMessage.RedirectUri = appBaseUrl;
context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;
return Task.FromResult(0);
},
AuthorizationCodeReceived = async context =>
{
// Get Access Token for User's Directory
try
{
var identity = (ClaimsIdentity)context.AuthenticationTicket.Principal.Identity;
// Hack. TODO: keep an eye on developments around here
foreach (var claim in identity.FindAll("roles"))
{
// Readd each role with the proper claim type
identity.AddClaim(new Claim(identity.RoleClaimType, claim.Value, claim.ValueType, claim.Issuer, claim.OriginalIssuer));
}
}
catch (AdalException)
{
context.HandleResponse();
context.Response.Redirect("/Error/ShowError?errorMessage=Were having trouble signing you in&signIn=true");
}
}
};
};
最佳答案
感谢您提供的信息。我首先要回答#7,因为它看起来非常令人担忧。乍一看它确实像是一个安全漏洞,但事实并非如此。这是 Azure 管理门户中的一个错误,我们正在努力修复。在“客户”租户 View 中,UX 显示应用程序(在公司租户中定义)请求的权限。它应该显示“客户”租户中实际授予的权限。在这种情况下,如果您的应用实际上尝试调用写入图形 API,它将收到访问被拒绝错误。无论如何 - 不是一个安全漏洞 - 但可以肯定理解为什么它看起来像这样 - 对此感到非常抱歉。我们会尽快修复此问题。
关于您关于同意行为的一些其他问题...顺便说一句,这是我们希望在文档中改进的内容。无论如何,我将尝试从设计行为方面广泛回答这个问题,因为看起来您已经多次更改了应用程序配置。
如果您选择任何应用权限(不是委派权限),同意用户体验将默认为“代表组织同意”体验。在此模式下,无论管理员之前是否同意,同意页面始终显示。如果您使用 QS 参数提示 = admin_consent 向授权端点发出请求,您也可以强制执行此行为。因此,假设您走了这条路,并且您拥有的唯一权限是仅应用程序的“读取目录”并且管理员同意。现在,用户来了,用户没有任何授权来允许他们登录并获取应用程序的 id_token(仅读取目录应用程序目前对此不适用),因此同意对话框尝试代表管理员显示组织同意,但这是非管理员,因此您会收到错误。 现在,如果您为应用程序添加委派的“登录并阅读我的个人资料”权限,并获得管理员的重新同意,您将看到现在不会提示用户同意。 我要做的是返回我们的团队,查看任何目录权限(仅限应用程序或委派)是否应允许任何用户获取登录 token 。有人可能会说情况应该如此。
HTH,
关于security - 为什么 Azure AD 在 Multi-Tenancy 场景中无法登录非管理员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29791557/