# Captcha Middleware CAPTCHA verification middleware package providing session-based captcha challenge and verification. ## Overview This package implements CAPTCHA verification middleware that protects routes by requiring users to complete a CAPTCHA challenge before accessing the protected resource. It supports pluggable providers (currently hCAPTCHA) and uses encrypted sessions for verification state. ## Architecture ```mermaid graph TD A[Client Request] --> B{Captcha Session?} B -->|Valid| C[Proceed to Backend] B -->|Invalid| D[Show CAPTCHA Page] D --> E{POST with Token?} E -->|Valid| F[Create Session
Set Cookie] E -->|Invalid| G[Show Error] F --> C subgraph Captcha Provider H[hCAPTCHA API] D -->|Script/Form HTML| H F -->|Verify Token| H end subgraph Session Store I[CaptchaSessions
jsonstore] end F --> I I -.->|Session Check| B ``` ## Captcha Flow ```mermaid sequenceDiagram participant C as Client participant M as Middleware participant P as Provider participant S as Session Store participant B as Backend C->>M: Request (no session) M->>M: Check cookie M->>M: Session not found/expired M->>C: Send CAPTCHA Page C->>M: POST with captcha response M->>P: Verify token P-->>M: Verification result alt Verification successful M->>S: Store session M->>C: Set session cookie
Redirect to protected path C->>M: Request (with session cookie) M->>S: Validate session M->>B: Forward request else Verification failed M->>C: Error: verification failed end ``` ## Core Components ### Provider Interface ```go type Provider interface { // CSP directives for the captcha provider CSPDirectives() []string // CSP sources for the captcha provider CSPSources() []string // Verify the captcha response from the request Verify(r *http.Request) error // Session expiry duration after successful verification SessionExpiry() time.Duration // Script HTML to include in the page ScriptHTML() string // Form HTML to render the captcha widget FormHTML() string } ``` ### ProviderBase ```go type ProviderBase struct { Expiry time.Duration `json:"session_expiry"` // Default: 24 hours } func (p *ProviderBase) SessionExpiry() time.Duration ``` ### hCAPTCHA Provider ```go type HcaptchaProvider struct { ProviderBase SiteKey string `json:"site_key" validate:"required"` Secret string `json:"secret" validate:"required"` } // CSP Directives: script-src, frame-src, style-src, connect-src // CSP Sources: https://hcaptcha.com, https://*.hcaptcha.com ``` ### Captcha Session ```go type CaptchaSession struct { ID string `json:"id"` Expiry time.Time `json:"expiry"` } var CaptchaSessions = jsonstore.Store[*CaptchaSession]("captcha_sessions") func newCaptchaSession(p Provider) *CaptchaSession func (s *CaptchaSession) expired() bool ``` ## Middleware Integration ```go type hCaptcha struct { captcha.HcaptchaProvider } func (h *hCaptcha) before(w http.ResponseWriter, r *http.Request) bool { return captcha.PreRequest(h, w, r) } var HCaptcha = NewMiddleware[hCaptcha]() ``` ### PreRequest Handler ```go func PreRequest(p Provider, w http.ResponseWriter, r *http.Request) (proceed bool) ``` This function: 1. Checks for valid session cookie 1. Validates session expiry 1. Returns true if session is valid 1. For non-HTML requests, returns 403 Forbidden 1. For POST requests, verifies the captcha token 1. For GET requests, renders the CAPTCHA challenge page ## Configuration ### hCAPTCHA Configuration ```yaml middleware: my-captcha: use: hcaptcha site_key: "YOUR_SITE_KEY" secret: "YOUR_SECRET" session_expiry: 24h # optional, default 24h ``` ### Route Configuration ```yaml routes: - host: example.com path: /admin middlewares: - my-captcha ``` ## Usage Examples ### Basic Setup ```go import "github.com/yusing/godoxy/internal/net/gphttp/middleware" hcaptchaMiddleware := middleware.HCaptcha.New(middleware.OptionsRaw{ "site_key": "your-site-key", "secret": "your-secret", }) ``` ### Using in Middleware Chain ```yaml # config/middlewares/admin-protection.yml - use: captcha site_key: "${HCAPTCHA_SITE_KEY}" secret: "${HCAPTCHA_SECRET}" bypass: - type: CIDR value: 10.0.0.0/8 ``` ## Session Management Sessions are stored in a JSON-based store with the following properties: - **Session ID**: 32-byte CRNG (`crypto/rand.Read`) random hex string - **Expiry**: Configurable duration (default 24 hours) - **Cookie**: `godoxy_captcha_session` with HttpOnly flag ```mermaid flowchart TD A[Session Created] --> B[Cookie Set] B --> C[Client Sends Cookie] C --> D{Session Valid?} D -->|Yes| E[Proceed] D -->|No| F{HTML Request?} F -->|Yes| G[Show CAPTCHA] F -->|No| H[403 Forbidden] ``` ## CSP Integration The CAPTCHA provider supplies CSP directives that should be added to the response: ```go // hCAPTCHA CSP Directives CSPDirectives() []string // Returns: ["script-src", "frame-src", "style-src", "connect-src"] CSPSources() []string // Returns: ["https://hcaptcha.com", "https://*.hcaptcha.com"] ``` ## HTML Template The package includes an embedded HTML template (`captcha.html`) that renders the CAPTCHA challenge page with: - Provider script (`