[英]How to use both internal Forms authenticationas well as Azure AD authentication
在我的Web应用程序中,我默认实现了表单身份验证。 但对于内部用户,我使用AD进行身份验证。 我有一个通过LDAP公开的内部部署AD,我只是用来验证内部用户。
现在我们计划搬到azure。 所以我们已经迁移到azure AD。
Azure AD的问题是我不能再使用页面内的表单来验证用户身份。 我必须将用户重定向到azure的身份验证页面(OWIN OpenIDConnect)。 有没有办法在我的本地应用程序中拥有用户名/密码,然后将它们发送到任何azure api /服务进行身份验证?
另一个问题是 - 现在我不能在我的web.config中使用表单身份验证作为默认值,或者它永远不会重定向到azure的身份验证页面。
有人可以帮忙吗?
注意:它是具有多个用户的单个租户WEB应用程序
这个问题可以用OWIN CookieAuthentication和ASP.NET的身份来处理与OpenIdConnect的本地认证AzureAD认证来解决。
“另一个问题是 - 现在我不能在我的web.config中使用表单身份验证作为默认值,或者它永远不会重定向到azure的身份验证页面。”
如果未在web.config
设置<authentication mode="none" />
,则OWIN无法从IIS接管应用程序的身份验证/授权过程。
在Startup
类中,您需要设置Identity和OpenIdConnect管道。
如果使用个人帐户生成新的MVC项目进行身份验证,除了具有Direct Authentication和ExternalLogin
(第三方) Login
操作的Account
控制器之外,您还可以看到Startup
类的自动生成代码(下面的示例)。 您还可以通过查看Account
控制器中的ExternalLogin
和ExternalLoginCallback
操作,了解如何将外部登录提供程序(在您的情况下为AzureAD)映射到本地用户帐户(即应用程序本地标识存储中的一个)。
设置本地身份验证所需的最低要求的教程。
添加-最小-OWIN -身份验证到的,现有-ASPNET-MVC-应用
设置OpenIdConnect时如果设置Notification
RedirectToIdentityProvider
(如下所示),并且domain_hint参数设置为域部分下的已验证域,该部分在Azure Active Directory(Azure管理门户)中具有单点登录,则用户应跳过如果已在已加入域的计算机上进行身份验证,则提示页
domain_hint - 此参数不是OpenID Connect标准的一部分。 Azure AD引入了它,允许您指定希望用户进行身份验证的IdP。 假设您的应用信任联合Azure AD租户。 使用默认请求,用户将首先看到Azure AD身份验证页面,并且只有在文本框中键入其用户名后才会重定向到联合ADFS。 如果将domain_hint参数集发送到联合域,则会跳过Azure AD页面,并且请求将直接发送到与租户关联的ADFS。 如果用户从Intranet访问您的应用程序,并且因此已经使用ADFS进行了身份验证,则实际上可以实现无缝的单点登录体验。
使用Azure Active Directory for Web Applications进行现代身份验证第118页
还有其他参数,例如prompt ,可用于控制身份验证流程。
http://openid.net/specs/openid-connect-core-1_0.html
Startup.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";
},
}
});
}
}
当未经身份验证的用户尝试访问受保护的代码时,他们将被定向到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"}
});
}
}
更新评论
资源所有者密码凭据授权 (即用户名和密码)流可以直接用作授权授权,但只应在完全必要时使用(请参阅已接受的答案) 如何以编程方式接受用户凭据 。 示例项目使用用户名和密码以非交互方式对Azure AD进行身份验证
如果它只是一个自定义的AzureAD登录页面,以实现一致的外观,那么添加AzureAD自定义品牌是一个选项。
未经测试 -
您可以尝试在RedirectToIdentityProvider
请求上设置用户名和密码参数。 根据OpenIDConnect规范设置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);
}
经过大量研究后我得出结论:
1) 在Web应用程序中,无法将用户名/密码直接传递给azure AD进行身份验证,就像使用内部部署AD(LDAP)一样。 这不是限制,但可以被视为安全实现。
2)最多可以使用RedirectToIdentityProvider和domain_hint跳过azure门户页面。
3) ADAL ,其中可以将用户凭证传递给azure AD进行身份验证仅适用于本机客户端希望允许用户访问其他资源的本机客户端(Web api,服务等)
4)要在基于表单的身份验证之上使用azure AD,您必须在web.config中将身份验证模式设置为none,并创建新的授权过滤器以将未经授权的用户重定向到基于表单的登录页面 。 或者,您可以使用以下URL中的答案: 使用Azure AD时将用户重定向到自定义登录页面
除了来自cID的解决方案,请查看Azure B2C以存储您的用户: https ://azure.microsoft.com/en-us/documentation/articles/active-directory-b2c-overview/
使用B2C,您拥有一个完整的用户OWIN / OpenID Connect数据库,但您必须将现有的表单数据库迁移到那里。
该解决方案的第二部分是预览MSAL库,它结合了AD和B2C的登录
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.