Skip to main content
Guides

Choosing data-plane auth: API key vs JWT vs mTLS

When to use API keys, JWT tokens, or mutual TLS for your RestWard APIs, with rotation guidance and configuration details.

RestWard supports three authentication methods for your generated APIs. Each method suits different use cases, security requirements, and operational patterns. This guide helps you choose the right method for your scenario and explains how to configure and rotate credentials for each.

Authentication methods overview

Method Best for Credential format How it works Rotation complexity
API Key Server-to-server, internal services, simple integrations rw_... string (32-byte random) Sent in X-API-Key header; matched against stored hash Single click in dashboard
JWT User-delegated access, tokens from your IdP (Entra ID, Auth0, etc.) Bearer token (JWT) Sent in Authorization: Bearer header; validated against JWKS or shared key Automatic via JWKS endpoint; manual for shared keys
mTLS High-assurance machine identity, zero-trust environments X.509 client certificate Sent via TLS client cert (or X-Forwarded-Client-Cert header from proxy); validated against CA or fingerprint CA/fingerprint rollover in dashboard

Key insight: All three methods can coexist on the same API. Enable the ones your consumers need in Auth & Keys for your organization. A request is authenticated by the first enabled method that presents a valid credential.

API Key authentication

API keys are the simplest authentication method. They are ideal for server-to-server communication, internal services, CI/CD pipelines, and any scenario where you control both the producer and consumer of the API.

Who it suits

  • Internal microservices communicating with each other
  • CI/CD pipelines that need programmatic access
  • Partner integrations where you issue and manage keys centrally
  • Simple mobile/desktop apps where embedding a key is acceptable
  • Machine-to-machine scenarios without user context

Dashboard configuration

  1. Go to Auth & Keys in your organization
  2. Ensure API Key method is enabled (toggle on if needed)
  3. Click New API Key
  4. Enter a Key Name (e.g., "Production Mobile App", "CI Pipeline")
  5. Select the API this key can access
  6. Choose the Role: Read Only, Read & Write, or Admin
  7. Optionally set Allowed IP addresses (one per line, supports CIDR)
  8. Optionally set Rate Limit Per Minute (defaults to 60, clamped to plan ceiling)
  9. Click Create Key
  10. Copy the key immediately — it displays only once in plaintext

The key appears in your API Keys table as Active. You can view its usage statistics, last used time, and manage it from there.

Rotation

Rotating an API key generates a new key string while keeping the same name, API assignment, role, and IP allowlist. The old key is revoked immediately in the platform. Running APIs stop accepting it on their next key reload, which happens within 30 seconds (configurable via EndpointConfig:RefreshSeconds).

To rotate a key:

  1. In the API Keys table, find the active key
  2. Click Rotate key (refresh icon)
  3. The new key is shown once in a success banner at the top of the page
  4. Copy it and update your consumer's configuration
  5. Dismiss the banner

What happens to the old key: It is immediately revoked in the database. The old key string no longer authenticates once running APIs reload their keys (within ~30 seconds). The new key inherits the old key's name, API assignment, role, and IP allowlist. The rate limit is re-clamped to the current plan ceiling at rotation time, so a key rotated after a plan downgrade comes back with the new, lower limit rather than keeping the old, higher value.

Per-method rate limits and IP allowlists

  • Rate limit: Each API key has its own RateLimitPerMinute value (default: 60). This is clamped to your plan's MaxKeyRateLimitPerMinute ceiling.
  • IP allowlist: Each key can have its own allowed IP ranges. A request from an address not in the list receives 403 Forbidden with the message IP address not allowed.

See API keys & tenant API auth for detailed key management.

JWT authentication

JWT (JSON Web Token) authentication validates bearer tokens issued by your identity provider. This is ideal when your API consumers already have tokens from your organization's IdP, or when you want to delegate authentication to a trusted third party.

Who it suits

  • User-delegated access: Your users obtain tokens from your IdP (e.g., Entra ID) and use them to call your API
  • Service-to-service with existing token infrastructure
  • Multi-tenant SaaS where each tenant brings their own IdP
  • Short-lived credentials with automatic expiration

Dashboard configuration

  1. Go to Auth & Keys in your organization
  2. Ensure JWT Bearer method is enabled
  3. Click Configure on the JWT Bearer card
  4. Enter the Issuer (required) — the expected iss claim in tokens (e.g., https://login.microsoftonline.com/your-tenant-id/v2.0)
  5. Optionally enter Audience — when set, tokens must contain this value in their aud claim
  6. Choose validation approach:
    • JWKS URI (recommended): Enter the OpenID Connect discovery endpoint or direct JWKS endpoint. Keys are fetched and cached automatically.
    • Signing Key: Enter a shared symmetric key for HMAC-signed tokens (HS256, HS384, HS512)
  7. Optionally set Role Claim — the claim name whose value maps to an API role (Admin, ReadWrite, ReadOnly)
  8. Optionally set Default Scope — the role granted when no role claim is present or matched
  9. Optionally set Rate Limit Per Minute for JWT callers (defaults to 60)
  10. Optionally set Allowed IP addresses for all JWT tokens
  11. Click Save

Token requirements

  • Tokens must have exactly three dot-separated parts (header.payload.signature)
  • Maximum token length: 16,384 characters
  • For JWKS validation: tokens must specify an alg (algorithm) that matches the key type
  • For symmetric validation: tokens must use an HS* algorithm (HS256, HS384, HS512)
  • The iss claim must match the configured issuer exactly (ordinal comparison)
  • If audience is configured, the token's aud must contain that value

Rotation

With JWKS endpoint (asymmetric):

JWT signing keys are automatically rotated when the IdP publishes new keys to its JWKS endpoint. RestWard:

  1. Caches the JWKS configuration per issuer endpoint (static ConcurrentDictionary in JwtAuthenticator)
  2. Uses ConfigurationManager<OpenIdConnectConfiguration> from Microsoft.IdentityModel which auto-refreshes keys
  3. When a token arrives with an unknown kid (key ID), requests a refresh (at most once per minute per issuer)
  4. Accepts tokens signed with any key in the current JWKS set

JWKS refresh behavior: An unknown kid triggers a single refresh attempt. If the refresh fails or the kid is still not found, the token is rejected with reason unknown_kid. If the JWKS endpoint is completely unavailable, authentication returns 503 Service Unavailable (not counted against rate limits).

With shared signing key (symmetric):

You must manually update the Signing Key in the dashboard when you rotate your shared secret. There is no automatic rotation — the old key continues to work until you replace it, at which point tokens signed with the old key are immediately rejected.

Best practice: Use asymmetric JWKS validation whenever possible. It enables automatic key rotation and is more secure (no shared secrets to manage).

Per-method rate limits and IP allowlists

  • Rate limit: JWT callers share a configured RateLimitPerMinute (default: 60). This applies per token subject.
  • IP allowlist: All JWT tokens for this method can be restricted to specific IP ranges. A request from an address not in the list receives 403 Forbidden.

mTLS authentication

Mutual TLS (mTLS) authentication validates client certificates presented during the TLS handshake. This provides the highest level of assurance that the caller is who they claim to be, as it relies on cryptographic proof of identity at the transport layer.

Who it suits

  • High-security environments requiring certificate-based authentication
  • Zero-trust architectures where every request must prove identity
  • Machine-to-machine in regulated industries (finance, healthcare)
  • Internal services in a PKI-managed infrastructure

Dashboard configuration

  1. Go to Auth & Keys in your organization
  2. Ensure Mutual TLS method is enabled
  3. Click Configure on the Mutual TLS card
  4. Configure at least one acceptance criterion:
    • Trusted CA PEM: The CA certificate (in PEM format) that issued the client certificates. All certificates that chain to this CA are accepted.
    • Allowed Fingerprints: SHA-256 thumbprints of specific client certificates. Enter one per line.
    • Allowed Subjects: Distinguished Names or Common Names from the certificate's subject. Requires a Trusted CA — subjects are only checked on certificates that chain to the configured CA.
  5. Optionally set Default Scope — the role granted to authenticated clients
  6. Optionally set Rate Limit Per Minute for mTLS callers (defaults to 60)
  7. Optionally set Allowed IP addresses for all mTLS connections
  8. Click Save

Validation rule: You must configure at least one criterion. If you use Allowed Subjects, you must also provide a Trusted CA. A configuration with subjects but no CA is refused on save.

How it works

RestWard's mTLS implementation handles two deployment topologies:

Proxy-terminated TLS (current production):

On the demo and production deployments, Caddy terminates TLS for the API hostnames under *.run.restward.tech and reverse-proxies to Kestrel on a loopback port. In this topology:

  1. Caddy is configured to request client certificates (client_auth mode request)
  2. Caddy forwards the client certificate to the backend in the X-Forwarded-Client-Cert header
  3. The header value is a single-line base64-DER encoding (multi-line PEM won't work in HTTP headers)
  4. MtlsAuthenticator reads this header first

See deploy/hetzner/conf.d/restward-app.caddy for the Caddy configuration.

Direct Kestrel TLS (future):

For direct Kestrel deployments where Kestrel performs the TLS handshake, the authenticator falls back to reading HttpContext.Connection.ClientCertificate.

Certificate validation

A presented certificate is accepted when:

  1. It is within its validity window (not before NotBefore, not after NotAfter)
  2. AND it matches at least one configured criterion:
    • Its SHA-256 thumbprint is in the Allowed Fingerprints list, OR
    • It chains to the configured Trusted CA AND (if Allowed Subjects are configured) its subject DN/CN/SAN is in the list

Subject matching: A subject match alone is never sufficient. Subjects are only checked when the certificate chains to the configured CA. This prevents spoofing via self-signed certificates with arbitrary subjects.

Rotation

CA rollover:

To rotate your CA certificate:

  1. Generate a new CA certificate
  2. Issue new client certificates from the new CA
  3. In the dashboard, add the new CA PEM to the Trusted CA PEM field (you can temporarily have both old and new)
  4. Deploy the new client certificates to your consumers
  5. Once all consumers are using the new CA, remove the old CA PEM

Grace period: During the transition, both old and new CA certificates are accepted. This allows for gradual rollout without downtime.

Fingerprint rollover:

To rotate client certificates identified by fingerprint:

  1. Generate new client certificates
  2. Add the new SHA-256 thumbprints to the Allowed Fingerprints list
  3. Deploy the new certificates to your consumers
  4. Remove the old fingerprints once all consumers have updated

Thumbprint format: SHA-256 hash of the certificate's DER encoding, represented as a lowercase hexadecimal string (no 0x prefix, no separators).

Subject rollover:

If you use Allowed Subjects with a CA:

  1. Update the Allowed Subjects list to include new subject DNs
  2. Deploy new client certificates with the new subjects
  3. Remove old subjects once all consumers have updated

Important: Subject-based validation always requires a Trusted CA. The subject is only checked after the certificate chain is verified.

Per-method rate limits and IP allowlists

  • Rate limit: mTLS callers share a configured RateLimitPerMinute (default: 60). This applies per client certificate.
  • IP allowlist: All mTLS connections for this method can be restricted to specific IP ranges. A request from an address not in the list receives 403 Forbidden.

Decision table

Use this table to quickly determine which authentication method fits your scenario:

Scenario API Key JWT mTLS Notes
Internal service-to-service ✅ Best ⚠️ Good ⚠️ Good API keys simplest; mTLS for highest assurance
User-delegated access (your IdP) ❌ No ✅ Best ❌ No JWT carries user identity from IdP
Partner integration (you issue keys) ✅ Best ⚠️ Possible ⚠️ Possible API keys simplest to manage
High-security zero-trust ⚠️ Possible ⚠️ Possible ✅ Best mTLS provides transport-level identity
Short-lived credentials ❌ No ✅ Best ⚠️ Possible JWT tokens have built-in expiration
Automatic rotation ❌ Manual ✅ JWKS ⚠️ Manual JWKS enables automatic key rotation
No infrastructure changes ✅ Best ✅ Best ❌ Requires TLS config mTLS needs certificate deployment
Fine-grained IP restrictions ✅ Per key ✅ Per method ✅ Per method API keys support per-key IP lists
Rate limiting ✅ Per key ✅ Per subject ✅ Per cert All methods support rate limits
Existing token infrastructure ❌ No ✅ Best ❌ No JWT integrates with your IdP
PKI-managed environment ⚠️ Possible ⚠️ Possible ✅ Best mTLS leverages existing PKI

Troubleshooting

401 Unauthorized vs 403 Forbidden

Understanding the difference helps you diagnose authentication issues:

Status Meaning Common causes
401 Unauthorized Authentication failed — no valid credential presented Expired key/token/certificate; revoked key; wrong issuer; invalid signature; malformed credential; key used for wrong API
403 Forbidden Authentication succeeded but access denied IP address not in allowlist; insufficient role/permissions for the operation

API Key specific:

  • 401: Key not found, key revoked, or key hash mismatch
  • 403: IP address not in the key's allowed IP ranges; key used for a different API (wrong API configuration)

JWT specific:

  • 401: Token malformed, wrong issuer, invalid signature, unknown kid (with JWKS), token expired
  • 503: JWKS endpoint could not be fetched (reason: jwks_unavailable)
  • 403: IP address not in the method's allowed IP ranges

mTLS specific:

  • 401: No client certificate presented, certificate outside validity window, certificate doesn't match any criterion
  • 403: IP address not in the method's allowed IP ranges

Common issues and solutions

"API key not working after rotation"

  • The old key is immediately invalid. Ensure you've updated your consumer with the new key.
  • Check that the new key was copied correctly (no truncation, no extra spaces).

"JWT tokens rejected with unknown_kid"

  • The token was signed with a key not in the current JWKS set.
  • This triggers a JWKS refresh (once per minute per issuer).
  • Verify your IdP has published the new signing keys to its JWKS endpoint.
  • Check that the token's kid header matches a key in the JWKS.

"JWT tokens rejected with wrong_issuer"

  • The token's iss claim doesn't match the configured issuer exactly (ordinal comparison).
  • Verify the issuer URL in your dashboard matches the iss claim in your tokens exactly.

"mTLS certificate rejected"

  • Certificate is outside its validity window: check NotBefore and NotAfter.
  • Certificate doesn't chain to the configured CA: verify the CA PEM is correct.
  • Certificate fingerprint doesn't match: recompute the SHA-256 thumbprint of the DER encoding.
  • Subject doesn't match: ensure the certificate's subject is in the Allowed Subjects list AND it chains to the CA.

"IP address not allowed" (403)

  • The client's IP address is not in the allowlist for the key or method.
  • Remember: the address compared is what the platform's reverse proxy appends to X-Forwarded-For, not the direct connection address.
  • For consumers behind NAT/proxy, this is the gateway's public address.
  • Clear the allowlist field to remove the restriction entirely.

"Rate limit exceeded" (429)

  • You've exceeded the configured rate limit for the key, token subject, or certificate.
  • Check the X-RateLimit-Scope header to see which limit was hit.
  • Wait for the Retry-After period before retrying.
  • Consider increasing the rate limit or implementing client-side backoff.

Verification checklist

Before deploying, verify your authentication configuration:

  • The authentication method is enabled in Auth & Keys
  • For JWT: Issuer is configured correctly; JWKS endpoint is accessible (test with curl)
  • For mTLS: At least one acceptance criterion is configured; CA PEM is valid
  • For API keys: Keys are created and assigned to the correct API
  • IP allowlists (if used) include the actual client addresses (consider NAT/proxy)
  • Rate limits are set appropriately for each method
  • You've tested authentication with a real request (not just dashboard configuration)

See also

Reconnecting to server...

Please wait while we restore your connection

Connection lost

Retrying in seconds...

Unable to reconnect

The server connection has been lost.
You may need to log in again.

Session Paused

The server has temporarily paused your session.

Session Expired

Your session could not be resumed.
Please reload the page to continue.