package middlewares import ( "crypto/hmac" "crypto/sha256" "encoding/base64" "net/http" "strings" "GoMembership/internal/config" // "GoMembership/internal/server" "GoMembership/internal/utils" "GoMembership/pkg/logger" ) // GenerateCSRFToken generates HMAC-signed CSRF token func GenerateCSRFToken(sessionID string, secretKey string) string { // Create message to be signed (e.g., combining sessionID with some random value) randomString, err := utils.GenerateRandomString(8) if err != nil { logger.Error.Fatalf("Could not create random string: %v", err) return "" } message := sessionID + "!" + randomString // Create HMAC hash using SHA-256 h := hmac.New(sha256.New, []byte(secretKey)) h.Write([]byte(message)) signature := h.Sum(nil) // Encode signature and message into a CSRF token csrfToken := base64.StdEncoding.EncodeToString(signature) + "." + message return csrfToken } func ComputeHMAC(message string, secretKey string) []byte { h := hmac.New(sha256.New, []byte(secretKey)) h.Write([]byte(message)) return h.Sum(nil) } // CSRFMiddleware verifies HMAC-signed CSRF token func CSRFMiddleware(next http.Handler) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet || r.Method == http.MethodHead || r.Method == http.MethodOptions { next.ServeHTTP(w, r) return } csrfSecret := config.Auth.CSRFSecret // Retrieve CSRF token from request (e.g., from cookie, header, or form data) csrfToken := r.Header.Get("X-CSRF-Token") // Extract signature and message from CSRF token parts := strings.SplitN(csrfToken, ".", 2) if len(parts) != 2 { http.Error(w, "Invalid CSRF token", http.StatusForbidden) return } receivedSignature := parts[0] receivedMessage := parts[1] // Compute HMAC using the received message and the CSRF secret key computedSignature := ComputeHMAC(receivedMessage, csrfSecret) // Compare computed HMAC with received signature if !hmac.Equal([]byte(receivedSignature), computedSignature) { http.Error(w, "CSRF Token validation failed", http.StatusForbidden) return } // CSRF token is valid, proceed to the next handler next.ServeHTTP(w, r) }) } func GenerateCSRFTokenHandler(w http.ResponseWriter, r *http.Request) { // Simulate getting session ID from authenticated session sessionID := "exampleSessionID123" // Generate HMAC-signed CSRF token csrfToken := GenerateCSRFToken(sessionID, config.Auth.CSRFSecret) // Set CSRF token in a cookie (example) http.SetCookie(w, &http.Cookie{ Name: "csrf_token", Value: csrfToken, Path: "/", HttpOnly: true, Secure: true, }) } /* func GenerateCSRFTokenHandler() http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { token, err := GenerateCSRFToken() if err != nil { http.Error(w, "Could not generate CSRF token", http.StatusInternalServerError) return } // Set CSRF token in cookie http.SetCookie(w, &http.Cookie{ Name: "csrf_token", Value: token, Path: "/", }) logger.Info.Printf("generated token: %v", token) // Return CSRF token in response w.Header().Set("X-CSRF-Token", token) w.WriteHeader(http.StatusOK) }) } */