Overview #
- Improve the security of your tokens with ChaCha20 + HMAC-BLAKE3.
- Accelerate backend development — auth handled at the proxy layer.
- Ultra-fast token verification 🚀 with LMDB + memory caching.
- Written in Rust 🦀 for memory safety and performance.
- Native SSO via GPG key export — multiple instances share token encryption.
Installation #
Auto Install via cURL
# Latest stable version $ curl -fsSL https://proxyauth.app/sh/install | bash # Latest beta version $ curl -fsSL https://proxyauth.app/sh/beta-install | bash # Specific version (must be >= 0.5.6) $ curl -fsSL https://proxyauth.app/sh/install@0.7.0 | bash # Check service status $ sudo systemctl status proxyauth
Docker Installation
# Clone the Docker project $ git clone https://git.proxyauth.app/ProxyAuth/Docker ProxyAuth && cd ProxyAuth/latest # Set correct permissions (proxyauth user inside container) $ sudo chown 1000:1000 config/config.json config/routes.yml # Build and start $ docker compose build && docker compose up -d
Uninstall #
# Remove ProxyAuth, users, config and all files $ curl -fsSL https://proxyauth.app/sh/uninstall | bash
CLI Commands #
proxyauth stats
# Show stats via cURL (admin token is in /etc/proxyauth/config/config.json) $ curl -k -H 'X-Auth-Token: [YOUR_TOKEN_ADMIN]' https://127.0.0.1:8080/adm/stats
[
{
"user": "admin",
"tokens": [
{
"token_id": "QzK=8S*lx9A@gebUZBB%m$a5+uo@lPx*F+d2QdCssbA+sl(R",
"count": 1,
"delivery_at": "2025-05-28T18:18:02.251295314Z",
"expire_at": "2025-05-28T19:17:47Z"
}
]
}
]Server Configuration #
/etc/proxyauth/config/config.json (versions ≥ 0.5.6).{
"token_expiry_seconds": 3600,
"secret": "supersecretvalue",
"host": "0.0.0.0",
"port": 8080,
"worker": 4,
"num_instances": 2,
"login_via_otp": false,
"tls": true,
"stats": true,
"max_idle_per_host": 200,
"timezone": "Europe/Paris",
"redis": "redis://redis_server:6379",
"session_cookie": false,
"max_age_session_cookie": 3600,
"cors_origins": [
"https://127.0.0.1",
"https://demo.proxyauth.app"
],
"log": {
"type": "local"
},
"ratelimit_auth": {
"burst": 10,
"block_delay": 500,
"requests_per_second": 10
},
"ratelimit_proxy": {
"burst": 10,
"block_delay": 500,
"requests_per_second": 10
},
"users": [
{
"username": "admin",
"password": "$argon2id$v=19$m=19456,t=2...",
"allow": ["192.168.1.0/24", "172.16.54.2"],
"roles": ["Administrator", "read", "write"]
},
{
"username": "alice",
"password": "$argon2id$v=19$m=19456,t=2...",
"roles": ["User", "read", "write"]
}
]
}
Configuration Reference
3600unset0.0.0.080804num_instances × worker2true | falsefalsetrue | falsefalseEurope/Paris UTC America/New_YorkEurope/ParisSet-Cookie header after successful authentication. Allows seamless frontend integration without manual token handling.Secure HttpOnly SameSite=Strictfalsesession_cookie is enabled.86400 = 24 hours3600 (1 hour)Origin header.["https://127.0.0.1", "https://demo.proxyauth.app"][] (CORS disabled)"redis://redis_server:6379"unset50GET /adm/stats | proxyauth stats CLIfalse{"type":"local"}Local logging only, no remote output.{"type":"loki","host":"127.0.0.1:1234"}Send structured logs to Grafana Loki.{"type":"http","max_writes_log":10000}Expose logs via HTTP endpoint.{"type":"local"}/auth authentication endpoint.0 to disable.disabledratelimit_auth.0 to disable.disabled/auth route to obtain a token./auth route.["192.168.1.0/24", "10.0.0.1"]x-user-roles HTTP header on each proxied request. Example: ["Administrator", "write", "read"]Routes Configuration #
File: /etc/proxyauth/config/routes.yml
routes: # Public route — no token required, path locked to exact target - prefix: "/redoc" target: "http://127.0.0.1:8000/redoc" secure: false secure_path: true filters: default_allow: false allow: - field: method pattern: "^GET$" - field: path pattern: "^/redoc(?:/.*)?$" # Load-balanced route with weighted backends - prefix: "/api_test/openapi.json" target: "http://localhost:8000/api_test/openapi.json" secure: false backends: - url: "http://localhost:8001/api_test/openapi.json" weight: 1 - url: "http://localhost:8002/api_test/openapi.json" weight: 2 # Secured route — specific users + method/path/query filters - prefix: "/api_test_default" target: "http://localhost:8000/api_test_default" username: ["admin", "alice1", "alice15", "alice30"] filters: default_allow: false allow: - field: method pattern: "^(?:GET|POST)$" - field: path pattern: "^/api_test_default(?:/.*)?$" # Forward through another proxy, with header ACL - prefix: "/api_test_proxy" target: "http://localhost:8000/api_test_proxy" username: ["admin", "alice1"] proxy: true proxy_config: "http://127.0.0.1:8888" filters: default_allow: false allow: - field: header name: "^X-API-Key$" pattern: "^[0-9a-f]{32}$" # mTLS forwarding with PKCS#12 certificate + JSON body filter - prefix: "/api_test_cert" target: "https://localhost:8000/api_test_cert" username: ["admin"] cert: file: "certificat.p12" password: "1234" filters: default_allow: false allow: - field: method pattern: "^POST$" - field: body_json key: status pattern: "^active$"
Route Options Reference
truetarget URL, ignoring the request sub-path. Prevents sub-path traversal and external redirects.http://localhost:8000/api/endpoint→
/api/endpoint/other still forwarded to http://localhost:8000/api/endpointfalse["admin", "alice"]unset (all users allowed)true | falsefalsehttp://host:portunset.p12 certificate file. Example: certificate.p12unsetDefines allow/deny rules evaluated before forwarding. All allow conditions must match for the request to pass. A matching deny rule blocks immediately.
true = allow by default | false = deny by defaultfieldmethod
Matches the HTTP method (GET, POST, PUT, DELETE…)
^GET$ — allow only GET requests
path
Matches the request URI path (without query string)
^/api/v[0-9]+/users$
header
Matches a specific HTTP request header
name: ^X-API-Key$ pattern: ^[0-9a-f]{32}$
query
Matches a URL query string parameter
name: ^token$ pattern: ^[0-9a-f-]{36}$
body_raw
Matches the raw request body as plain text or binary
(?i)DROP\s+TABLE — detect SQL injection attempts
body_json
Matches a specific value inside a JSON request body
key: status pattern: ^active$
Keystore Export / Import #
Share cryptographic keys across multiple ProxyAuth instances for multi-service SSO.
$ sudo proxyauth sync export # Output: Key export successful # Two files are created in the current directory: $ ls -al -rw-r--r-- 1 root root 488 14 juin 18:55 data.pgp -rw-r--r-- 1 root root 1885 14 juin 18:55 key.asc
# Create the import directory
$ mkdir -p /etc/proxyauth/import
# Set permissions for the proxyauth user
$ sudo chown proxyauth:proxyauth \
/etc/proxyauth/import/data.gpg \
/etc/proxyauth/import/key.ascOnce keys are imported, both instances share the same encryption — tokens are valid across services.
Credential Route #
Authenticate and receive an encrypted token.
Content-Type: application/json{"username": "<string>", "password": "<string>"}ratelimit_auth# Default: admin / admin123 — change in config.json
$ curl -k -X POST https://127.0.0.1:8080/auth \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "admin123"}'HTTP/1.1 200 OK
content-type: application/json
x-ratelimit-remaining: 4
x-ratelimit-limit: 5
{
"expires_at": "2025-04-27 09:37:05",
"token": "85l19fN5l+DKozxk29xeMtw2PgH/aNnVAgEJLxNo8M7xs..."
}HTTP/1.1 429 Too Many Requests x-ratelimit-remaining: 0 x-ratelimit-limit: 5 x-ratelimit-after: 6 retry-after: 6 Too many requests, retry in 6s
TOTP Mechanism #
Content-Type: application/json{"username": "<string>", "password": "<string>"}$ curl -k -X POST https://127.0.0.1:8080/adm/auth/totp/get \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "admin123"}'{
"otpauth_uri": "otpauth://totp/ProxyAuth%3Aadmin?secret=4DX6B7CVQ...&issuer=ProxyAuth",
"otpkey": "4DX6B7CVQ24LHNIDBENSZI54Q2RTPC7D4AFNRPKHX7VCW3T6IVGQ"
}ppauth-cli (Python)
$ pip install ppauth
$ ppauth-cli registry otp \
--host 127.0.0.1 \
--port 8080 \
--username admin \
--password admin123 \
--no-tls-verifyForward Route #
Authorization: Bearer <your_token>secure: true in routes.yml (default)$ curl -k -X GET https://127.0.0.1:8080/api_test \
-H "Authorization: Bearer YOUR_TOKEN_HERE"Scenario 1 — Valid Token
Scenario 2 — Invalid / Expired Token
Forward via Other Proxy #
proxy: true and set proxy_config in routes.yml.HTTPS / PKCS#12 Forwarding #
Forward requests to HTTPS/TLS services using a client certificate (PKCS#12 / .p12). Configure via the cert key in routes.yml.
HTTPS Forwarding #
Return Block Error #
Applies when session_cookie: true. Errors are embedded in HTML comments for programmatic parsing.
<!-- BEGIN_BLOCK_ERROR -->
<!--
<div id="error_display" class="col-lg-5">
{{ error }}
</div>
-->
<!-- END_BLOCK_ERROR -->Scenario 1 — Valid token: 200/204 — no error block included.
Scenario 2 — Invalid/expired token: 401 — error block included with the actual message replacing {"{{ error }}"}.
CSRF Protection #
Applies when session_cookie: true. ProxyAuth injects CSRF tokens server-side — any {"{{ csrf_token }}"} in proxied HTML is replaced automatically.
HTML Form
<form method="POST" action="/orders/create">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="text" name="item" required>
<button type="submit">Create order</button>
</form>JavaScript (fetch)
// Read the injected token from the DOM
const csrf = document.querySelector('input[name="csrf_token"]')?.value;
// Include it in the request body
const body = new URLSearchParams({ csrf_token: csrf, data: "test" });
fetch("/api/write", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body,
});Logs via Loki #
Integrate with Grafana Loki for real-time log visualization. Add to config.json:
{
"log": {
"type": "loki",
"host": "127.0.0.1:5000"
}
}Sample Grafana dashboard: github.com/ProxyAuth/Grafana
Changelog #
- [ADD]Redis multi-node token sync for full SSO
- [ADD]CSRF token injection and validation
- [ADD]Session cookie support
- [PERF]180,000+ requests/second under load
- [FIX]Update base32 handling
- [CLEAN]Remove unused dependencies
- [FIX]Fix sorted key inside config.json after reboot
- [FIX]Nginx bad Host header returning 400
- [SEC]CVE update: sequoia-opengpg ≥ 2.1, tracing-subscriber ≥ 0.3.20
- [ADD]Auto-reload TLS certificates for external server
- [ADD]~354 tests, ~50% code coverage
- [FIX]Better logs
- [ADD]Route Prefix Reordering: Longest to Shortest Match
- [ADD]Canonicalize URL
- [ADD]ACL route filters
- [ADD]Allow methods in routes.yml
- [ADD]
preserve_prefixin routes.yml - [ADD]
secure_pathin routes.yml
- [FIX]CORS Options for OTP registry
- [ADD]Forward
x-userheader to backends - [ADD]
csrf_tokenvalidate-generate - [ADD]Control cache routes
- [FIX]Fix rules routes
- [ADD]Cookie session
- [ADD]
max_age_session_cookie - [ADD]CORS support
- [FIX]Rate limit behavior
- [MOVE]Timezone to
token::security - [ADD]ProxyAuth now supports auth via
session_tokencookie andAuthorization: Bearer
- [MULTI]Database (multi-instance Docker) to RAM sync every 15 seconds
- [ADD]
x-user-rolesheader injection - [ADD]Initial implementation of token revocation
- [ADD]Option
max_connections - [ADD]Option
pending_connections_limit - [ADD]Option
socket_listen - [ADD]Option
keep_alive - [ADD]Option
client_timeout - [ADD]Option
num_instances - [OPT]XOR Algorithm transform hash (+30% better)
- [SEC]IP restriction per user for authentication (optional)
- [SEC]Change HMAC-SHA256 to HMAC-BLAKE3 (speed ~+50%)
- [PERF]Caching HMAC-BLAKE3 key for better performance
- [PERF]Optimized Ahasher type for CLIENT_POOL / PROXY_POOL
- [ADD]Nix-Shell support
- [ADD]rustfmt edition
- [FIX]Minor timezone issue
- [FIX]Minor deprecated method
.timestamp()
- [ADD]TOTP Login mechanism
- [ADD]Command
--version - [FIX]Logging bug when loading config on startup
- [FIX]Possible disable log on option
- [PERF]Better performance loadbalancer
- [ADD]Export/import keystores for multi-service cryptographic integration
- [SEC]Rewrite all headers from original requests, replace server name
- [ADD]Export build parameters for GPG multi-service integration
- [ADD]New cryptographic build export generated by GPG file
- [ADD]Better proxy logs
- [ADD]Token ID random over timestamp
- [ADD]Reuse client cache
- [ADD]Failover to backup backends if primary route is unreachable
- [ADD]Timezone support when creating tokens
- [ADD]
expire_atanddelivery_atfields in token stats
- [FIX]Design improved, proxy functionality restored
- [FIX]Rate limiting now applied per route and per user
- [CLEAN]Clean all compiler warnings
- [ADD]😅 Sorry for deploying so many versions in such a short time
- [ADD]Download default config from proxyauth.app
- [ADD]Check build version status via proxyauth.app to detect invalid or yanked versions
- [PERF]Complete rewrite of proxy architecture
- [DISABLED]Proxy forwarding via routes.yml (temporarily)
- [DISABLED]Certificate-based forwarding in routes.yml (temporarily)
- [ADD]HTTPS forwarding when valid certificates are present
- [ADD]Disable/Enable/Redirect logs on Loki/local
- [ADD]Disable/Enable stats
- [ADD]Disable/Enable ratelimit
- [PERF]~600k HTTPS requests/sec on server hardware
- [OPT]Optimized configuration
- [ADD]HTTP/2, HTTPS only, auto-generate certs in
/etc/proxyauth/certs/
- [REBUILD]Rebuild all proxy conception
- [BUG]Fix load configuration ratelimit when key is unset or
requests_per_secondsis 0
- [PERF]Improve performance ~1 million requests per second
- [SEC]Rotate random params
- [SEC]Better security hash token ID
- [OPT]Better performance
- [FIX]ratelimit not detecting configuration
- [FIX]Launch cmd
proxyauth statsfor user
- [FIX]cmd cli stats for routes
/adm/stats
- [ADD]Clear project
/adm/stats
- [ADD]Route Admin
/adm/stats - [ADD]New CLI command
proxyauth statsto display token usage statistics - [ADD]Token usage stats per user
- [ADD]Token usage stats per user
- [ADD]Improved rate limit configuration for proxy routes and the
/authendpoint
- [UPDATE]Launching Actix Web with rate limiting. Modes: NO_RATELIMIT_AUTH, NO_RATELIMIT_PROXY, RATELIMIT_GLOBAL_ON/OFF
- [BUG]Default launch now correctly uses HTTPS/TLS
- [FIX]Improved installation script
- [ADD]Clearer explanation of rate limiting (wait time in milliseconds)
- [FIX]Better compatibility with Alpine and other Linux distributions
- [ADD]New
'prepare'command - [ADD]Program now launches as root and creates/uses the
'proxyauth'user to write in/etc/proxyauth
- [ADD]Create configuration file automatically from GitHub repo
- [FIX]Replace host label with app to improve log display in Loki
- [ADD]Integration log for Loki/Grafana
- [ADD]Experimental feature: forward on HTTPS requests
- [BUG]Minor bug over message proxy
- [ADD]Possible config proxy on file routes.yml
- [ADD]Rate limiting over routes
/auth - [ADD]Auto Argon2 for encrypting password in config.json
- [SEC]Improved security and re-checking of factor if it exceeds the defined limit
- [SEC]Use SHA-256 instead of SHA-1
- [SEC]Add HMAC SHA-256 over ChaCha20 AED
- [REFACTO]Moved the utils method into security
- [ADD]Enhanced hash security
- [FIX]Bug with rate limiting when anonymous user makes requests to unsecured routes
- [ADD]Better logging / error handling when token encryption fails — triggers warning log with source IP
- [ADD]Improved log messages
- [ADD]Applied rate limiting only on proxy routes, not on
/refresh_token - [ADD]
ulimitsetting in Docker configuration for better performance
- [ADD]
delay_blocksetting in the config file
- [ADD]Rate limiting per request and per user
- [FIX]Bug related to date handling
- [ADD]Added logging via tracing
- [ADD]Improved user check via index
- [ADD]Improved the
/authroute algorithm - [ADD]Added Dockerfile and docker-compose.yml (built from rust:alpine)
- [BUG]Date checking issue still present
- [ADD]Implemented ChaCha20/SHA1/ROTATE algorithm for token handling
- [ADD]Implemented request forwarding routes
- [ADD]Added configuration files: routes.yml and config.json
- [ADD]Worker execution count handling