README
¶
Autentico - OIDC Identity Provider
Auténtico is a lightweight OpenID Connect (OIDC) Identity Provider (IdP) built with Go. It provides standards-compliant authentication and identity management for your applications, issuing and managing identity tokens, access tokens, and user sessions. Auténtico uses SQLite for persistence, making it easy to deploy as a standalone IdP without external database dependencies.
Try It Live
A brand-new, isolated Autentico instance is provisioned just for you
Clicking the link spins up a fresh instance with its own isolated database and a full Admin UI. The first account you create becomes the administrator. Instances are automatically cleaned up after 24 hours.
Table of Contents
- Features
- Tech Stack
- Architecture Overview
- Getting Started
- Configuration
- API Documentation
- Endpoints
- Supported Grant Types
- Client Interaction Examples
- Security Considerations
- Deployment & Operations
- Troubleshooting & Operations
- Admin UI
- Testing
- Contributing
- License
Features
Autentico provides a full-featured OIDC Identity Provider with the following capabilities:
- OIDC Discovery: Publishes
/.well-known/openid-configurationso relying parties can auto-discover endpoints, supported scopes, and signing keys. - ID Token Issuance: Issues RS256-signed ID tokens containing standard OIDC claims (
sub,iss,aud,exp,iat,nonce). - UserInfo Endpoint: Serves authenticated identity claims via
/oauth2/userinfoper the OIDC Core specification. - JWK Set Endpoint: Exposes public signing keys at
/oauth2/certsfor token verification by relying parties. - Authorization Code Flow with PKCE: Implements the recommended secure flow for web and mobile applications, with Proof Key for Code Exchange (RFC 7636) support for public clients.
- Dynamic Client Registration: Register and manage OAuth2 clients (relying parties) via REST API with support for confidential and public client types.
- Client Authentication: Supports
client_secret_basic(HTTP Basic Auth) andclient_secret_post(form parameters) authentication methods. - Refresh Token Support: Allows relying parties to obtain new access tokens without re-authenticating the user.
- Token Introspection & Revocation: Provides endpoints for validating and invalidating tokens (RFC 7009, RFC 7662).
- Session Management: Manages user sessions with configurable idle timeouts and logout support.
- Lightweight & Self-Contained: Single binary with embedded SQLite — no external database or infrastructure required.
- CSRF Protection: Utilizes
gorilla/csrffor protection against Cross-Site Request Forgery attacks on relevant endpoints.
Tech Stack
- Go (Golang): Single-binary deployment with strong performance and type safety.
- SQLite: Embedded database — no external database server required.
- RS256 (RSA) JWT Signing: Industry-standard asymmetric signing for ID and access tokens.
- Gorilla Toolkit: CSRF protection middleware.
- Testify: Test assertions and mocking.
- Swagger/OpenAPI: Interactive API documentation.
Architecture Overview
Project Structure
Autentico is structured as a modular Go application. Each package in pkg/ encapsulates a distinct area of IdP functionality:
| Package | IdP Role |
|---|---|
pkg/authorize |
Handles the OIDC authorization endpoint — renders the login page and initiates the auth flow |
pkg/login |
Processes user authentication and issues authorization codes |
pkg/token |
Token endpoint — issues ID tokens, access tokens, and refresh tokens; handles introspection and revocation |
pkg/wellknown |
Serves the OIDC discovery document (/.well-known/openid-configuration) |
pkg/key |
RSA key management and JWK Set generation for token verification |
pkg/client |
OAuth2 client (relying party) registration and management |
pkg/user |
User identity storage and credential management |
pkg/session |
User session lifecycle, idle timeouts, and logout |
pkg/middleware |
HTTP middleware (CORS, CSRF, logging, authentication) |
pkg/config |
Application configuration |
pkg/db |
SQLite database initialization and schema |
The main.go file initializes the configuration, database, and routes, and starts the HTTP server. The login page is served from the view/ directory.
Design Philosophy
Auténtico prioritizes operational simplicity and deployment autonomy as first-class architectural concerns. The design deliberately minimizes external dependencies and infrastructure complexity to reduce the operational surface area and eliminate entire classes of failure modes. This is not a prototype—it is production-grade infrastructure built with the understanding that the highest leverage engineering decisions are those that remove complexity rather than accommodate it prematurely.
Why SQLite
SQLite is an architectural choice, not a constraint. For identity workloads at this scale, SQLite's performance characteristics—handling tens of thousands of concurrent reads with single-digit millisecond latency—far exceed typical requirements. The embedded database eliminates connection pooling, network partitions, credential rotation, and distributed transaction complexity. It collapses the deployment model to a single binary with no external runtime dependencies, which fundamentally changes the operational contract: no orchestration layers, no managed services, no stateful infrastructure to provision. When load characteristics eventually justify migration, that decision comes with the resources and operational maturity to execute it correctly. Until then, the engineering velocity gained from eliminating accidental complexity is substantial.
Performance Benchmarks (2024 M1 MacBook Pro, 16GB RAM):
- Token issuance: ~2,500 tokens/sec/core
- Authorization code validation: < 5ms p99
- Session lookup: < 2ms p95
- Database size: ~50KB per 1,000 users (excluding audit logs)
- Memory footprint: ~45MB baseline, ~120MB under load (10k concurrent sessions)
SQLite's write serialization is the eventual bottleneck. At ~500 writes/sec sustained, consider write batching or migration to PostgreSQL. For read-heavy IdP workloads (typical ratio: 100:1 reads:writes), this threshold represents approximately 50,000 logins/hour.
Why RS256 over HS256
Symmetric signing algorithms like HS256 require any party that verifies a token to also hold the secret used to sign it, which creates a secret distribution problem as the number of relying parties grows. RS256 allows Auténtico to hold the private key exclusively while any relying party can verify tokens independently using the public JWK Set exposed at /oauth2/certs. This is the correct architecture for an IdP regardless of scale.
On ROPC Support
The Resource Owner Password Credentials grant is deprecated in OAuth 2.1 and not recommended for new integrations. It is supported here deliberately, because omitting it would break backward compatibility with legacy clients, older SDKs, and internal tooling that existing projects may already depend on. If you are building something new, use the Authorization Code flow instead. (ROPC support is planned to be feature flagged allowing to disable it)
Getting Started
Prerequisites
- Go 1.21 or later installed on your system.
make(optional, for using Makefile commands).
Installation & Running
-
Clone the repository:
git clone https://github.com/eugenioenko/autentico.git cd autentico -
Build the application:
make build # Or directly using Go: # go build autentico main.go -
Initialize the configuration:
Generate a
.envfile with secure secrets and a stable RSA private key:./autentico init -
Run the application:
./autentico startThe server will start on
http://localhost:9999. -
Complete Onboarding:
Open the ONBOARDING URL displayed in your terminal (e.g.,
http://localhost:9999/admin/). Follow the instructions to create the first administrator account and complete the system setup.
Configuration
Auténtico uses a three-layer configuration system:
- Bootstrap Settings (
.envfile): Immutable infrastructure settings (database path, port, secrets, RSA key). - Global Settings (Database): Runtime-editable settings (token expiration, MFA, SMTP, theming) managed via the Admin UI.
- Per-Client Overrides: Specific settings (like token TTL or allowed audiences) configured individually for each OAuth2 client.
Environment Variables (.env)
| Variable | Description | Default |
|---|---|---|
AUTENTICO_APP_URL |
Base URL of the application | http://localhost:9999 |
AUTENTICO_APP_OAUTH_PATH |
Path prefix for OAuth2 endpoints | /oauth2 |
AUTENTICO_DB_FILE_PATH |
Path to SQLite database file | ./db/autentico.db |
AUTENTICO_PRIVATE_KEY |
Base64-encoded RSA private key | (Generated by init) |
AUTENTICO_ACCESS_TOKEN_SECRET |
Secret for signing access tokens | (Generated by init) |
AUTENTICO_REFRESH_TOKEN_SECRET |
Secret for signing refresh tokens | (Generated by init) |
AUTENTICO_CSRF_SECRET_KEY |
Secret for CSRF protection | (Generated by init) |
Managing Settings
Once onboarded, navigate to the Settings section in the Admin UI to configure runtime options such as:
- Multi-Factor Authentication (TOTP, Email OTP)
- Security Policies (Password length, account lockout)
- Email (SMTP) server configuration
- Theme & Branding (Logo, colors, title)
- Token Lifetimes (Access, refresh, and auth code durations)
Multi-Factor Authentication (MFA)
Autentico supports MFA with two methods:
- TOTP — Time-based one-time passwords via authenticator apps (Google Authenticator, Authy, etc.)
- Email — One-time codes sent via email (requires SMTP configuration)
When mfaEnabled is true, all users are required to complete MFA after password authentication. For TOTP, users who haven't enrolled yet will be shown a QR code to scan with their authenticator app on their next login.
Login Page Theming
The login page can be customized via the Settings section in the Admin UI.
Available CSS Variables:
Override these in your custom CSS:
:root {
/* Typography */
--font-size: 16px;
--font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
/* Colors - Light Mode */
--color-primary: #2e5bff;
--color-accent: #188060;
--color-danger: #ff4848;
--color-text: #0f0f0f;
--color-inverse: #ffffff;
--color-background: #f1f1f1;
--color-card: #ffffff;
--color-border: #696969;
/* Layout */
--border-radius: 2px;
--form-width: 380px;
--form-padding: 30px;
--form-gap: 16px;
--form-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
/* Logo */
--logo-size: 96px;
--logo-margin: 16px 0 32px 0;
--logo-padding: 16px;
/* Elements */
--input-padding: 10px;
--button-padding: 10px;
--button-margin-top: 16px;
--h1-font-size: 2rem;
--label-padding-bottom: 4px;
}
/* Dark mode: override color variables */
@media (prefers-color-scheme: dark) {
:root {
--color-primary: #2e5bff;
--color-accent: #188060;
--color-danger: #d60b0b;
--color-text: #e7e7e7;
--color-inverse: #e7e7e7;
--color-background: #0f0f0f;
--color-card: #1e1f22;
--color-border: #cccccc;
}
}
API Documentation
Autentico provides comprehensive API documentation:
-
Static HTML Documentation: A pre-generated, detailed HTML API reference is available.
- Autentico API Documentation (GitHub Pages)
- You can also find this at
/docs/index.htmlin the repository.
-
Swagger UI / OpenAPI Specification: To explore the API interactively using Swagger UI:
make docsThis command starts a local server (default:
http://localhost:8888) serving the Swagger UI.- Access it at: http://localhost:8888/swagger/index.html
- The OpenAPI specification files (
swagger.json,swagger.yaml) are located in the/docsdirectory.
Endpoints
OIDC Discovery & Identity
| Endpoint | Method | Description |
|---|---|---|
/.well-known/openid-configuration |
GET | OIDC discovery document — relying parties use this to auto-configure |
/oauth2/certs |
GET | JWK Set — public keys for verifying tokens issued by this IdP |
/oauth2/authorize |
GET | Authorization endpoint — initiates the authentication flow |
/oauth2/token |
POST | Token endpoint — issues ID tokens, access tokens, and refresh tokens |
/oauth2/userinfo |
GET | UserInfo endpoint — returns identity claims for the authenticated user |
/oauth2/introspect |
POST | Token introspection (RFC 7662) |
/oauth2/revoke |
POST | Token revocation (RFC 7009) |
/oauth2/logout |
POST | Ends the user session |
User Management
| Endpoint | Method | Description |
|---|---|---|
/users/create |
POST | Register a new user identity |
Client Registration (Admin Only)
Relying parties (OAuth2 clients) are managed via these endpoints. All require admin authentication.
| Endpoint | Method | Description |
|---|---|---|
/oauth2/register |
POST | Register a new relying party |
/oauth2/register |
GET | List all registered relying parties |
/oauth2/register/{client_id} |
GET | Get a specific relying party |
/oauth2/register/{client_id} |
PUT | Update a relying party's configuration |
/oauth2/register/{client_id} |
DELETE | Deactivate a relying party (soft delete) |
Supported Grant Types
Autentico supports the following OAuth 2.0 / OIDC grant types:
- Authorization Code (with PKCE) — The recommended flow for web and native applications. The IdP authenticates the user, issues an authorization code, and the relying party exchanges it for ID + access tokens. PKCE (RFC 7636) is supported for public clients using S256 or plain challenge methods.
- Resource Owner Password Credentials — Direct credential exchange. Provided for trusted or legacy clients; not recommended for new applications.
- Refresh Token — Obtain new access tokens without re-authenticating the user.
Client Interaction Examples
Autentico supports dynamic client registration via the /oauth2/register API. Admin users can register relying parties (OAuth2 clients), which are then validated during authorization and token flows.
Register an OAuth2 Client (Admin Only)
Register a new client application. This requires an admin user's access token:
# First, obtain an admin access token (admin user must exist)
ADMIN_TOKEN=$(curl -s -X POST http://localhost:9999/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=password&username=admin@example.com&password=AdminPassword123!" \
| jq -r '.access_token')
# Register a new confidential client
curl -X POST http://localhost:9999/oauth2/register \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"client_name": "My Application",
"redirect_uris": ["https://myapp.com/callback", "http://localhost:3000/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"client_type": "confidential",
"token_endpoint_auth_method": "client_secret_basic"
}'
Response:
{
"client_id": "abc123xyz...",
"client_secret": "generated_secret_shown_once",
"client_secret_expires_at": 0,
"client_name": "My Application",
"client_type": "confidential",
"redirect_uris": [
"https://myapp.com/callback",
"http://localhost:3000/callback"
],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "client_secret_basic"
}
Important: The
client_secretis only shown once during registration. Store it securely.
Register a Public Client (SPA/Mobile)
For single-page applications or mobile apps that cannot securely store secrets:
curl -X POST http://localhost:9999/oauth2/register \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"client_name": "My SPA",
"redirect_uris": ["http://localhost:3000/callback"],
"grant_types": ["authorization_code"],
"client_type": "public"
}'
Register a User
Create a new user via the /users/create endpoint:
curl -X POST http://localhost:9999/users/create \
-H "Content-Type: application/json" \
-d '{"username": "user@example.com", "password": "SecurePassword123!", "email": "user@example.com"}'
Authorization Request
Redirect the user to the /oauth2/authorize endpoint to start the login process.
Using JavaScript (with PKCE):
// Generate PKCE code_verifier and code_challenge
function generateCodeVerifier() {
const array = new Uint8Array(32);
crypto.getRandomValues(array);
return btoa(String.fromCharCode(...array))
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
async function generateCodeChallenge(verifier) {
const encoder = new TextEncoder();
const data = encoder.encode(verifier);
const digest = await crypto.subtle.digest("SHA-256", data);
return btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
// Store codeVerifier for the token exchange step
sessionStorage.setItem("code_verifier", codeVerifier);
const authServerUrl = "http://localhost:9999/oauth2/authorize";
const params = new URLSearchParams({
response_type: "code",
redirect_uri: "https://your-client-app.com/callback",
scope: "openid profile email",
state: "callback_state",
nonce: crypto.randomUUID(),
code_challenge: codeChallenge,
code_challenge_method: "S256",
});
window.location.href = `${authServerUrl}?${params.toString()}`;
Using curl to construct the URL for manual testing:
# Note: This curl command just constructs the URL. You'd then open this URL in a browser.
# Replace placeholders accordingly.
# Ensure the redirect_uri is whitelisted in Autentico's config.
EFFECTIVE_URL=$(curl -G -s -o /dev/null -w "%{url_effective}\n" \
--data-urlencode "response_type=code" \
--data-urlencode "client_id=el_autentico_!" \
--data-urlencode "redirect_uri=https://your-client-app.com/callback" \
--data-urlencode "scope=openid profile email" \
--data-urlencode "state=xyz123abc" \
--data-urlencode "nonce=$(uuidgen)" \
http://localhost:9999/oauth2/authorize)
echo "Open this URL in your browser: ${EFFECTIVE_URL}"
# Example for macOS: open "${EFFECTIVE_URL}"
Token Exchange
After successful authentication, the user is redirected back to your redirect_uri with an authorization code. Exchange this code for tokens at the /oauth2/token endpoint.
Using HTTP Basic Auth (client_secret_basic - Recommended):
curl -X POST http://localhost:9999/oauth2/token \
-u "your_client_id:your_client_secret" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=your_received_authorization_code" \
-d "redirect_uri=https://your-client-app.com/callback"
Using Form Parameters (client_secret_post):
curl -X POST http://localhost:9999/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=your_received_authorization_code" \
-d "redirect_uri=https://your-client-app.com/callback" \
-d "client_id=your_client_id" \
-d "client_secret=your_client_secret"
For Public Clients with PKCE (recommended):
curl -X POST http://localhost:9999/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=your_received_authorization_code" \
-d "redirect_uri=https://your-client-app.com/callback" \
-d "client_id=your_client_id" \
-d "code_verifier=your_stored_code_verifier"
A successful response will contain access_token, id_token, refresh_token, token_type, and expires_in.
Security Considerations
As an Identity Provider, Autentico is a critical trust boundary. The following practices apply:
- HTTPS: Always deploy behind a reverse proxy with TLS in production. An IdP must never serve tokens over plaintext.
- Secure Cookies: Set
AuthRefreshTokenAsSecureCookieandAuthCSRFSecureCookietotruewhen using HTTPS. - CSRF Protection:
gorilla/csrfprotects interactive endpoints (login form). Use a strong, unique 32-byteAuthCSRFProtectionSecretKey. - Redirect URI Validation: Strictly validates
redirect_uriagainst registered client URIs to prevent open redirector attacks. - Client Authentication: Confidential relying parties authenticate via client secret (HTTP Basic Auth or form parameters). Secrets are bcrypt-hashed at rest.
- Strong Secret Keys: All configured secrets (
AuthAccessTokenSecret,AuthRefreshTokenSecret,AuthCSRFProtectionSecretKey) must be cryptographically strong. - RS256 Token Signing: Tokens are signed with RSA private keys. Only the IdP holds the private key; relying parties verify using the public JWK Set.
- Input Validation: Usernames and passwords are validated according to configured length and format rules.
Deployment & Operations
Production Deployment Patterns
Autentico's single-binary architecture supports multiple deployment models:
Container Deployment (Recommended for orchestrated environments):
FROM alpine:latest
RUN apk add --no-cache ca-certificates
COPY autentico /usr/local/bin/
COPY autentico.json /etc/autentico/
VOLUME ["/data"]
EXPOSE 9999
CMD ["autentico", "start"]
Reverse Proxy Configuration (nginx example):
upstream autentico {
server 127.0.0.1:9999;
keepalive 32;
}
server {
listen 443 ssl http2;
server_name auth.example.com;
ssl_certificate /etc/ssl/certs/auth.example.com.crt;
ssl_certificate_key /etc/ssl/private/auth.example.com.key;
location / {
proxy_pass http://autentico;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Observability
Autentico logs structured events to stdout. Recommended observability stack:
- Metrics: Expose
/metricsendpoint for Prometheus scraping (memory, request rates, token issuance) - Logging: JSON-structured logs with correlation IDs for distributed tracing
- Alerting: Monitor failed authentication attempts, token validation failures, session expiry rates
- Key SLIs:
- Token issuance latency (p95 < 100ms)
- Authorization code exchange success rate (> 99.9%)
- Session validation latency (p99 < 50ms)
Backup & Recovery
SQLite database backup strategies:
# Hot backup using SQLite's backup API
sqlite3 /data/autentico.db ".backup /backup/autentico-$(date +%Y%m%d-%H%M%S).db"
# Incremental backups using WAL mode
sqlite3 /data/autentico.db "PRAGMA journal_mode=WAL;"
# WAL files can be backed up separately while database is running
Recovery time objective (RTO): < 5 minutes for single-instance deployments.
Migration Path to Distributed Database
When SQLite performance becomes constrained (typically > 100k daily active users), migration path:
- Read Replica Pattern: Add PostgreSQL as async replica for read queries
- Dual-Write Phase: Write to both SQLite and PostgreSQL with SQLite as source of truth
- Cutover: Switch reads to PostgreSQL, validate consistency
- Finalize: Remove SQLite dependency
The codebase abstracts database operations through the pkg/db interface, allowing backend swaps without rewriting business logic.
High Availability Considerations
For HA deployments:
- Stateless Design: All session state in database; instances are interchangeable
- Health Checks:
GET /.well-known/openid-configurationas liveness probe - Graceful Shutdown: SIGTERM handling ensures in-flight requests complete
- Database Locking: SQLite WAL mode supports concurrent readers; single writer sufficient for typical IdP workloads
Admin UI
Autentico includes a built-in admin dashboard served at /admin/. It requires an admin user account to log in.
Building the Admin UI
The admin UI is a React application embedded into the Go binary at build time. To build it:
# Build the admin UI and copy it into the Go embed directory
make admin-ui-build
# Or build everything (admin UI + Go binary) in one step
make build-all
After building, the admin UI is available at http://localhost:9999/admin/ when the server is running.
Development Mode
For frontend development with hot-reload:
# Start the Go server
make run
# In another terminal, start the Vite dev server
cd admin-ui && pnpm dev
The dev server runs at http://localhost:5173/admin/ and proxies API requests to the Go server on port 9999.
Testing
Autentico maintains comprehensive test coverage with 464+ test functions across unit, integration, and end-to-end tests.
Test Coverage
| Package | Coverage | Focus Area |
|---|---|---|
pkg/trusteddevice |
96.9% | Device fingerprinting |
pkg/jwtutil |
95.7% | JWT validation |
pkg/middleware |
91.0% | Security middleware |
pkg/auth_code |
90.9% | Authorization codes |
pkg/introspect |
89.4% | Token introspection |
pkg/cleanup |
88.9% | Data retention |
pkg/utils |
87.8% | Core utilities |
pkg/idpsession |
86.2% | Session management |
pkg/user |
85.8% | User management |
pkg/userinfo |
84.6% | User Info endpoint |
pkg/session |
84.3% | Session lifecycle |
pkg/token |
83.5% | Token handling |
pkg/client |
80.2% | Client registration |
pkg/signup |
78.2% | User registration |
pkg/authorize |
77.4% | Authorization flow |
pkg/key |
76.7% | Key management |
pkg/login |
76.7% | Authentication logic |
pkg/config |
76.0% | Configuration |
pkg/db |
71.7% | Database layer |
pkg/onboarding |
69.8% | Initial setup flow |
pkg/appsettings |
64.9% | Runtime settings |
pkg/passkey |
52.9% | WebAuthn authentication |
pkg/mfa |
44.1% | Multi-factor auth |
Running Tests
# Run all tests with coverage
make test
# Or: go test -p 1 -v ./...
# Generate coverage report
go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.html
# Run specific test suites
go test ./pkg/token/... -v # Token handling tests
go test ./tests/e2e/... -v # End-to-end integration tests
go test ./pkg/middleware/... -v # Security middleware tests
Test Categories
Unit Tests (280+ tests): Comprehensive coverage of individual components
- Handler tests: API endpoint behavior, error handling, validation
- Model tests: Data structure validation, serialization/deserialization
- Service tests: Business logic, authentication flows
- Utility tests: Helper functions, middleware components
Integration Tests (40+ tests): Cross-component functionality
- Authorization flow: Complete OAuth2/OIDC workflows
- Token lifecycle: Issuance, refresh, revocation, introspection
- Client authentication: Multiple auth methods and grant types
- Session management: Login, logout, idle timeout handling
End-to-End Tests (16+ tests): Full system workflows
- Authentication flows: Real browser-like interactions
- Token exchanges: Complete authorization code flow
- Security validations: CSRF, CORS, input validation
- Performance tests: Load testing critical endpoints
Test Quality Assurance
Tests cover IdP-critical functionality including:
- Security: Token signing, validation, CSRF protection, input sanitization
- Standards Compliance: OAuth2/OIDC specification adherence
- Error Handling: Graceful degradation, proper error responses
- Edge Cases: Expired tokens, invalid inputs, malformed requests
- Performance: Response times, memory usage, concurrent access
Troubleshooting & Operations
Common Operational Issues
Token Validation Failures
# Verify JWK Set is accessible
curl http://localhost:9999/oauth2/certs
# Check private key permissions
ls -la ./db/private_key.pem # Should be 600
# Validate token signature locally
# Use jwt.io or jwt-cli to decode and verify against public key
Database Lock Timeouts
# Check for long-running transactions
sqlite3 /data/autentico.db "PRAGMA wal_checkpoint(FULL);"
# Verify WAL mode is enabled
sqlite3 /data/autentico.db "PRAGMA journal_mode;"
# Expected output: wal
Session Exhaustion
- Monitor active session count in database
- Default idle timeout: 30 minutes
- Implement session cleanup cron:
DELETE FROM sessions WHERE updated_at < datetime('now', '-30 minutes')
Memory Leaks
- Watch RSS over time:
ps aux | grep autentico - Check for orphaned goroutines: enable pprof endpoint in production builds
- Expected steady-state: 45-120MB depending on active sessions
Performance Tuning
SQLite Optimizations:
-- Enable WAL mode for better concurrency
PRAGMA journal_mode=WAL;
-- Increase cache size (default 2MB, increase to 64MB)
PRAGMA cache_size=-64000;
-- Synchronous mode for performance vs. durability tradeoff
PRAGMA synchronous=NORMAL; -- FULL for maximum durability
Go Runtime Tuning:
# In containerized environments, explicitly set GOMAXPROCS to match CPU limits
# Go may not auto-detect container CPU quotas correctly
GOMAXPROCS=4 ./autentico start
# Adjust GC target percentage for memory/CPU tradeoff
GOGC=200 ./autentico start # Less frequent GC, higher memory usage, lower CPU overhead
# Note: SQLite write serialization is the bottleneck, not CPU parallelism
# GOMAXPROCS helps with concurrent request handling and cryptographic operations,
# but won't increase write throughput beyond SQLite's single-writer constraint
Security Incident Response
Compromised Client Secret:
- Rotate secret via
PUT /oauth2/register/{client_id} - Revoke all tokens for affected client:
DELETE FROM tokens WHERE client_id = ? - Force re-authentication:
DELETE FROM sessions WHERE client_id = ?
Suspected Token Leakage:
- Rotate signing keys (requires downtime or dual-key validation period)
- Revoke affected tokens via
/oauth2/revoke - Monitor for unusual token introspection patterns
Brute Force Attack:
- Rate limiting implemented at reverse proxy layer (recommended)
- Monitor failed login attempts:
grep 'authentication failed' /var/log/autentico.log | wc -l - Consider CAPTCHA integration for repeated failures
Contributing
Contributions are welcome and appreciated! Please follow these general guidelines:
- Fork the repository on GitHub.
- Create a new feature branch for your changes (e.g.,
git checkout -b feature/my-new-feature). - Make your changes and ensure they adhere to Go best practices and project style.
- Add or update tests for your changes. Ensure all tests pass (
make test). - Commit your changes with clear and descriptive commit messages.
- Push your branch to your fork (
git push origin feature/my-new-feature). - Submit a pull request to the main Autentico repository.
Please open an issue to discuss significant changes or new features before starting work.
License
This project is licensed under the MIT License. See the LICENSE file in the repository for the full license text.
Documentation
¶
There is no documentation for this package.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package docs Code generated by swaggo/swag.
|
Package docs Code generated by swaggo/swag. |
|
pkg
|
|
|
tests
|
|