Fix RLS permissions and JWT validation for admin club creation #5

Merged
MasterMito merged 18 commits from fix/rls-permission-test-failure into epic/admin_rework_second_try 2026-03-20 11:42:05 +01:00
Showing only changes of commit 13f9e7be7f - Show all commits
+41 -9
View File
@@ -51,21 +51,53 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
options.RequireHttpsMetadata = false; options.RequireHttpsMetadata = false;
options.MapInboundClaims = false; options.MapInboundClaims = false;
// For Docker internal communication, use the direct Keycloak URL for metadata // For Docker internal communication, configure metadata and signing key resolution
// This bypasses the hostname mismatch in Keycloak's discovery endpoint // to bypass the hostname mismatch in Keycloak's discovery endpoint
var keycloakAuthority = builder.Configuration["Keycloak:Authority"]; var keycloakAuthority = builder.Configuration["Keycloak:Authority"];
var keycloakInternalUrl = "http://keycloak:8081";
if (keycloakAuthority?.Contains("keycloak:") == true) if (keycloakAuthority?.Contains("keycloak:") == true)
{ {
// Set metadata address to internal Keycloak URL
options.MetadataAddress = $"{keycloakAuthority}/.well-known/openid-configuration"; options.MetadataAddress = $"{keycloakAuthority}/.well-known/openid-configuration";
// Configure custom signing key resolver to fetch from internal Keycloak URL
// This overrides the URLs returned in the discovery document
var httpClient = new HttpClient();
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKeyResolver = (token, securityToken, kid, validationParameters) =>
{
// Fetch JWKS from internal Keycloak URL
var jwksUrl = $"{keycloakInternalUrl}/realms/workclub/protocol/openid-connect/certs";
try
{
var response = httpClient.GetStringAsync(jwksUrl).GetAwaiter().GetResult();
var jwks = new Microsoft.IdentityModel.Tokens.JsonWebKeySet(response);
return jwks.Keys;
}
catch (Exception ex)
{
Console.WriteLine($"Failed to fetch JWKS from {jwksUrl}: {ex.Message}");
return Array.Empty<Microsoft.IdentityModel.Tokens.SecurityKey>();
}
}
};
} }
else
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{ {
ValidateIssuer = false, // Disabled for local dev - external clients use localhost:8080, internal use keycloak:8080 options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
ValidateAudience = true, {
ValidateLifetime = true, ValidateIssuer = false,
ValidateIssuerSigningKey = true ValidateAudience = true,
}; ValidateLifetime = true,
ValidateIssuerSigningKey = true
};
}
options.Events = new JwtBearerEvents options.Events = new JwtBearerEvents
{ {
OnAuthenticationFailed = context => OnAuthenticationFailed = context =>