forked from baron/baron-sso
fix(headless-login): honor public base url for audience checks
- resolve headless audience against BACKEND_PUBLIC_URL first - keep forwarded header support for https absolute audiences - add regression tests for https success and http mismatch rejection - write BACKEND_PUBLIC_URL into staging workflow env generation
This commit is contained in:
@@ -703,30 +703,124 @@ func (h *AuthHandler) getBearerToken(c *fiber.Ctx) string {
|
||||
return parts[1]
|
||||
}
|
||||
|
||||
func (h *AuthHandler) resolveUserfrontURL(c *fiber.Ctx) string {
|
||||
// 1. Try to use the Host header from the request
|
||||
host := c.Get("X-Forwarded-Host")
|
||||
func firstForwardedValue(raw string) string {
|
||||
for _, part := range strings.Split(raw, ",") {
|
||||
value := strings.TrimSpace(part)
|
||||
if value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func forwardedDirective(raw, key string) string {
|
||||
for _, group := range strings.Split(raw, ",") {
|
||||
for _, directive := range strings.Split(group, ";") {
|
||||
pair := strings.SplitN(strings.TrimSpace(directive), "=", 2)
|
||||
if len(pair) != 2 {
|
||||
continue
|
||||
}
|
||||
if !strings.EqualFold(strings.TrimSpace(pair[0]), key) {
|
||||
continue
|
||||
}
|
||||
return strings.Trim(strings.TrimSpace(pair[1]), "\"")
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func normalizedAbsoluteBaseURL(raw string) string {
|
||||
trimmed := strings.TrimSpace(raw)
|
||||
if trimmed == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
parsed, err := url.Parse(trimmed)
|
||||
if err != nil || parsed.Scheme == "" || parsed.Host == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
parsed.RawQuery = ""
|
||||
parsed.Fragment = ""
|
||||
return strings.TrimRight(parsed.String(), "/")
|
||||
}
|
||||
|
||||
func forwardedRequestHost(c *fiber.Ctx) string {
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
if host := firstForwardedValue(c.Get("X-Forwarded-Host")); host != "" {
|
||||
return host
|
||||
}
|
||||
if host := forwardedDirective(c.Get("Forwarded"), "host"); host != "" {
|
||||
return host
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func forwardedRequestProto(c *fiber.Ctx) string {
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
if proto := firstForwardedValue(c.Get("X-Forwarded-Proto")); proto != "" {
|
||||
return strings.ToLower(proto)
|
||||
}
|
||||
if proto := forwardedDirective(c.Get("Forwarded"), "proto"); proto != "" {
|
||||
return strings.ToLower(proto)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func resolvePublicRequestBaseURL(c *fiber.Ctx, configuredBaseURL string) string {
|
||||
if base := normalizedAbsoluteBaseURL(configuredBaseURL); base != "" {
|
||||
return base
|
||||
}
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
host := forwardedRequestHost(c)
|
||||
proto := forwardedRequestProto(c)
|
||||
if host != "" && proto != "" {
|
||||
return fmt.Sprintf("%s://%s", proto, host)
|
||||
}
|
||||
|
||||
base := strings.TrimRight(strings.TrimSpace(c.BaseURL()), "/")
|
||||
if base != "" {
|
||||
return base
|
||||
}
|
||||
|
||||
host = strings.TrimSpace(c.Get("Host"))
|
||||
if host == "" {
|
||||
host = c.Hostname()
|
||||
host = strings.TrimSpace(c.Hostname())
|
||||
}
|
||||
|
||||
// 2. Determine scheme
|
||||
scheme := "https"
|
||||
if os.Getenv("APP_ENV") == "dev" || os.Getenv("APP_ENV") == "" || c.Protocol() == "http" {
|
||||
scheme = "http"
|
||||
proto = strings.ToLower(strings.TrimSpace(c.Protocol()))
|
||||
if host == "" || proto == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s://%s", proto, host)
|
||||
}
|
||||
|
||||
// 3. Fallback to env if host is not available or is localhost (and not in dev)
|
||||
func (h *AuthHandler) resolveUserfrontURL(c *fiber.Ctx) string {
|
||||
envURL := os.Getenv("USERFRONT_URL")
|
||||
if envURL == "" {
|
||||
envURL = "http://sso.hmac.kr"
|
||||
}
|
||||
|
||||
baseURL := resolvePublicRequestBaseURL(c, "")
|
||||
host := strings.TrimSpace(forwardedRequestHost(c))
|
||||
if host == "" {
|
||||
host = strings.TrimSpace(c.Hostname())
|
||||
}
|
||||
|
||||
if host == "" || (host == "localhost" && os.Getenv("APP_ENV") != "dev") {
|
||||
return strings.TrimRight(envURL, "/")
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s://%s", scheme, host)
|
||||
if baseURL == "" {
|
||||
return strings.TrimRight(envURL, "/")
|
||||
}
|
||||
return baseURL
|
||||
}
|
||||
|
||||
func (h *AuthHandler) GetTenantInfo(c *fiber.Ctx) error {
|
||||
@@ -1751,7 +1845,7 @@ func headlessAssertionAudiences(c *fiber.Ctx) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
base := strings.TrimRight(strings.TrimSpace(c.BaseURL()), "/")
|
||||
base := resolvePublicRequestBaseURL(c, os.Getenv("BACKEND_PUBLIC_URL"))
|
||||
if base == "" {
|
||||
return []string{path}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user