mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-12 04:04:26 +00:00
93 lines
3.0 KiB
Go
93 lines
3.0 KiB
Go
package traefikoidc
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
// TestApplyBypassUserHeaders_SanitizesIdentifier is a regression test for the
|
|
// auth-bypass header path (applyBypassUserHeaders). The claim-derived user
|
|
// identifier is injected into X-Forwarded-User / X-Auth-Request-User without
|
|
// sanitization, unlike forwardAuthorized which uses sanitizeHeaderClaimValue.
|
|
// An IdP-controlled identifier containing CRLF (or a delimiter) would
|
|
// otherwise inject or confuse downstream header parsing. Now the bypass path
|
|
// sanitizes the identifier and drops the header on failure.
|
|
func TestApplyBypassUserHeaders_SanitizesIdentifier(t *testing.T) {
|
|
sm := createTestSessionManager(t)
|
|
|
|
base := httptest.NewRequest(http.MethodGet, "/protected", nil)
|
|
baseRec := httptest.NewRecorder()
|
|
|
|
// Build an authenticated session whose user identifier contains CRLF.
|
|
session, err := sm.GetSession(base)
|
|
if err != nil {
|
|
t.Fatalf("GetSession: %v", err)
|
|
}
|
|
if err := session.SetAuthenticated(true); err != nil {
|
|
t.Fatalf("SetAuthenticated: %v", err)
|
|
}
|
|
session.SetUserIdentifier("user\nX-Injected: yes")
|
|
if err := session.Save(base, baseRec); err != nil {
|
|
t.Fatalf("Save: %v", err)
|
|
}
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/protected", nil)
|
|
for _, c := range baseRec.Result().Cookies() {
|
|
req.AddCookie(c)
|
|
}
|
|
|
|
oidc := &TraefikOidc{
|
|
sessionManager: sm,
|
|
logger: NewLogger("debug"),
|
|
}
|
|
|
|
if ok, _ := oidc.applyBypassUserHeaders(req, "test"); !ok {
|
|
t.Fatalf("applyBypassUserHeaders returned false; bypass should be honored")
|
|
}
|
|
if v := req.Header.Get("X-Forwarded-User"); v != "" {
|
|
t.Fatalf("X-Forwarded-User = %q, want empty (unsafe identifier dropped)", v)
|
|
}
|
|
if v := req.Header.Get("X-Auth-Request-User"); v != "" {
|
|
t.Fatalf("X-Auth-Request-User = %q, want empty (unsafe identifier dropped)", v)
|
|
}
|
|
}
|
|
|
|
// TestApplyBypassUserHeaders_KeepsCleanIdentifier ensures a normal identifier
|
|
// still flows through, and is trimmed/sanitized.
|
|
func TestApplyBypassUserHeaders_KeepsCleanIdentifier(t *testing.T) {
|
|
sm := createTestSessionManager(t)
|
|
|
|
base := httptest.NewRequest(http.MethodGet, "/protected", nil)
|
|
baseRec := httptest.NewRecorder()
|
|
|
|
session, err := sm.GetSession(base)
|
|
if err != nil {
|
|
t.Fatalf("GetSession: %v", err)
|
|
}
|
|
if err := session.SetAuthenticated(true); err != nil {
|
|
t.Fatalf("SetAuthenticated: %v", err)
|
|
}
|
|
session.SetUserIdentifier(" [email protected] ")
|
|
if err := session.Save(base, baseRec); err != nil {
|
|
t.Fatalf("Save: %v", err)
|
|
}
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/protected", nil)
|
|
for _, c := range baseRec.Result().Cookies() {
|
|
req.AddCookie(c)
|
|
}
|
|
|
|
oidc := &TraefikOidc{
|
|
sessionManager: sm,
|
|
logger: NewLogger("debug"),
|
|
}
|
|
|
|
if ok, _ := oidc.applyBypassUserHeaders(req, "test"); !ok {
|
|
t.Fatalf("applyBypassUserHeaders returned false; bypass should be honored")
|
|
}
|
|
if v := req.Header.Get("X-Forwarded-User"); v != "[email protected]" {
|
|
t.Fatalf("X-Forwarded-User = %q, want %q (trimmed)", v, "[email protected]")
|
|
}
|
|
}
|