A Spring Boot microservice that provides proof-of-work CAPTCHA challenges using the ALTCHA library. This service offers an alternative to traditional image-based CAPTCHAs with adaptive difficulty management and multi-tenant support.
graph TB
%% External Client
Client
%% External Services
subgraph "External Services"
PostgreSQL[(PostgreSQL<br/>Database)]
end
%% Main CaptchaService Application
subgraph "CaptchaService Application"
%% Monitoring & Management
subgraph "Monitoring"
Actuator["**Spring Actuator**<br/>/actuator/info<br/>/actuator/health<br/>/actuator/metrics"]
end
%% API Endpoints Detail
subgraph "CaptchaController"
ChallengeEndpoint["**postChallenge()**<br/>Create CAPTCHA Challenge"]
VerifyEndpoint["**postVerify()**<br/>Verify CAPTCHA Solution"]
end
%% Service Layer
subgraph "Service Layer"
CaptchaService["**CaptchaService**<br/>Core CAPTCHA Logic"]
DifficultyService["**DifficultyService**<br/>Adaptive Difficulty Management"]
SiteAuthService["**SiteAuthService**<br/>Site Key/Secret Validation"]
SourceAddressService["**SourceAddressService**<br/>IP Address Validation"]
ExpiredDataService["**ExpiredDataService**<br/>Cleanup Scheduler"]
end
%% Data Layer
subgraph "Data Layer"
CaptchaRequestRepo["**CaptchaRequestRepository**<br/>JPA Repository"]
InvalidatedPayloadRepo["**InvalidatedPayloadRepository**<br/>JPA Repository"]
subgraph "JPA Entities"
CaptchaRequestEntity["**CaptchaRequest**<br/>Entity"]
InvalidatedPayloadEntity["**InvalidatedPayload**<br/>Entity"]
end
end
%% Properties/Configuration
subgraph "Configuration Properties"
CaptchaProperties["**CaptchaProperties**<br/>HMAC Key, Sites Config"]
CaptchaSite["**CaptchaSite**<br/>Site-specific Settings"]
DifficultyItem["**DifficultyItem**<br/>Difficulty Mappings"]
end
end
%% Request Flow
Client -->|POST /api/v1/challenge| ChallengeEndpoint
Client -->|POST /api/v1/verify| VerifyEndpoint
Client --> Monitoring
%% Controller to Services
ChallengeEndpoint --> CaptchaService
VerifyEndpoint --> CaptchaService
ChallengeEndpoint --> SiteAuthService
VerifyEndpoint --> SiteAuthService
ChallengeEndpoint --> SourceAddressService
%% Service Interactions
CaptchaService --> DifficultyService
CaptchaService --> CaptchaRequestRepo
CaptchaService --> InvalidatedPayloadRepo
CaptchaService --> AltchaLib
DifficultyService --> CaptchaRequestRepo
ExpiredDataService -->|Scheduled Cleanup| CaptchaRequestRepo
ExpiredDataService -->|Scheduled Cleanup| InvalidatedPayloadRepo
%% Data Layer
CaptchaRequestRepo --> CaptchaRequestEntity
InvalidatedPayloadRepo --> InvalidatedPayloadEntity
CaptchaRequestEntity -.->|JPA/Hibernate| PostgreSQL
InvalidatedPayloadEntity -.->|JPA/Hibernate| PostgreSQL
%% Configuration Dependencies
CaptchaService -.->|Uses| CaptchaProperties
SiteAuthService -.->|Uses| CaptchaProperties
SourceAddressService -.->|Uses| CaptchaProperties
DifficultyService -.->|Uses| CaptchaProperties
%% Database Migration
Flyway -.->|Schema Management| PostgreSQL
class CaptchaService,DifficultyService,SiteAuthService,SourceAddressService,ExpiredDataService service
class CaptchaRequestRepo,InvalidatedPayloadRepo,CaptchaRequestEntity,InvalidatedPayloadEntity data
class PostgreSQL,Client external
class ChallengeEndpoint,VerifyEndpoint endpoint
class CaptchaProperties,CaptchaSite,DifficultyItem properties
- Proof-of-Work CAPTCHA: Uses ALTCHA library for crypto-based challenge verification
- Adaptive Difficulty: Automatically adjusts challenge difficulty based on request patterns
- Multi-Tenant Support: Site-specific configuration with individual keys and secrets
- Source Address Validation: IP-based filtering and network address validation
- Scheduled Cleanup: Automatic removal of expired challenges and invalidated payloads
- Monitoring: Comprehensive health checks and metrics via Spring Actuator
- Database Persistence: PostgreSQL storage with automated Flyway migrations
- Java 21 or later
- Maven 3.8+
- PostgreSQL 16+
- Docker and Docker Compose (for local development)
-
Clone the repository
git clone https://github.com/it-at-m/captchaservice.git cd captchaservice
-
Start the development stack
cd stack docker compose up -d
-
Build and run the application
cd captchaservice-backend bash runLocal.sh
-
Verify the service is running
curl http://localhost:39146/actuator/health
Variable | Description | Default |
---|---|---|
SPRING_DATASOURCE_URL |
PostgreSQL connection URL | jdbc:postgresql://localhost:5432/captchaservice |
SPRING_DATASOURCE_USERNAME |
Database username | - |
SPRING_DATASOURCE_PASSWORD |
Database password | - |
CAPTCHA_HMAC_KEY |
HMAC key for challenge signing | - |
CAPTCHA_CAPTCHA_TIMEOUT_SECONDS |
Challenge validity period | 300 |
CAPTCHA_SOURCE_ADDRESS_WINDOW_SECONDS |
Source address tracking window | 3600 |
Configure multiple sites in your application.yml
:
captcha:
hmac-key: secret # HMAC key for signing challenges
captcha-timeout-seconds: 300 # How long a CAPTCHA challenge is valid
source-address-window-seconds: 3600 # How long a source address is stored
sites:
site1: # Site key for site1
site-secret: "secret1" # Site secret for site1
max-verifies-per-payload: 1 # How many times a payload can be verified
whitelisted_source-addresses:
- "192.0.2.0/24" # Whitelisted IP address range
site2:
site-secret: "secret2"
whitelisted_source-addresses:
- "192.0.2.0/24" # Whitelisted IP address range
difficulty-map:
- min-visits: 1 # From the first visit on...
max-number: 1000 # ...the difficulty is 1000
- min-visits: 10 # From the 10th visit on...
max-number: 10000 # ...the difficulty is 10000
POST /api/v1/captcha/challenge
Creates a new CAPTCHA challenge for the specified site.
Request Body:
{
"siteKey": "site1",
"siteSecret": "secret1",
"clientAddress": "192.168.1.100"
}
Response:
{
"algorithm": "SHA-256",
"challenge": "abc123...",
"maxNumber": 1000,
"salt": "def456...",
"signature": "ghi789..."
}
POST /api/v1/captcha/verify
Verifies a CAPTCHA solution payload.
Request Body:
{
"siteKey": "site1",
"siteSecret": "secret1",
"clientAddress": "192.168.1.100",
"payload": {
"algorithm": "SHA-256",
"challenge": "abc123...",
"number": 542,
"salt": "def456...",
"signature": "ghi789...",
"took": 4400
}
}
Response:
401 Unauthorized - Invalid site credentials
{
"status": 401,
"error": "Authentication Error"
}
400 Bad Request - Invalid request format
{
"status": 400,
"error": "Bad Request"
}
Database schema is managed using Flyway migrations located in src/main/resources/db/migration/
# Run migrations manually
mvn flyway:migrate
# Check migration status
mvn flyway:info
# Validate migrations
mvn flyway:validate
- Liveness:
GET /actuator/health/liveness
- Readiness:
GET /actuator/health/readiness
- Overall Health:
GET /actuator/health
- Info Endpoint:
GET /actuator/info
- Metrics:
GET /actuator/metrics
Prometheus metrics available at /actuator/prometheus
:
- Application metrics
- JVM metrics
- Database connection pool metrics
- Custom CAPTCHA metrics
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
To learn more about how you can contribute, please read our contribution documentation.
Distributed under the MIT License. See LICENSE file for more information.
it@M - [email protected]