Authentication ASP.Net Core 2.0:使用在启用Windows身份验证的IIS站点下运行的OpenId连接身份验证

Authentication ASP.Net Core 2.0:使用在启用Windows身份验证的IIS站点下运行的OpenId连接身份验证,authentication,asp.net-core,openid-connect,Authentication,Asp.net Core,Openid Connect,我正在为我的ASP.Net Core 2.0 web应用程序实施OpenID连接身份验证。应用程序在启用Windows身份验证的IIS站点内运行。在用户登录到公司网络时访问应用程序的情况下,我不想让他们在Azure AD对话框中输入用户名,而是让应用程序从存储在HttpContext中的用户名派生出来,并将其作为登录提示传递到AD登录链接。下面是我试图实现所需行为的代码: services.AddAuthentication(options => { options

我正在为我的ASP.Net Core 2.0 web应用程序实施OpenID连接身份验证。应用程序在启用Windows身份验证的IIS站点内运行。在用户登录到公司网络时访问应用程序的情况下,我不想让他们在Azure AD对话框中输入用户名,而是让应用程序从存储在HttpContext中的用户名派生出来,并将其作为
登录提示
传递到AD登录链接。下面是我试图实现所需行为的代码:

services.AddAuthentication(options =>
    {
        options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddOpenIdConnect(options =>
        {
            options.Authority = "https://login.microsoftonline.com/<removed>";
            options.ClientId = "<removed>";
            options.ResponseType = OpenIdConnectResponseType.IdToken;
            options.CallbackPath = "/auth/signin-callback";
            options.Events = new OpenIdConnectEvents
            {
                OnRedirectToIdentityProvider = context =>
                {

                    if(context?.HttpContext?.User?.Identity?.Name != null)
                        context.ProtocolMessage.SetParameter("login_hint", context.HttpContext.User.Identity.Name.Replace("domain\\", "") + "@domain.com");

                    return Task.FromResult(0);
                }
            };
        }
    ).AddCookie();
services.AddAuthentication(选项=>
{
options.DefaultChallengeScheme=OpenIdConnectDefaults.AuthenticationScheme;
options.defaultsignnscheme=CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme=CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddOpenIdConnect(选项=>
{
选项。权限=”https://login.microsoftonline.com/";
options.ClientId=“”;
options.ResponseType=OpenIdConnectResponseType.IdToken;
options.CallbackPath=“/auth/sign callback”;
options.Events=新的OpenIdConnectEvents
{
OnRedirectToIdentityProvider=上下文=>
{
if(context?.HttpContext?.User?.Identity?.Name!=null)
context.ProtocolMessage.SetParameter(“login_hint”,context.HttpContext.User.Identity.Name.Replace(“domain\\”,“)+”@domain.com”);
返回Task.FromResult(0);
}
};
}
).AddCookie();
然而,这不起作用。一旦用户点击受
[Authorize]
属性保护的控制器,框架就会看到该用户已经通过IIS身份验证,并且不会重定向到Azure AD登录

如果我在属性中指定身份验证方案

[授权(AuthenticationSchemes=OpenIdConnectDefaults.AuthenticationScheme)]

应用程序重定向到AD登录,但
context.HttpContext.User.Identity.Name
null
,表示未进行IIS身份验证

我还尝试在Startup.cs的
ConfigureServices
方法中禁用自动身份验证

services.Configure(选项=>{options.AutomaticAuthentication=false;})

同样的效果——OpenID连接也起作用,但是
context.HttpContext.User.Identity.Name
null
。如果我在Kestrel上运行应用程序或在IIS站点上关闭Windows Auth,也会发生同样的情况

有没有一种方法可以同时实现这两种功能——在IIS身份验证可用时进行身份验证,但在使用IIS为login\u hint参数建立的标识时仍继续使用OpenId Connect


提前谢谢

如果我理解正确,您正在尝试首先执行Windows身份验证,请读取用户名并将其传递给Azure广告

我的问题是,如果您使用
[Authorize(AuthenticationSchemes=OpenIdConnectDefaults.AuthenticationScheme)]
强制执行OIDC方案,IIS将不再为您执行IWA(集成Windows身份验证)

以下是一些您可以尝试的东西:

  • 至少对于经典的ASP.NET应用程序,您可以转到IIS站点仪表板,并在
    Authentication
    下禁用“匿名身份验证”,同时启用“Windows身份验证”。这将强制用户始终使用Windows进行身份验证,而这可能不是您要查找的

  • 在重定向之前,您可以在控制器操作中手动质询Windows身份验证。下面是我将如何做到这一点(Core1.1现在可能略有不同)


  • 多亏了@mode777,我找到了一个解决方案——我将此代码添加到我的家庭控制器:

    var oidcAuthResult = HttpContext.AuthenticateAsync(OpenIdConnectDefaults.AuthenticationScheme).Result;
    if (oidcAuthResult.Principal == null)
       return Challenge(OpenIdConnectDefaults.AuthenticationScheme);
    
    因此,my Home controller(应用程序的默认路径)索引操作的完整代码如下:

    [Authorize]
    public IActionResult Index()
    {
            var oidcAuthResult = HttpContext.AuthenticateAsync(OpenIdConnectDefaults.AuthenticationScheme).Result;
            if (oidcAuthResult.Principal == null)
                return Challenge(OpenIdConnectDefaults.AuthenticationScheme);
    
            return View();
    }
    
    ConfigureServices方法保持不变,如问题中所述:

    services.AddAuthentication(options =>
        {
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
        .AddOpenIdConnect(options =>
            {
                options.Authority = "https://login.microsoftonline.com/<removed>";
                options.ClientId = "<removed>";
                options.ResponseType = OpenIdConnectResponseType.IdToken;
                options.CallbackPath = "/auth/signin-callback";
                options.Events = new OpenIdConnectEvents
                {
                    OnRedirectToIdentityProvider = context =>
                    {
    
                        if(context?.HttpContext?.User?.Identity?.Name != null)
                            context.ProtocolMessage.SetParameter("login_hint", context.HttpContext.User.Identity.Name.Replace("domain\\", "") + "@domain.com");
    
                        return Task.FromResult(0);
                    }
                };
            }
        ).AddCookie();
    
    services.AddAuthentication(选项=>
    {
    options.DefaultChallengeScheme=OpenIdConnectDefaults.AuthenticationScheme;
    options.defaultsignnscheme=CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultAuthenticateScheme=CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddOpenIdConnect(选项=>
    {
    选项。权限=”https://login.microsoftonline.com/";
    options.ClientId=“”;
    options.ResponseType=OpenIdConnectResponseType.IdToken;
    options.CallbackPath=“/auth/sign callback”;
    options.Events=新的OpenIdConnectEvents
    {
    OnRedirectToIdentityProvider=上下文=>
    {
    if(context?.HttpContext?.User?.Identity?.Name!=null)
    context.ProtocolMessage.SetParameter(“login_hint”,context.HttpContext.User.Identity.Name.Replace(“domain\\”,“)+”@domain.com”);
    返回Task.FromResult(0);
    }
    };
    }
    ).AddCookie();
    
    因此,现在身份验证流的工作方式如下:

    如果应用程序在启用Windows Auth的IIS下运行,则会满足[Authorize]属性,因此执行将进入索引操作体,此时将强制通过OIDC进行身份验证,ConfigureServices中的代码将使用Windows Auth提供的标识设置登录提示。如果应用程序在不支持Windows Auth(或已禁用)的服务器上运行,[Authorize]属性将立即启用OIDC,控制器中的
    If
    语句将阻止两次重定向到AD

    太好了

    再次感谢@mode777。

    谢谢@mode777!方法1不起作用
    services.AddAuthentication(options =>
        {
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
        .AddOpenIdConnect(options =>
            {
                options.Authority = "https://login.microsoftonline.com/<removed>";
                options.ClientId = "<removed>";
                options.ResponseType = OpenIdConnectResponseType.IdToken;
                options.CallbackPath = "/auth/signin-callback";
                options.Events = new OpenIdConnectEvents
                {
                    OnRedirectToIdentityProvider = context =>
                    {
    
                        if(context?.HttpContext?.User?.Identity?.Name != null)
                            context.ProtocolMessage.SetParameter("login_hint", context.HttpContext.User.Identity.Name.Replace("domain\\", "") + "@domain.com");
    
                        return Task.FromResult(0);
                    }
                };
            }
        ).AddCookie();