hcaptcha

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 8, 2026 License: GPL-3.0 Imports: 16 Imported by: 0

README

hCaptcha Module

A bot protection module for oCMS integrating hCaptcha on the login form.

Features

  • hCaptcha widget integration on login form
  • Server-side token verification with hCaptcha API
  • Environment variable overrides for keys
  • Configurable theme (light/dark) and size (normal/compact)
  • Template functions for custom integration
  • Hook-based architecture for extensibility
  • Admin interface for configuration
  • Settings persisted in database

Admin Interface

Access at Admin > Modules > hCaptcha or /admin/hcaptcha.

Routes
Method Path Description
GET /admin/hcaptcha Settings dashboard
POST /admin/hcaptcha Save settings

Configuration

Via Admin Interface
  1. Navigate to hCaptcha settings
  2. Enter your Site Key (from hCaptcha dashboard)
  3. Enter your Secret Key (from hCaptcha dashboard)
  4. Choose theme and size preferences
  5. Enable hCaptcha
  6. Save settings
Via Environment Variables
OCMS_HCAPTCHA_SITE_KEY=your-site-key
OCMS_HCAPTCHA_SECRET_KEY=your-secret-key

Environment variables override database settings for keys.

Test Keys (Defaults)

hCaptcha's test keys are used as defaults when no keys are configured:

Key Value
Site Key 10000000-ffff-ffff-ffff-000000000001
Secret Key 0x0000000000000000000000000000000000000000

With test keys, the widget auto-passes without showing a challenge.

This means you can enable hCaptcha immediately in development without configuring any keys. Just enable it in the admin interface and it will work. Replace with your own keys from hcaptcha.com for production use.

Template Functions

hcaptchaEnabled

Returns true if hCaptcha is enabled and properly configured.

{{if hcaptchaEnabled}}
    <!-- Show captcha-related content -->
{{end}}
hcaptchaWidget

Returns the hCaptcha widget HTML (script + div).

{{if hcaptchaEnabled}}
<div class="captcha-container">
    {{hcaptchaWidget}}
</div>
{{end}}

Output:

<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
<div class="h-captcha" data-sitekey="..." data-theme="light" data-size="normal"></div>

Hooks

The module registers two hooks for integration:

auth.login_widget

Called to render the captcha widget in the login form.

auth.before_login

Called before login to verify the captcha response. Receives a VerifyRequest struct:

type VerifyRequest struct {
    Response  string // h-captcha-response from form
    RemoteIP  string // Client IP address
    Verified  bool   // Set to true after successful verification
    Error     string // Error message if verification failed
    ErrorCode string // Error code for i18n
}

Database Schema

Settings are stored in a single-row table:

CREATE TABLE hcaptcha_settings (
    id INTEGER PRIMARY KEY CHECK (id = 1),
    enabled INTEGER NOT NULL DEFAULT 0,
    site_key TEXT NOT NULL DEFAULT '10000000-ffff-ffff-ffff-000000000001',
    secret_key TEXT NOT NULL DEFAULT '0x0000000000000000000000000000000000000000',
    theme TEXT NOT NULL DEFAULT 'light',
    size TEXT NOT NULL DEFAULT 'normal',
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

Note: Default values are hCaptcha test keys for development convenience.

Module Structure

modules/hcaptcha/
├── module.go      # Module definition, lifecycle, hooks, template funcs, migrations
├── handlers.go    # HTTP handlers (dashboard, save settings)
├── settings.go    # Settings struct, load/save, widget rendering
├── verify.go      # hCaptcha API verification
├── README.md      # This file
└── locales/       # Embedded i18n translations
    ├── en/messages.json
    └── ru/messages.json

Verification Flow

  1. User loads login page with hCaptcha widget
  2. User completes captcha challenge
  3. Form submission includes h-captcha-response field
  4. Server extracts response and client IP
  5. auth.before_login hook is called
  6. Module verifies token with hCaptcha API (https://api.hcaptcha.com/siteverify)
  7. Verification result determines if login proceeds

API Verification

The module sends a POST request to hCaptcha:

POST https://api.hcaptcha.com/siteverify
Content-Type: application/x-www-form-urlencoded

secret=your-secret-key&response=token&remoteip=client-ip

Response:

{
  "success": true,
  "challenge_ts": "2024-01-01T00:00:00Z",
  "hostname": "example.com",
  "error-codes": []
}

Error Codes

Code Description
hcaptcha.error_required User didn't complete captcha
hcaptcha.error_verification API request failed
hcaptcha.error_invalid Token rejected by hCaptcha

Internationalization

Translations are embedded and automatically loaded. Supported languages:

  • English (en)
  • Russian (ru)

Add new languages by creating locales/{lang}/messages.json.

See docs/i18n.md for the translation file format and guidelines.

Module Active Status

The module can be enabled/disabled from Admin > Modules:

  • Active: Hooks registered, widget renders, verification enforced
  • Inactive: No widget shown, verification skipped

Note: Even when the module is active, hCaptcha protection only applies when enabled=true in settings AND both keys are configured.

Security

  • Secret key is masked in admin display (shows xxxx****xxxx)
  • All keys are HTML-escaped before injection
  • Settings require admin authentication
  • CSRF protection on form submission
  • Client IP extraction supports reverse proxy headers (X-Forwarded-For, X-Real-IP)
  • Verification timeout of 10 seconds prevents hanging

Troubleshooting

Locked out after enabling

Disable via database:

sqlite3 ./data/ocms.db "UPDATE hcaptcha_settings SET enabled = 0"
Widget not appearing
  1. Check enabled = 1 in database
  2. Verify both site_key and secret_key are set
  3. Check browser console for JavaScript errors
  4. Ensure hCaptcha script can load (no firewall/ad blocker)
Verification always fails
  1. Verify secret key is correct
  2. Check server can reach https://api.hcaptcha.com
  3. Check server logs for specific error codes
  4. Ensure client IP is correctly detected (check proxy headers)

Dependencies

  • hCaptcha API: https://api.hcaptcha.com/siteverify
  • hCaptcha JS: https://js.hcaptcha.com/1/api.js

Documentation

Overview

Package hcaptcha provides hCaptcha integration for oCMS. Protects login forms from bots and automated attacks.

Index

Constants

View Source
const (
	// HookAuthLoginWidget is called to render the captcha widget in login form.
	HookAuthLoginWidget = "auth.login_widget"
	// HookAuthBeforeLogin is called before login to verify captcha.
	HookAuthBeforeLogin = "auth.before_login"
	// HookFormCaptchaWidget is called to render captcha widget in public forms.
	HookFormCaptchaWidget = "form.captcha_widget"
	// HookFormCaptchaVerify is called to verify captcha on form submission.
	HookFormCaptchaVerify = "form.captcha_verify"
)

Hook names for hCaptcha integration.

View Source
const (
	TestSiteKey   = "10000000-ffff-ffff-ffff-000000000001"
	TestSecretKey = "0x0000000000000000000000000000000000000000"
)

hCaptcha test/debug keys for development. These always pass verification without showing a challenge. See: https://docs.hcaptcha.com/#integration-testing-test-keys

Variables

This section is empty.

Functions

func GetRemoteIP

func GetRemoteIP(r *http.Request) string

GetRemoteIP extracts the client IP from an HTTP request.

func GetResponseFromForm

func GetResponseFromForm(r *http.Request) string

GetResponseFromForm extracts the h-captcha-response from an HTTP request.

Types

type Module

type Module struct {
	module.BaseModule
	// contains filtered or unexported fields
}

Module implements the module.Module interface for the hCaptcha module.

func New

func New() *Module

New creates a new instance of the hCaptcha module.

func (*Module) AdminURL

func (m *Module) AdminURL() string

AdminURL returns the admin dashboard URL for the module.

func (*Module) GetSettings

func (m *Module) GetSettings() Settings

GetSettings returns a copy of the current settings (for use by other packages).

func (*Module) Init

func (m *Module) Init(ctx *module.Context) error

Init initializes the module with the given context.

func (*Module) IsEnabled

func (m *Module) IsEnabled() bool

IsEnabled returns whether hCaptcha protection is enabled and configured.

func (*Module) Migrations

func (m *Module) Migrations() []module.Migration

Migrations returns database migrations for the module.

func (*Module) RegisterAdminRoutes

func (m *Module) RegisterAdminRoutes(r chi.Router)

RegisterAdminRoutes registers admin routes for the module.

func (*Module) RegisterRoutes

func (m *Module) RegisterRoutes(_ chi.Router)

RegisterRoutes registers public routes for the module.

func (*Module) ReloadSettings

func (m *Module) ReloadSettings() error

ReloadSettings reloads settings from the database.

func (*Module) RenderWidget

func (m *Module) RenderWidget() template.HTML

RenderWidget returns the hCaptcha widget HTML.

func (*Module) Shutdown

func (m *Module) Shutdown() error

Shutdown performs cleanup when the module is shutting down.

func (*Module) SidebarLabel

func (m *Module) SidebarLabel() string

SidebarLabel returns the display label for the admin sidebar.

func (*Module) TemplateFuncs

func (m *Module) TemplateFuncs() template.FuncMap

TemplateFuncs returns template functions provided by the module.

func (*Module) TranslationsFS

func (m *Module) TranslationsFS() embed.FS

TranslationsFS returns the embedded filesystem containing module translations.

func (*Module) Verify

func (m *Module) Verify(response, remoteIP string) (*VerifyResponse, error)

Verify checks the hCaptcha response token with the hCaptcha API.

func (*Module) VerifyFromRequest

func (m *Module) VerifyFromRequest(req *VerifyRequest) (*VerifyRequest, error)

VerifyFromRequest verifies the captcha from a VerifyRequest struct.

type Settings

type Settings struct {
	Enabled   bool
	SiteKey   string // Public site key
	SecretKey string // Secret key for verification
	Theme     string // "light" or "dark"
	Size      string // "normal" or "compact"
}

Settings holds the hCaptcha configuration.

type VerifyRequest

type VerifyRequest struct {
	Response  string // h-captcha-response from form
	RemoteIP  string // Client IP address
	Verified  bool   // Set to true after successful verification
	Error     string // Error message if verification failed
	ErrorCode string // Error code for i18n
}

VerifyRequest contains the data needed to verify a captcha response.

type VerifyResponse

type VerifyResponse struct {
	Success     bool      `json:"success"`
	ChallengeTS time.Time `json:"challenge_ts"`
	Hostname    string    `json:"hostname"`
	ErrorCodes  []string  `json:"error-codes"`
}

VerifyResponse represents the hCaptcha API response.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL