From f6add24177103fbcd9bc8513b245d7bbdfe8d6f3 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 13:38:56 +0000 Subject: [PATCH] fix(api): normalise authentik public paths Co-Authored-By: Virgil --- authentik.go | 34 +++++++++++++++++++++++++++++++++- modernization_test.go | 12 ++++++++++++ spec_builder_helper_test.go | 2 +- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/authentik.go b/authentik.go index dfd63a9..6a23e3e 100644 --- a/authentik.go +++ b/authentik.go @@ -235,7 +235,39 @@ func authentikMiddleware(cfg AuthentikConfig, publicPaths func() []string) gin.H func cloneAuthentikConfig(cfg AuthentikConfig) AuthentikConfig { out := cfg - out.PublicPaths = slices.Clone(cfg.PublicPaths) + out.PublicPaths = normalisePublicPaths(cfg.PublicPaths) + return out +} + +// normalisePublicPaths trims whitespace, ensures a leading slash, and removes +// duplicate entries while preserving the first occurrence of each path. +func normalisePublicPaths(paths []string) []string { + if len(paths) == 0 { + return nil + } + + out := make([]string, 0, len(paths)) + seen := make(map[string]struct{}, len(paths)) + + for _, path := range paths { + path = strings.TrimSpace(path) + if path == "" { + continue + } + if !strings.HasPrefix(path, "/") { + path = "/" + path + } + path = strings.TrimRight(path, "/") + if path == "" { + path = "/" + } + if _, ok := seen[path]; ok { + continue + } + seen[path] = struct{}{} + out = append(out, path) + } + return out } diff --git a/modernization_test.go b/modernization_test.go index 54335e7..612be35 100644 --- a/modernization_test.go +++ b/modernization_test.go @@ -219,6 +219,18 @@ func TestEngine_AuthentikConfig_Good_ClonesPublicPaths(t *testing.T) { } } +func TestEngine_AuthentikConfig_Good_NormalisesPublicPaths(t *testing.T) { + e, _ := api.New(api.WithAuthentik(api.AuthentikConfig{ + PublicPaths: []string{" /public/ ", "docs", "/public"}, + })) + + cfg := e.AuthentikConfig() + expected := []string{"/public", "/docs"} + if !slices.Equal(cfg.PublicPaths, expected) { + t.Fatalf("expected normalised public paths %v, got %v", expected, cfg.PublicPaths) + } +} + func TestEngine_Register_Good_IgnoresNilGroups(t *testing.T) { e, _ := api.New() diff --git a/spec_builder_helper_test.go b/spec_builder_helper_test.go index 95d7b2c..ab3ee60 100644 --- a/spec_builder_helper_test.go +++ b/spec_builder_helper_test.go @@ -42,7 +42,7 @@ func TestEngine_Good_OpenAPISpecBuilderCarriesEngineMetadata(t *testing.T) { Issuer: "https://auth.example.com", ClientID: "core-client", TrustedProxy: true, - PublicPaths: []string{"/public", "/docs"}, + PublicPaths: []string{" /public/ ", "docs", "/public"}, }), api.WithWSPath("/socket"), api.WithWSHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})),