asp.net-mvc - 如何同时使用内部表单例份验证和 Azure AD 身份验证

标签 asp.net-mvc azure authentication owin azure-active-directory

在我的网络应用程序中,我默认实现了表单例份验证。但对于内部用户我使用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

<小时/>

位于租户下的“域”选项卡
Domain tab located under your tenant

<小时/>

还有其他参数,例如提示,可用于控制身份验证流程。

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/

相关文章:

asp.net-mvc - ASP.NET MVC : What are Action Method?操作结果?它们有什么关系?

Azure 应用程序网关未采用超时设置

python - 没有名为 'azure.eventhub' 的模块; 'azure' 不是一个包

php - 使用 PHP 和 MySQL 登录到管理员 - 成员(member)网站 - 登录不工作

c# - 如何在 .NET Core MVC 项目中转换 appsettings.json?

javascript - Asp.net razor javascript 避免对字符串进行数学运算

c# - 在 Windows Azure 上托管的项目上调用查询时,TFS Api 崩溃

Azure blob 错误 :The specified blob does not exist, 但 Blob 存在

linux - squid basic_ldap_auth 从用户名中剥离 nt 域

azure - 以非交互方式向 Azure REST API 进行 PowerBi 嵌入报告的身份验证时出现 403 Forbidden