Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f5a69de0a0 | |||
| 40a5f94941 | |||
| fc4db32f20 | |||
| 9cb4b8264d | |||
| ddd823afab | |||
| a9aa0a675a | |||
| 6418d27f5a | |||
| a763e5e40e | |||
| 9b15e296df |
@@ -3,8 +3,6 @@ using LiteCharms.Features.Api;
|
|||||||
using LiteCharms.Features.Api.Configuration;
|
using LiteCharms.Features.Api.Configuration;
|
||||||
using LiteCharms.Features.Api.Sdk;
|
using LiteCharms.Features.Api.Sdk;
|
||||||
using LiteCharms.Features.Postgres;
|
using LiteCharms.Features.Postgres;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace LiteCharms.Features.Extensions;
|
namespace LiteCharms.Features.Extensions;
|
||||||
|
|
||||||
@@ -56,9 +54,14 @@ public static class Api
|
|||||||
|
|
||||||
public static IServiceCollection AddLiteCharmsWebSecurity(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddLiteCharmsWebSecurity(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
|
var certificate = X509CertificateLoader.LoadPkcs12(Convert.FromBase64String(configuration["DataProtection:Certificate"]!), configuration["DataProtection:Password"]);
|
||||||
|
|
||||||
services.AddDataProtection().PersistKeysToDbContext<DataProtectionDbContext>()
|
services.AddDataProtection().PersistKeysToDbContext<DataProtectionDbContext>()
|
||||||
|
.ProtectKeysWithCertificate(certificate)
|
||||||
.SetApplicationName("LiteCharmsApp");
|
.SetApplicationName("LiteCharmsApp");
|
||||||
|
|
||||||
|
services.ConfigureCookieOidcSameSiteSupport();
|
||||||
|
|
||||||
var configSection = configuration.GetSection(nameof(LiteCharmsSettings));
|
var configSection = configuration.GetSection(nameof(LiteCharmsSettings));
|
||||||
|
|
||||||
var authOptions = new LiteCharmsSettings();
|
var authOptions = new LiteCharmsSettings();
|
||||||
@@ -71,39 +74,48 @@ public static class Api
|
|||||||
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||||
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
|
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
|
||||||
})
|
})
|
||||||
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
|
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
|
||||||
|
{
|
||||||
|
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
|
||||||
|
options.Cookie.SameSite = SameSiteMode.Lax;
|
||||||
|
options.Cookie.Name = "LiteCharmsApp.Session";
|
||||||
|
})
|
||||||
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
|
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
|
||||||
{
|
{
|
||||||
options.Authority = authOptions.Authority;
|
options.Authority = authOptions.Authority;
|
||||||
|
|
||||||
options.ClientId = authOptions.ClientId;
|
options.ClientId = authOptions.ClientId;
|
||||||
options.ClientSecret = authOptions.ClientSecret;
|
options.ClientSecret = authOptions.ClientSecret;
|
||||||
options.ResponseType = "code";
|
options.ResponseType = "code";
|
||||||
|
|
||||||
options.SaveTokens = true;
|
options.SaveTokens = true;
|
||||||
options.GetClaimsFromUserInfoEndpoint = true;
|
options.GetClaimsFromUserInfoEndpoint = true;
|
||||||
|
options.CorrelationCookie.SecurePolicy = CookieSecurePolicy.Always;
|
||||||
|
options.CorrelationCookie.SameSite = SameSiteMode.None;
|
||||||
|
|
||||||
|
options.NonceCookie.SecurePolicy = CookieSecurePolicy.Always;
|
||||||
|
options.NonceCookie.SameSite = SameSiteMode.None;
|
||||||
|
|
||||||
options.ForwardSignOut = CookieAuthenticationDefaults.AuthenticationScheme;
|
options.ForwardSignOut = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||||
|
|
||||||
options.Scope.Clear();
|
options.Scope.Clear();
|
||||||
options.Scope.Add("openid");
|
options.Scope.Add("openid");
|
||||||
options.Scope.Add("profile");
|
options.Scope.Add("profile");
|
||||||
options.Scope.Add("email");
|
options.Scope.Add("email");
|
||||||
|
|
||||||
options.Events = new OpenIdConnectEvents
|
options.Events = new OpenIdConnectEvents
|
||||||
{
|
{
|
||||||
OnRedirectToIdentityProviderForSignOut = context =>
|
OnRedirectToIdentityProviderForSignOut = context =>
|
||||||
{
|
{
|
||||||
var idToken = context.ProtocolMessage.IdTokenHint;
|
var idToken = context.ProtocolMessage.IdTokenHint;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(idToken))
|
if (string.IsNullOrEmpty(idToken))
|
||||||
{
|
{
|
||||||
var tokens = context.Properties.GetTokens();
|
var tokens = context.Properties.GetTokens();
|
||||||
var idTokenItem = tokens.FirstOrDefault(t => string.Equals(t.Name, "id_token", StringComparison.Ordinal));
|
var idTokenItem = tokens.FirstOrDefault(t => string.Equals(t.Name, "id_token", StringComparison.Ordinal));
|
||||||
|
|
||||||
if (idTokenItem != null) context.ProtocolMessage.IdTokenHint = idTokenItem.Value;
|
if (idTokenItem != null) context.ProtocolMessage.IdTokenHint = idTokenItem.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -114,6 +126,30 @@ public static class Api
|
|||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ConfigureCookieOidcSameSiteSupport(this IServiceCollection services) =>
|
||||||
|
services.Configure<CookiePolicyOptions>(options =>
|
||||||
|
{
|
||||||
|
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
|
||||||
|
options.OnAppendCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
|
||||||
|
options.OnDeleteCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
|
||||||
|
});
|
||||||
|
|
||||||
|
private static void CheckSameSite(HttpContext httpContext, CookieOptions options)
|
||||||
|
{
|
||||||
|
if (options.SameSite == SameSiteMode.None)
|
||||||
|
{
|
||||||
|
bool isSecure = httpContext.Request.IsHttps;
|
||||||
|
|
||||||
|
if (!isSecure && httpContext.Request.Headers.TryGetValue("X-Forwarded-Proto", out var proto))
|
||||||
|
isSecure = string.Equals(proto, "https", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (!isSecure && httpContext.Request.Headers.TryGetValue("Forwarded", out var forwarded))
|
||||||
|
isSecure = forwarded.ToString().Contains("proto=https", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (!isSecure) options.SameSite = SameSiteMode.Unspecified;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddLiteCharmsApiSecurity(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddLiteCharmsApiSecurity(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
var configSection = configuration.GetSection(nameof(LiteCharmsSettings));
|
var configSection = configuration.GetSection(nameof(LiteCharmsSettings));
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public static class Postgres
|
|||||||
|
|
||||||
public static IServiceCollection AddDataProtectionDatabase(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddDataProtectionDatabase(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
var connectionString = configuration.GetConnectionString(DataProtectionDbConfigName);
|
var connectionString = configuration.GetConnectionString(DataProtectionDbConfigName);
|
||||||
|
|
||||||
services.AddPooledDbContextFactory<DataProtectionDbContext>(options =>
|
services.AddPooledDbContextFactory<DataProtectionDbContext>(options =>
|
||||||
options.UseNpgsql(connectionString));
|
options.UseNpgsql(connectionString));
|
||||||
|
|||||||
@@ -197,6 +197,7 @@
|
|||||||
<!-- Shared Usings -->
|
<!-- Shared Usings -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Using Include="Microsoft.AspNetCore.DataProtection" />
|
<Using Include="Microsoft.AspNetCore.DataProtection" />
|
||||||
|
<Using Include="System.Security.Cryptography.X509Certificates" />
|
||||||
<Using Include="Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage" />
|
<Using Include="Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage" />
|
||||||
<Using Include="System.Text.Json.Serialization" />
|
<Using Include="System.Text.Json.Serialization" />
|
||||||
<Using Include="System.Reflection" />
|
<Using Include="System.Reflection" />
|
||||||
|
|||||||
Reference in New Issue
Block a user