From adfd2e9d6fc2842c9180a7f5dc4b32dc16bee0d7 Mon Sep 17 00:00:00 2001 From: LD-Reborn Date: Sat, 18 Jul 2026 20:20:28 +0200 Subject: [PATCH] feat(server): adds CORS settings --- src/ReverseLlama.Server/Program.cs | 50 ++++++++++++++++++----- src/ReverseLlama.Server/ServerSettings.cs | 31 ++++++++++++++ src/ReverseLlama.Server/appsettings.json | 6 +++ 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/src/ReverseLlama.Server/Program.cs b/src/ReverseLlama.Server/Program.cs index 7839870..7e330a0 100644 --- a/src/ReverseLlama.Server/Program.cs +++ b/src/ReverseLlama.Server/Program.cs @@ -73,6 +73,44 @@ if (settings.Keycloak.IsConfigured) builder.Services.AddAuthorization(); +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(policy => + { + if (settings.Cors.AllowedOrigins.Contains("*")) + { + policy.AllowAnyOrigin(); + } + else + { + policy.WithOrigins(settings.Cors.AllowedOrigins); + } + + if (settings.Cors.AllowedMethods.Contains("*")) + { + policy.AllowAnyMethod(); + } + else + { + policy.WithMethods(settings.Cors.AllowedMethods); + } + + if (settings.Cors.AllowedHeaders.Contains("*")) + { + policy.AllowAnyHeader(); + } + else + { + policy.WithHeaders(settings.Cors.AllowedHeaders); + } + + if (settings.Cors.AllowCredentials) + { + policy.AllowCredentials(); + } + }); +}); + var app = builder.Build(); var managementStore = app.Services.GetRequiredService(); @@ -87,20 +125,12 @@ if (settings.Keycloak.IsConfigured) app.UseElmah(); +app.UseCors(); + app.Use(async (context, next) => { - context.Response.Headers.AccessControlAllowOrigin = "*"; - context.Response.Headers.AccessControlAllowMethods = "GET, POST, PUT, DELETE, PATCH, OPTIONS"; - context.Response.Headers.AccessControlAllowHeaders = "Content-Type, Authorization"; context.Response.Headers.XFrameOptions = "DENY"; context.Response.Headers.ContentSecurityPolicy = "frame-ancestors 'none'"; - - if (HttpMethods.IsOptions(context.Request.Method)) - { - context.Response.StatusCode = StatusCodes.Status204NoContent; - return; - } - await next(); }); diff --git a/src/ReverseLlama.Server/ServerSettings.cs b/src/ReverseLlama.Server/ServerSettings.cs index 2c0ca3d..4cdc220 100644 --- a/src/ReverseLlama.Server/ServerSettings.cs +++ b/src/ReverseLlama.Server/ServerSettings.cs @@ -19,6 +19,8 @@ internal sealed class ServerSettings public KeycloakSettings Keycloak { get; init; } = new(); + public CorsSettings Cors { get; init; } = new(); + public static ServerSettings FromConfiguration(IConfiguration configuration) { return new ServerSettings @@ -47,6 +49,13 @@ internal sealed class ServerSettings true, "Authentication:Keycloak:RequireHttpsMetadata", "REVERSE_LLAMA_KEYCLOAK_REQUIRE_HTTPS_METADATA") + }, + Cors = new CorsSettings + { + AllowedOrigins = ReadStringArray(configuration, ["CORS:AllowedOrigins"]), + AllowedMethods = ReadStringArray(configuration, ["CORS:AllowedMethods"]), + AllowedHeaders = ReadStringArray(configuration, ["CORS:AllowedHeaders"]), + AllowCredentials = ReadBool(configuration, false, "CORS:AllowCredentials") } }; } @@ -77,10 +86,32 @@ internal sealed class ServerSettings return bool.TryParse(value, out var parsed) ? parsed : fallback; } + private static string[] ReadStringArray(IConfiguration configuration, params string[] keys) + { + var value = Read(configuration, keys); + if (string.IsNullOrWhiteSpace(value)) + { + return []; + } + + return value.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + } + private static string NormalizePath(string path) => path.StartsWith('/') ? path : $"/{path}"; } +internal sealed class CorsSettings +{ + public string[] AllowedOrigins { get; init; } = ["*"]; + + public string[] AllowedMethods { get; init; } = ["*"]; + + public string[] AllowedHeaders { get; init; } = ["*"]; + + public bool AllowCredentials { get; init; } +} + internal sealed class KeycloakSettings { public string? Authority { get; init; } diff --git a/src/ReverseLlama.Server/appsettings.json b/src/ReverseLlama.Server/appsettings.json index 10f68b8..7e1ea93 100644 --- a/src/ReverseLlama.Server/appsettings.json +++ b/src/ReverseLlama.Server/appsettings.json @@ -5,5 +5,11 @@ "Microsoft.AspNetCore": "Warning" } }, + "CORS": { + "AllowedOrigins": [ "*" ], + "AllowedMethods": [ "GET", "POST", "PUT", "DELETE", "PATCH" ], + "AllowedHeaders": [ "Content-Type", "Authorization" ], + "AllowCredentials": false + }, "AllowedHosts": "*" }