Revert "Merge pull request #9 from wahyd4/traefik-support"

This reverts commit 01a625d8fd, reversing
changes made to 1aba3b3947.
This commit is contained in:
2025-08-08 20:52:06 +10:00
parent 01a625d8fd
commit 2836c22e3b
12 changed files with 27 additions and 441 deletions
+4 -40
View File
@@ -392,18 +392,17 @@ func (h *Handlers) Logout(w http.ResponseWriter, r *http.Request) {
h.writeJSON(w, map[string]string{"status": "success"})
}
// AuthCheck implements auth backend for both nginx auth_request and Traefik ForwardAuth
// AuthCheck implements the nginx auth_request protocol
func (h *Handlers) AuthCheck(w http.ResponseWriter, r *http.Request) {
// Debug logging
logrus.Debugf("AuthCheck request from %s", r.RemoteAddr)
logrus.Debugf("AuthCheck headers: %+v", r.Header)
logrus.Debugf("AuthCheck cookies: %+v", r.Cookies())
logrus.Debugf("AuthCheck query params: %+v", r.URL.Query())
session, err := h.store.Get(r, "auth-session")
if err != nil {
logrus.Errorf("Failed to get auth session: %v", err)
h.handleUnauthenticated(w, r)
w.WriteHeader(http.StatusUnauthorized)
return
}
@@ -412,8 +411,8 @@ func (h *Handlers) AuthCheck(w http.ResponseWriter, r *http.Request) {
logrus.Debugf("Session values: %+v", session.Values)
if !ok || !authenticated {
logrus.Debugf("User not authenticated")
h.handleUnauthenticated(w, r)
logrus.Debugf("User not authenticated, returning 401")
w.WriteHeader(http.StatusUnauthorized)
return
}
@@ -429,41 +428,6 @@ func (h *Handlers) AuthCheck(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}
// handleUnauthenticated handles unauthenticated requests for both Nginx and Traefik
func (h *Handlers) handleUnauthenticated(w http.ResponseWriter, r *http.Request) {
// Check for redirect parameter (Traefik ForwardAuth typically includes this)
redirectURL := r.URL.Query().Get("rd")
if redirectURL == "" {
// Also check for other common redirect parameter names
redirectURL = r.URL.Query().Get("redirect")
}
// If redirect parameter is present, return 302 redirect (Traefik ForwardAuth)
if redirectURL != "" {
logrus.Debugf("Redirect parameter found (%s), returning 302 redirect for Traefik", redirectURL)
// Construct login URL with redirect parameter
loginURL := "/login.html?redirect=" + redirectURL
// If we have a host header, construct a full URL
if host := r.Header.Get("Host"); host != "" {
scheme := "http"
if r.Header.Get("X-Forwarded-Proto") == "https" || r.TLS != nil {
scheme = "https"
}
loginURL = scheme + "://" + host + loginURL
}
w.Header().Set("Location", loginURL)
w.WriteHeader(http.StatusFound) // 302
return
}
// No redirect parameter, return 401 (Nginx auth_request)
logrus.Debugf("No redirect parameter, returning 401 for Nginx auth_request")
w.WriteHeader(http.StatusUnauthorized)
}
// GetAuthStatus returns the current authentication status
func (h *Handlers) GetAuthStatus(w http.ResponseWriter, r *http.Request) {
session, err := h.store.Get(r, "auth-session")
-195
View File
@@ -1,195 +0,0 @@
package handlers
import (
"net/http"
"net/http/httptest"
"testing"
"passkey-auth/internal/auth"
"passkey-auth/internal/config"
"passkey-auth/internal/database"
)
func TestAuthCheck(t *testing.T) {
// Setup test config
cfg := &config.Config{
Auth: config.AuthConfig{
SessionSecret: "test-secret",
},
WebAuthn: config.WebAuthnConfig{
RPDisplayName: "Test Passkey Auth",
RPID: "localhost",
RPOrigins: []string{"http://localhost:8080"},
},
}
// Setup test database
db, err := database.New(":memory:")
if err != nil {
t.Fatalf("Failed to create test database: %v", err)
}
defer db.Close()
// Setup test WebAuthn (mock)
webAuthn, err := auth.NewWebAuthn(cfg)
if err != nil {
t.Fatalf("Failed to create test WebAuthn: %v", err)
}
// Create handlers
h := New(db, webAuthn, cfg)
tests := []struct {
name string
queryParams string
authenticated bool
expectedStatus int
expectedHeader string
}{
{
name: "Unauthenticated without redirect param (Nginx)",
queryParams: "",
authenticated: false,
expectedStatus: http.StatusUnauthorized,
expectedHeader: "",
},
{
name: "Unauthenticated with rd param (Traefik)",
queryParams: "rd=https://example.com/protected",
authenticated: false,
expectedStatus: http.StatusFound,
expectedHeader: "/login.html?redirect=https://example.com/protected",
},
{
name: "Unauthenticated with redirect param (Traefik)",
queryParams: "redirect=https://example.com/protected",
authenticated: false,
expectedStatus: http.StatusFound,
expectedHeader: "/login.html?redirect=https://example.com/protected",
},
{
name: "Authenticated with redirect param",
queryParams: "rd=https://example.com/protected",
authenticated: true,
expectedStatus: http.StatusOK,
expectedHeader: "",
},
{
name: "Authenticated without redirect param",
queryParams: "",
authenticated: true,
expectedStatus: http.StatusOK,
expectedHeader: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create request
req, err := http.NewRequest("GET", "/auth?"+tt.queryParams, nil)
if err != nil {
t.Fatalf("Failed to create request: %v", err)
}
// Mock session if authenticated
if tt.authenticated {
// Create a session cookie for testing
session, _ := h.store.Get(req, "auth-session")
session.Values["authenticated"] = true
session.Values["user_id"] = 1
session.Values["user_email"] = "test@example.com"
// Create a response recorder to capture the session cookie
w := httptest.NewRecorder()
session.Save(req, w)
// Extract the cookie and add it to the request
for _, cookie := range w.Result().Cookies() {
if cookie.Name == "auth-session" {
req.AddCookie(cookie)
break
}
}
}
// Create response recorder
w := httptest.NewRecorder()
// Call the handler
h.AuthCheck(w, req)
// Check status code
if w.Code != tt.expectedStatus {
t.Errorf("Expected status %d, got %d", tt.expectedStatus, w.Code)
}
// Check Location header for redirects
if tt.expectedStatus == http.StatusFound {
location := w.Header().Get("Location")
if location != tt.expectedHeader {
t.Errorf("Expected Location header %s, got %s", tt.expectedHeader, location)
}
}
// Check auth headers for authenticated requests
if tt.authenticated && tt.expectedStatus == http.StatusOK {
userHeader := w.Header().Get("X-Auth-User")
if userHeader == "" {
t.Error("Expected X-Auth-User header for authenticated request")
}
}
})
}
}
func TestAuthCheckWithHost(t *testing.T) {
// Setup test config
cfg := &config.Config{
Auth: config.AuthConfig{
SessionSecret: "test-secret",
},
WebAuthn: config.WebAuthnConfig{
RPDisplayName: "Test Passkey Auth",
RPID: "localhost",
RPOrigins: []string{"http://localhost:8080"},
},
}
// Setup test database
db, err := database.New(":memory:")
if err != nil {
t.Fatalf("Failed to create test database: %v", err)
}
defer db.Close()
// Setup test WebAuthn
webAuthn, err := auth.NewWebAuthn(cfg)
if err != nil {
t.Fatalf("Failed to create test WebAuthn: %v", err)
}
// Create handlers
h := New(db, webAuthn, cfg)
// Test with Host header
req, err := http.NewRequest("GET", "/auth?rd=https://example.com/protected", nil)
if err != nil {
t.Fatalf("Failed to create request: %v", err)
}
req.Header.Set("Host", "auth.example.com")
req.Header.Set("X-Forwarded-Proto", "https")
w := httptest.NewRecorder()
h.AuthCheck(w, req)
// Should return 302 with full URL
if w.Code != http.StatusFound {
t.Errorf("Expected status %d, got %d", http.StatusFound, w.Code)
}
expectedLocation := "https://auth.example.com/login.html?redirect=https://example.com/protected"
location := w.Header().Get("Location")
if location != expectedLocation {
t.Errorf("Expected Location header %s, got %s", expectedLocation, location)
}
}