在我的网络应用程序中,我默认实现了表单例份验证。但对于内部用户我使用AD进行身份验证。 我有一个通过 LDAP 公开的本地 AD,我只是用它来验证内部用户的身份。
现在我们计划迁移到 Azure。因此,我们已迁移到 Azure AD。
Azure AD 的问题是我无法再使用页面内的表单来对用户进行身份验证。我必须将用户重定向到 azure 的身份验证页面 (OWIN OpenIDConnect)。有没有办法可以在我的本地应用程序中拥有用户名/密码,然后将它们发送到任何 azure api/服务来对其进行身份验证?
另一个问题是 - 现在我无法在 web.config 中使用表单例份验证作为默认值,或者它永远不会重定向到 azure 的身份验证页面。
有人可以帮忙吗?
注意:这是一个具有多个用户的单租户 WEB 应用程序
最佳答案
可以使用OWIN CookieAuthentication 和 ASP.NET 身份处理本地身份验证,并使用OpenIdConnect进行 AzureAD 身份验证来解决该问题。
"The other problem is - Now I cannot use forms authentication as default in my web.config or it never redirects to the azure's authentication page."
如果不设置<authentication mode="none" />
在 web.config
OWIN 无法从 IIS 接管您的应用程序的身份验证/授权过程。
在您的 Startup
中类,您将需要设置 Identity 和 OpenIdConnect 管道。
身份
如果您使用个人帐户进行身份验证生成新的 MVC 项目,您可以看到自动生成的代码 Startup
除了 Account
之外的类(下面的示例) Controller 有 Login
直接身份验证和 ExternalLogin
的操作(第三方)。您还可以通过查看 ExternalLogin
了解如何将外部登录提供程序(在您的情况下为 AzureAD)映射到本地用户帐户,即应用程序本地身份存储中的帐户。和ExternalLoginCallback
Account
中的操作 Controller 。
设置本地身份认证最低要求的教程。
Adding-minimal-OWIN-Identity-Authentication-to-an-Existing-ASPNET-MVC-Application
OpenIdConnect
设置 OpenIdConnect 时,如果设置 Notification
RedirectToIdentityProvider
(如下所示)将 domain_hint 参数设置为域部分下经过验证的域,该域在您的 Azure Active Directory(Azure 管理门户)中具有单点登录功能,用户如果已经在加入域的计算机上进行了身份验证,则应跳过提示页面。
<小时/> <小时/>domain_hint - This parameter is not part of the OpenID Connect standard. Azure AD introduced it to allow you to specify which IdP you want users to authenticate with. Say that your app trusts a federated Azure AD tenant. With the default request, users would first see the Azure AD authentication pages and be redirected to the federated ADFS only after they type their username in the text box. If you send the domain_hint parameter set to the federated domain, the Azure AD page is skipped, and the request goes straight to the ADFS associated with the tenant. If the user is accessing your app from an Intranet, and is thus already authenticated with ADFS, this can actually enable a seamless single sign-on experience.
Modern Authentication with Azure Active Directory for Web Applications p.118
还有其他参数,例如提示,可用于控制身份验证流程。
http://openid.net/specs/openid-connect-core-1_0.html
启动.Auth
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<SystemUserManager, SystemUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = Authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
// Used to skip login prompt for trusted tenant
Notifications = new OpenIdConnectAuthenticationNotifications()
{
RedirectToIdentityProvider = async (context) =>
{
context.ProtocolMessage.DomainHint = "someDomainName";
},
}
});
}
}
<小时/>
当未经身份验证的用户尝试访问 protected 代码时,他们将被定向到 Azure 登录页面。处理此问题的一种方法是创建自定义属性并将其引导至所需的登录页面。
public class ExampleAuthorize : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return httpContext.User.IsInRole(this.Roles);
}
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{
{"action", "Login"},{"controller", "Account"}
});
}
}
**更新评论**
Resource Owner Password Credentials Grant (即用户名和密码)流可以直接用作授权授予,但仅应在完全必要的情况下使用(请参阅已接受的答案)How to accept user credentials programmatically 。示例项目 Authenticating to Azure AD non-interactively using a username & password
如果只是自定义的 AzureAD 登录页面以实现一致的外观,则添加 AzureAD custom branding是一个选项。
未经测试 -
您可以尝试在 RedirectToIdentityProvider
上设置用户名和密码参数要求。根据OpenIDConnect Spec设置prompt="none"
应告诉服务器“不要显示任何身份验证或同意用户界面页面”(请参阅代码和注释)。
中间件设置 -
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = "https://login.windows.net/yourcompany.onmicrosoft.com",
PostLogoutRedirectUri = postLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
RedirectToIdentityProvider = async (context) =>
{
context.ProtocolMessage.Username = context.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary["username"];
context.ProtocolMessage.Password = context.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary["password"];
// Its my understanding that setting prompt="none" should tell the server not to display any authentication or consent user interface pages however this has not worked for me
// context.ProtocolMessage.Prompt = "none";
},
}
});
在您的登录操作中 -
public void Login(string username, string password, string redirectUri, string loginProvider)
{
AuthenticationProperties properties = new AuthenticationProperties();
properties.RedirectUri = RedirectUri;
properties.Dictionary.Add("username", username);
properties.Dictionary.Add("password", password);
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, loginProvider);
}
关于asp.net-mvc - 如何同时使用内部表单例份验证和 Azure AD 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38517518/