How API Authentication and Rate Limiting Work in Uptime Kuma
Uptime Kuma protects its HTTP API using API keys (or basic auth fallback) and enforces per-endpoint rate limits via token-bucket limiters to prevent abuse.
The louislam/uptime-kuma repository implements a dual-layer security model that combines flexible authentication with aggressive throttling. Understanding how server/auth.js and server/rate-limiter.js interact is essential for integrating monitoring data safely into your infrastructure. This article explains the exact mechanisms governing credential verification and request throttling as implemented in the source code.
API Authentication Architecture
Authentication Flow and Middleware
All API routes in Uptime Kuma are protected by the apiAuth middleware defined in server/auth.js. The middleware first consults runtime settings to determine which authentication mode is active:
- Auth disabled mode – When
Settings.get("disableAuth")returnstrue, the middleware bypasses all checks entirely (useful for isolated testing environments). - API key mode – When
apiKeysEnabledistrue, the system invokesapiAuthorizer(lines 79-96 inserver/auth.js). - Basic auth fallback – If API keys are disabled, the system falls back to
userAuthorizer(lines 106-122 inserver/auth.js) for traditional username/password validation.
Both authorizers integrate with the rate limiting system before performing credential verification. If the respective rate limiter denies the request, authentication aborts immediately and logs a warning.
API Key Format and Verification
Uptime Kuma API keys follow a strict format: uk<ID>_<secret>. The prefix uk identifies the key type, the numeric segment between the prefix and the first underscore represents the database ID, and the trailing segment is the clear-text secret users must protect.
The verification logic resides in verifyAPIKey (lines 41-63 in server/auth.js). This function:
- Extracts the ID from the key format
- Queries the
api_keytable for the stored bcrypt hash - Validates the key's expiry date and active status
- Compares the supplied clear-text secret against the stored hash using
passwordHash
When authentication succeeds, the request proceeds to the route handler. On failure, the server returns 401 Unauthorized. Notably, rate limiter tokens are not consumed for failed API key validations—only successful checks decrement the bucket.
Basic Auth Fallback
When API keys are disabled, userAuthorizer handles credential validation using the same HTTP Basic Auth mechanism but validates against user account passwords stored in the database. This path uses loginRateLimiter rather than apiRateLimiter, applying stricter throttling appropriate for interactive login attempts.
Rate Limiting Implementation
Token Bucket Configuration
Uptime Kuma leverages the limiter NPM package to implement token-bucket rate limiting. The server/rate-limiter.js file instantiates three independent limiters wrapped in a custom KumaRateLimiter class that logs remaining tokens via its pass() method (lines 25-38).
Each limiter maintains a token count that decrements with every permitted request. When the count goes negative, the limiter returns false and the calling authorizer rejects the request.
Rate Limit Thresholds
The system enforces distinct thresholds for different authentication surfaces:
apiRateLimiter: 60 requests per minute for API key authentication (apiAuthorizer)loginRateLimiter: 20 requests per minute for username/password login attempts (userAuthorizer)twoFaRateLimiter: 30 requests per minute for two-factor authentication verification (handled in2fa.js)
These limits apply before credential verification occurs, protecting the bcrypt hashing operations from brute-force load.
Runtime Configuration Settings
Authentication behavior is controlled through the Settings class in server/settings.js, which provides a cached key/value store with a 60-second TTL:
disableAuth: When set totrue, all authentication checks are skipped across the entire applicationapiKeysEnabled: Toggles between API key mode and traditional basic authentication
Both settings persist in the setting database table and are queried by apiAuth on every request to determine which authorization path to execute.
Practical Usage Examples
Creating API Keys
Generate keys through the web interface:
- Log in to the Uptime Kuma dashboard
- Navigate to Settings → API Keys
- Click Add New Key to generate a key like
uk12_7e4a9b... - Copy the key immediately—the clear-text secret cannot be retrieved later
The UI stores only the bcrypt hash in the api_key table via the socket handler in server/socket-handlers/api-key-socket-handler.js.
Authenticating Requests with cURL
Pass the API key as the password in HTTP Basic Auth. The username field is ignored but conventionally set to api:
curl -u api:'uk12_7e4a9b...' \
-H "Accept: application/json" \
https://uptime.kuma.example/api/monitors
For automated scripts, include the key in the Authorization header:
curl -H "Authorization: Basic $(echo -n 'api:uk12_7e4a9b...' | base64)" \
https://uptime.kuma.example/api/monitors
Handling Rate Limit Responses
When exceeding the 60 requests/minute threshold for API keys, the apiRateLimiter causes apiAuthorizer to return 401 Unauthorized (or 429 Too Many Requests in some edge cases). Test rate limiting behavior with a loop:
for i in {1..65}; do
curl -s -o /dev/null -w "%{http_code}\n" \
-u api:'uk12_7e4a9b...' \
https://uptime.kuma.example/api/monitors
done
Requests 61 through 65 will fail with authentication errors once the token bucket empties.
Summary
- API authentication in Uptime Kuma uses the
apiAuthmiddleware to choose between API key verification (apiAuthorizer) and basic auth (userAuthorizer) based on theapiKeysEnabledsetting. - API keys follow the format
uk<ID>_<secret>and are verified against bcrypt hashes stored in the database viaverifyAPIKeyinserver/auth.js. - Rate limiting employs token-bucket limiters (
apiRateLimiter,loginRateLimiter,twoFaRateLimiter) that enforce thresholds of 60, 20, and 30 requests per minute respectively. - Runtime settings (
disableAuth,apiKeysEnabled) are cached for 60 seconds viaserver/settings.jsto minimize database queries on every request. - Security sequencing checks rate limits before performing expensive bcrypt hash comparisons, preventing CPU exhaustion attacks.
Frequently Asked Questions
What authentication methods does Uptime Kuma support?
Uptime Kuma supports two primary authentication methods: API keys (recommended for automation) and HTTP Basic Auth using username and password credentials. The active method is determined by the apiKeysEnabled runtime setting stored in server/settings.js. When disableAuth is enabled, all authentication is bypassed for testing purposes.
How does the API key format work in Uptime Kuma?
All API keys use the format uk<ID>_<secret>, where the numeric ID identifies the database record and the secret portion is user-provided. The server extracts the ID from between the uk prefix and the first underscore, then verifies the secret against a bcrypt hash stored in the api_key table using the verifyAPIKey function in server/auth.js.
What are the rate limits for API requests?
Uptime Kuma enforces three distinct rate limits via server/rate-limiter.js: 60 requests per minute for API key authentication (apiRateLimiter), 20 requests per minute for username/password login attempts (loginRateLimiter), and 30 requests per minute for 2FA verification (twoFaRateLimiter). These limits apply before credential validation to protect against brute-force attacks.
How can I disable authentication for testing?
Set the disableAuth setting to true via the runtime configuration in server/settings.js. When this flag is active, the apiAuth middleware in server/auth.js bypasses all credential checks, allowing unrestricted access to the API. This should only be used in isolated testing environments and never in production deployments.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →