fix(auth): prevent open redirect via callback_ui (#3844)

Validate callback_ui and default invalid values to /.
Allow absolute callback_ui only when its origin is allowlisted via http.auth.openid.callbackAllowOrigins (and externalUrl).
Add/adjust unit + controller tests and update examples/docs for relative vs allowlisted absolute redirect

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
This commit is contained in:
Andrei Aaron
2026-03-08 08:13:16 +02:00
committed by GitHub
parent 6f67fcdf8f
commit 9425ca8b7d
10 changed files with 368 additions and 12 deletions
+8 -1
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"maps"
"os"
"slices"
"sync"
"time"
@@ -279,6 +280,11 @@ type SessionKeys struct {
type OpenIDConfig struct {
Providers map[string]OpenIDProviderConfig
// CallbackAllowOrigins is an allowlist of absolute URL origins that are permitted in the
// callback_ui query parameter during the OpenID/OAuth2 login flow. If empty, callback_ui must
// be a same-origin relative path (e.g. "/v2/") to prevent open redirects.
// Example: ["http://localhost:3000", "https://ui.example.com"]
CallbackAllowOrigins []string `mapstructure:"callbackAllowOrigins,omitempty"`
}
type OpenIDCredentials struct {
@@ -720,7 +726,8 @@ func (c *Config) Sanitize() *Config {
// Sanitize OpenID client secrets
if c.HTTP.Auth.OpenID != nil {
sanitizedConfig.HTTP.Auth.OpenID = &OpenIDConfig{
Providers: make(map[string]OpenIDProviderConfig),
Providers: make(map[string]OpenIDProviderConfig),
CallbackAllowOrigins: slices.Clone(c.HTTP.Auth.OpenID.CallbackAllowOrigins),
}
for provider, config := range c.HTTP.Auth.OpenID.Providers {