ASP.NET Core 3.1 同时使用 OpenIDConnect 和自定义 Cookie 身份验证

问题描述 投票:0回答:5

我有一个使用

Cookie Authentication
的现有应用程序,并且希望添加使用
Active Directory
对用户进行身份验证的功能。当前应用程序使用基于 Cookie 的
authentication
和自定义
authorisation
- 数据库中的角色。

我正在添加此处示例中的位:

将 Microsoft 登录添加到 ASP.NET Core Web 应用程序

当我运行应用程序时,出现错误:

System.InvalidOperationException:方案已存在:Cookies

正确的配置方式是什么

OpenIdConnect
Cookie Authentication
.

// 第 1 步 基本 Cookie 身份验证

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(options =>
            {
                options.LoginPath = "/Auth";
                options.AccessDeniedPath = "/Home/AccessDenied";
                options.Cookie.IsEssential = true;
                options.SlidingExpiration = true;
                options.ExpireTimeSpan = TimeSpan.FromSeconds(day/2.0);
                options.Cookie.HttpOnly = true; // not accessible via JavaScript
                options.Cookie.Name = "login_token";

                options.TicketDataFormat = new CustomJwtDataFormat(
                    SecurityAlgorithms.HmacSha256,
                    tokenValidationParameters);
            });

// 第 2 步 OpenID Connect 身份验证

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"), "OpenIdConnect", "Cookies", true);

我找不到任何同时使用

Cookie Authentication
OpenID Connect
的示例。这可能吗? 允许用户使用 Active Directory 身份验证或本地身份验证(详细信息存储在本地数据库中)有选择地登录。

更改“Cookie”名称后,消除错误消息, 但违反了当地授权,例如

当提供有效的用户名和密码时,我通常会 授权登录。

HttpContext.Response.Cookies.Append("login_token", token, GetCookieOptions());

当前已配置 OpenIDConnect

User.Identity.IsAuthenticated
仍然是假的。

asp.net-core cookies openid-connect
5个回答
3
投票

根据错误信息,它告诉你你有多个名为cookies的Scheme。

根据AddMicrosoftIdentityWebApp方法文档,可以发现第三个参数名称是cookieScheme。

要使用的基于 cookie 的方案名称。默认情况下它使用“Cookies”。

但是您已经在上面设置了这个名称,所以您应该使用其他名称。例如:“ADCookies”。

如下:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"), "OpenIdConnect", "ADCookies", true);

3
投票

混合方法是一个雷区,但下面允许使用 OIDC 通过 IdentityServer4 对用户进行身份验证,同时使用 Identity.Web 对 AzureAD 中的应用程序进行身份验证,以获取 Api 调用的令牌。

services.AddAuthentication(options =>
{
    options.DefaultScheme = "IS4Cookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie("IS4Cookies")
.AddOpenIdConnect("oidc", "OpenID Connect", options =>
{
    options.SignInScheme = "IS4Cookies";
    // Get IdentityServer configuration from appsettings.json.
    var config = Configuration.GetSection("IdentityServerOptions").Get<IdentityServerOptions>();

    options.Authority = config.Authority;
    options.RequireHttpsMetadata = false;
    options.ClientId = config.ClientId;
    options.ClientSecret = config.ClientSecret;
    options.ResponseType = "code";
    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;
    options.ClaimActions.MapJsonKey("role", "role");
    options.ClaimActions.MapJsonKey("role", System.Security.Claims.ClaimTypes.Role);
    options.ClaimActions.MapJsonKey("email", "email");
    options.ClaimActions.MapJsonKey("preferred_username", "preferred_username");
    options.Events = new OpenIdConnectEvents
    {
        OnRemoteFailure = context =>
        {
            context.Response.Redirect("/");
            context.HandleResponse();
            return Task.FromResult(0);
        }
    };
})
.AddMicrosoftIdentityWebApp(Configuration, "AzureOptions")
    .EnableTokenAcquisitionToCallDownstreamApi(new string[]{"sms.all" })
    .AddInMemoryTokenCaches();

2
投票

这就是我使用的并且它有效,您只需要指定configureCookieAuthenticationOptions并在其中设置名称,您应该就可以开始了,而且我必须对SameSite使用lax,否则它对我不起作用。

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(identityOptions =>
/* {identityOptions.ClientId ="";}, // if you want to specify the options manually instead of Configuration.GetSection() call*/
    Configuration.GetSection("AzureAd"),                    
    configureCookieAuthenticationOptions: authCookie => { // Setup SSO cookie                        
        authCookie.Cookie.Name ="Your.Cookie.Name.Here";// change name to hide .net identifiers in name
        authCookie.Cookie.HttpOnly = true;// make so client cannot alter cookie
        authCookie.Cookie.SecurePolicy = CookieSecurePolicy.Always;// require https
        authCookie.Cookie.SameSite = SameSiteMode.Lax;// from external resource
        // verify options are valid or throw exception 
        authCookie.Validate();
    }
);

您可能需要也可能不需要此处的所有 authCookie 值,但它应该让您朝着正确的方向开始!


1
投票

可以混合使用两种机制。 我使用 MicrosoftIdentity 身份验证来访问管理网页,并使用 Cookie 身份验证来访问我的 API 和 SignalR 集线器。

我在启动ConfigureServices时使用它

services
    .AddAuthentication(sharedOptions =>
    {
        sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie("CookiesApiScheme", options =>
    {
        options.SlidingExpiration = true;
        // There is no redirection to a login page for APIs and SignalR Hubs, I just made a call to /Api/Login/SignIn with credential
        options.AccessDeniedPath = new PathString("/Api/Login/AccessDenied"); // Action who just returns an Unauthorized
    })
    .AddMicrosoftIdentityWebApp(Configuration); // By default scheme is "CookieAuthenticationDefaults.AuthenticationScheme"

在API控制器中你可以使用这样的东西

    [Route("api/[controller]")]
    [ApiController]
    [Authorize(Roles = Roles.ADMIN)]
    [Authorize(AuthenticationSchemes = "CookiesApiScheme")]
    public class DefaultController : ControllerBase
    {
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
    }

基于这篇文章:ASP.NET Core 2.0 AzureAD 身份验证不起作用


0
投票

迈克的答案是我需要的,但是我收到了这个错误:

ArgumentNullException: IDW10106: The 'ClientId' option must be provided.

所以我需要手动将AzureAd配置部分绑定到identityOptions:

.AddMicrosoftIdentityWebApp(identityOptions => 
      /* {identityOptions.ClientId ="";}, // if you want to specify the options manually instead of Configuration.GetSection() call*/
      builder.Configuration.GetSection("AzureAd").Bind(identityOptions),
© www.soinside.com 2019 - 2024. All rights reserved.