Compare commits

...

16 Commits

Author SHA1 Message Date
khwezi 8d8ebffabf Merge pull request 'Removed required scope policy, no longer needed, audience covers the intent' (#84) from payments into master
Reviewed-on: #84
2026-06-06 16:44:52 +02:00
Khwezi Mngoma dc4addb43a Removed required scope policy, no longer needed, audience covers the intent
continuous-integration/drone/pr Build is passing
2026-06-06 16:44:22 +02:00
khwezi e2d29261da Merge pull request 'Updated API to use LiteCharms Security' (#83) from payments into master
Reviewed-on: #83
2026-06-06 16:27:16 +02:00
Khwezi Mngoma 5d5b59d610 Updated API to use LiteCharms Security
continuous-integration/drone/pr Build is passing
2026-06-06 16:26:27 +02:00
khwezi f001b02633 Merge pull request 'Refactored to deal with cookie hell' (#82) from payments into master
Reviewed-on: #82
2026-06-05 09:20:17 +02:00
Khwezi Mngoma 90a11dc65e Refactored to deal with cookie hell
continuous-integration/drone/pr Build is passing
2026-06-05 09:19:32 +02:00
khwezi de955a96a8 Merge pull request 'Removed login proto handling' (#81) from payments into master
Reviewed-on: #81
2026-06-05 08:56:17 +02:00
Khwezi Mngoma cdf5cfb5cd Removed login proto handling
continuous-integration/drone/pr Build is passing
2026-06-05 08:55:31 +02:00
khwezi c4d3bb4cdf Merge pull request 'Simplified login process' (#80) from payments into master
Reviewed-on: #80
2026-06-05 08:18:12 +02:00
Khwezi Mngoma 65f102f18a Simplified login process
continuous-integration/drone/pr Build is passing
2026-06-05 08:17:32 +02:00
khwezi cdc80db214 Merge pull request 'Refactored logout endpoint' (#79) from payments into master
Reviewed-on: #79
2026-06-05 08:15:50 +02:00
Khwezi Mngoma 4576b5aa2b Refactored logout endpoint
continuous-integration/drone/pr Build is passing
2026-06-05 08:15:13 +02:00
khwezi 3847927ace Merge pull request 'Added port stripping' (#78) from payments into master
Reviewed-on: #78
2026-06-05 07:37:16 +02:00
Khwezi Mngoma d38d1dd059 Added port stripping
continuous-integration/drone/pr Build is passing
2026-06-05 07:36:41 +02:00
khwezi c27aba1954 Merge pull request 'Forcing login https proto on redirect' (#77) from payments into master
Reviewed-on: #77
2026-06-05 06:40:33 +02:00
Khwezi Mngoma e646d16053 Forcing login https proto on redirect
continuous-integration/drone/pr Build is passing
2026-06-05 06:39:47 +02:00
5 changed files with 59 additions and 76 deletions
@@ -1,6 +1,6 @@
### Authentik Token Request (Service Account Explicit) ### Authentik Token Request (Service Account Explicit)
POST {{authority}} POST {{authority}}/connect/token
Content-Type: application/x-www-form-urlencoded Content-Type: application/x-www-form-urlencoded
Accept-Encoding: identity Accept-Encoding: identity
grant_type={{grantType}}&client_id={{clientId}}&username={{username}}&password={{password}}&scope={{scope}} grant_type={{grantType}}&client_id={{clientId}}&client_secret={{clientSecret}}&scope={{scope}}
@@ -0,0 +1,9 @@
{
"uat": {
"authority": "https://sts.security.khongisa.co.za",
"grantType": "client_credentials",
"clientId": "midrandbooks-api-uat",
"clientSecret": "secret_5a36d0024980544c875447a4b052938becc3fbbb10b8b2c097310c1a53ba3c0a",
"scope": "midrandbooks-api"
}
}
@@ -1,22 +0,0 @@
namespace LiteCharms.Features.Api.Configuration;
public sealed class AuthentikSettings
{
public string? Authority { get; set; }
public string? IntrospectionEndpoint { get; set; }
public string? MetadataEndpoint { get; set; }
public string? RevokationEndpoint { get; set; }
public string? ClientId { get; set; }
public string? ClientSecret { get; set; }
public string? RequiredClaimName { get; set; }
public string? RequiredClaimNameValue { get; set; }
public bool RequireHttpsMetadata { get; set; }
}
@@ -0,0 +1,12 @@
namespace LiteCharms.Features.Api.Configuration;
public sealed class LiteCharmsSettings
{
public string? Authority { get; set; }
public string? ClientId { get; set; }
public string? ClientSecret { get; set; }
public string? Audience { get; set; }
}
+36 -52
View File
@@ -1,6 +1,7 @@
using LiteCharms.Features.Abstractions; using LiteCharms.Features.Abstractions;
using LiteCharms.Features.Api; using LiteCharms.Features.Api;
using LiteCharms.Features.Api.Configuration; using LiteCharms.Features.Api.Configuration;
using Microsoft.AspNetCore.Authentication.JwtBearer;
namespace LiteCharms.Features.Extensions; namespace LiteCharms.Features.Extensions;
@@ -9,14 +10,14 @@ public static class Api
public const string Books = nameof(Books); public const string Books = nameof(Books);
public const string Payments = nameof(Payments); public const string Payments = nameof(Payments);
public static IServiceCollection AddAuthentikUiSecurity(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddLiteCharmsUiSecurity(this IServiceCollection services, IConfiguration configuration)
{ {
var configSection = configuration.GetSection(nameof(AuthentikSettings)); var configSection = configuration.GetSection(nameof(LiteCharmsSettings));
var authOptions = new AuthentikSettings(); var authOptions = new LiteCharmsSettings();
configSection.Bind(authOptions); configSection.Bind(authOptions);
services.Configure<AuthentikSettings>(configSection); services.Configure<LiteCharmsSettings>(configSection);
services.AddAuthentication(options => services.AddAuthentication(options =>
{ {
@@ -26,8 +27,7 @@ public static class Api
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{ {
options.Authority = authOptions.Authority; options.Authority = authOptions.Authority;
options.MetadataAddress = authOptions.MetadataEndpoint;
options.ClientId = authOptions.ClientId; options.ClientId = authOptions.ClientId;
options.ClientSecret = authOptions.ClientSecret; options.ClientSecret = authOptions.ClientSecret;
@@ -41,42 +41,42 @@ public static class Api
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.CorrelationCookie.SecurePolicy = CookieSecurePolicy.Always;
options.CorrelationCookie.SameSite = SameSiteMode.None;
options.CorrelationCookie.HttpOnly = true;
options.NonceCookie.SecurePolicy = CookieSecurePolicy.Always;
options.NonceCookie.SameSite = SameSiteMode.None;
options.NonceCookie.HttpOnly = true;
}); });
return services; return services;
} }
public static IServiceCollection AddAuthentikApiSecurity(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddLiteCharmsApiSecurity(this IServiceCollection services, IConfiguration configuration)
{ {
var configSection = configuration.GetSection(nameof(AuthentikSettings)); var configSection = configuration.GetSection(nameof(LiteCharmsSettings));
var authOptions = new AuthentikSettings(); var authOptions = new LiteCharmsSettings();
configSection.Bind(authOptions); configSection.Bind(authOptions);
services.Configure<AuthentikSettings>(configSection); services.Configure<LiteCharmsSettings>(configSection);
services.AddAuthentication(OAuth2IntrospectionDefaults.AuthenticationScheme) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddOAuth2Introspection(OAuth2IntrospectionDefaults.AuthenticationScheme, options => .AddJwtBearer(options =>
{ {
options.Authority = authOptions.Authority; options.Authority = authOptions.Authority;
options.IntrospectionEndpoint = authOptions.IntrospectionEndpoint; options.Audience = authOptions.Audience;
options.ClientId = authOptions.ClientId; options.TokenValidationParameters = new TokenValidationParameters
options.ClientSecret = authOptions.ClientSecret; {
ValidIssuer = authOptions.Authority,
options.NameClaimType = "sub"; ValidateAudience = true,
options.DiscoveryPolicy.RequireHttps = authOptions.RequireHttpsMetadata; ValidateIssuer = true,
options.DiscoveryPolicy.ValidateEndpoints = false; };
options.EnableCaching = false;
}); });
if (!string.IsNullOrWhiteSpace(authOptions.RequiredClaimName) && !string.IsNullOrWhiteSpace(authOptions.RequiredClaimNameValue)) services.AddAuthorization();
{
services.AddAuthorizationBuilder()
.AddPolicy("RequiredScope", policy =>
policy.RequireClaim(authOptions.RequiredClaimName, authOptions.RequiredClaimNameValue));
}
else
services.AddAuthorization();
return services; return services;
} }
@@ -87,36 +87,20 @@ public static class Api
{ {
await context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties await context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties
{ {
RedirectUri = redirectUri, RedirectUri = redirectUri,
}); });
}); });
app.MapGet("/logout", async (HttpContext context, IHttpClientFactory httpClientFactory, IOptions<AuthentikSettings> settings) => app.MapGet("/logout", async (HttpContext context, IHttpClientFactory httpClientFactory, IOptions<LiteCharmsSettings> settings) =>
{ {
var authOptions = settings.Value;
var accessToken = await context.GetTokenAsync("access_token");
if (!string.IsNullOrEmpty(accessToken))
{
try
{
var client = httpClientFactory.CreateClient();
var requestContent = new FormUrlEncodedContent(new Dictionary<string, string>(StringComparer.Ordinal)
{
{ "token", accessToken },
{ "client_id", authOptions.ClientId! },
{ "client_secret", authOptions.ClientSecret! },
});
await client.PostAsync(authOptions.RevokationEndpoint, requestContent, context.RequestAborted);
}
catch { }
}
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Results.Redirect("/"); string currentBaseUrl = $"https://{context.Request.Host}{context.Request.PathBase}/";
await context.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties
{
RedirectUri = currentBaseUrl
});
}); });
return app; return app;