ASP.NET Core 3.1 同时使用 OpenIDConnect 和自定义 Cookie 身份验证
ASP.NET Core 3.1 Use both OpenIDConnect and Custom Cookie Authentication
我有一个使用 Cookie Authentication
的现有应用程序,我想添加使用 Active Directory
对用户进行身份验证的功能。当前应用程序使用基于 Cookie authentication
和自定义 authorisation
- 数据库中的角色。
我正在从位于此处的示例添加位:
Add sign-in with Microsoft to an ASP.NET Core web app
当我 运行 应用程序出现错误时:
System.InvalidOperationException: Scheme already exists: 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 连接验证
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
仍然是假的。
根据错误信息,它告诉你你有多个名为cookies的Scheme。
根据AddMicrosoftIdentityWebApp方法document,可以发现第三个参数名称是cookieScheme。
要使用的基于 cookie 的方案名称。默认情况下它使用“Cookies”。
但是你已经在上面设置了这个名字,所以你应该使用其他的。例如:“ADCookies”。
如下所示:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"), "OpenIdConnect", "ADCookies", true);
可以混合使用两种机制。
我使用 MicrosoftIdentity 身份验证来访问我的 APIs 和 SignalR 中心的管理网页和 cookie 身份验证。
我在启动 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" };
}
}
基于此post:
混合方法是一个雷区,但下面允许使用 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();
我有一个使用 Cookie Authentication
的现有应用程序,我想添加使用 Active Directory
对用户进行身份验证的功能。当前应用程序使用基于 Cookie authentication
和自定义 authorisation
- 数据库中的角色。
我正在从位于此处的示例添加位:
Add sign-in with Microsoft to an ASP.NET Core web app
当我 运行 应用程序出现错误时:
System.InvalidOperationException: Scheme already exists: 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 连接验证
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
仍然是假的。
根据错误信息,它告诉你你有多个名为cookies的Scheme。
根据AddMicrosoftIdentityWebApp方法document,可以发现第三个参数名称是cookieScheme。
要使用的基于 cookie 的方案名称。默认情况下它使用“Cookies”。
但是你已经在上面设置了这个名字,所以你应该使用其他的。例如:“ADCookies”。
如下所示:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"), "OpenIdConnect", "ADCookies", true);
可以混合使用两种机制。 我使用 MicrosoftIdentity 身份验证来访问我的 APIs 和 SignalR 中心的管理网页和 cookie 身份验证。
我在启动 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" };
}
}
基于此post:
混合方法是一个雷区,但下面允许使用 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();