我有一个使用
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
仍然是假的。
根据错误信息,它告诉你你有多个名为cookies的Scheme。
根据AddMicrosoftIdentityWebApp方法文档,可以发现第三个参数名称是cookieScheme。
要使用的基于 cookie 的方案名称。默认情况下它使用“Cookies”。
但是您已经在上面设置了这个名称,所以您应该使用其他名称。例如:“ADCookies”。
如下:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"), "OpenIdConnect", "ADCookies", true);
混合方法是一个雷区,但下面允许使用 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();
这就是我使用的并且它有效,您只需要指定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 值,但它应该让您朝着正确的方向开始!
可以混合使用两种机制。 我使用 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" };
}
}
迈克的答案是我需要的,但是我收到了这个错误:
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),