prestd has support in JWT Token generation based on two fields (example user and password), being possible to use an existing table from your database to login configuring some parameters in the configuration file (or environment variable), by default this feature is disabled.
- Bearer - RFC 6750, bearer tokens to access OAuth 2.0-protected resources
- Basic - RFC 7617, base64-encoded credentials. More information below
understand more about http authentication see this documentation
JWT middleware is disabled by default in v2+ (jwt.default = false). Set jwt.default = true to require a valid Bearer token on all endpoints except those in the JWT whitelist. See Configuring pREST — JWT for full configuration.
MCP (/_mcp, v2.1.0+) inherits the same JWT and auth stack as REST routes. When auth is enabled, send credentials on every GET and POST to /_mcp. Stdio clients that use the pREST MCP Adapter can pass a bearer token via PREST_MCP_TOKEN.
When jwt.default = true and debug mode is off, you should configure one of the following:
| Setting | Environment variable | Purpose |
|---|---|---|
jwt.key |
PREST_JWT_KEY |
Shared secret for HMAC algorithms — minimum length applies, see below |
jwt.jwks |
PREST_JWT_JWKS |
JSON Web Key Set for asymmetric verification |
jwt.wellknownurl |
PREST_JWT_WELLKNOWNURL |
OpenID Connect well-known URL to fetch JWKS |
In v2+ (#974): if JWT is enabled but no verification material is configured, JWT middleware is auto-disabled with an error log — the server continues to start. When auth.enabled = true without jwt.key, auth is also auto-disabled.
v2.0.0-rc6 tagged binary: the rc6 release refuses to start in the same situations. See v2.0.0-rc6.
Since v2.4.2 (#1017), pREST validates jwt.key against the RFC 7518 minimum for the configured HMAC algorithm at config load. The underlying library (go-jose/v4) enforces these sizes itself; checking at startup surfaces the problem in logs instead of at request time.
jwt.algo |
Minimum jwt.key length |
|---|---|
HS256 — also the default when jwt.algo is unset |
32 bytes |
HS384 |
48 bytes |
HS512 |
64 bytes |
RS*, ES*, PS*, EdDSA |
Not checked — jwt.key is not used as a MAC key |
The check is on the byte length of the raw string, so a 32-character ASCII secret satisfies HS256. Measure yours with printf '%s' "$PREST_JWT_KEY" | wc -c.
{% hint style="danger" %}
An undersized key fails open, not closed. pREST starts normally, discards the key, and disables the features that need it. POST /auth is no longer registered (clients get 404, not 401) and every route wrapped by the auth middleware passes through unauthenticated. With jwt.default = true and no JWKS, the JWT middleware is removed from the stack entirely.
Rotate short secrets before upgrading, and check startup logs for:
level=ERROR msg="jwt.key too short for HMAC algorithm" algo=HS256 got=6 want=32
level=ERROR msg="auth disabled: jwt.key is empty"
{% endhint %}
A configured jwt.jwks or jwt.wellknownurl is unaffected — verification continues against the JWKS even when an undersized HMAC key is discarded.
jwt.algo was accepted but discarded in earlier v2 releases — tokens were parsed without restricting the permitted signature algorithm. Since v2.4.2 it is passed to the parser as the single allowed algorithm, which structurally prevents algorithm-confusion attacks.
- A token whose
algheader does not matchjwt.algois rejected with 401 and{"error": "failed JWT token parser"}. - The value is matched case-sensitively against
EdDSA,HS256,HS384,HS512,RS256,RS384,RS512,ES256,ES384,ES512,PS256,PS384,PS512. Anything else — includinghs256in lowercase or an explicitalgo = ""— makes every request return HTTP 500 withunsupported JWT signature algorithm.
Leave jwt.algo unset to get the HS256 default.
When you configure jwt.wellknownurl / PREST_JWT_WELLKNOWNURL, pREST fetches the JWKS from the identity provider. Since v2.3.0 (#1002), that fetch (now on jwx/v3):
- Rejects non-2xx responses instead of attempting to parse an error page.
- Caps the response body at 1 MiB to bound memory.
- Redacts the URL in logs — userinfo, query string, and fragment are dropped.
Key-matching semantics (kid match, single-key with empty kid, empty-HMAC-key bypass guard) are unchanged, and there are no config or environment changes: jwt.jwks and jwt.wellknownurl work exactly as before.
Debug mode (PREST_DEBUG=true or debug = true in TOML) bypasses JWT enforcement at runtime.
To disable JWT entirely, leave jwt.default = false (the default in v2+).
Endpoints matching the whitelist regex do not require a JWT. The v2 default whitelist is ^\/auth$ (only the /auth endpoint). Configure additional patterns in TOML or via PREST_JWT_WHITELIST:
[jwt]
whitelist = ["\\/auth", "\\/ping", "\\/ping\\/.*"]v1 used [/auth] as the default whitelist and did not enforce JWT key configuration at startup. See Upgrading to v2 for migration steps.
When auth.enabled = true, pREST exposes a /auth endpoint that validates credentials against a database table and returns a signed JWT.
curl -i -X POST http://127.0.0.1:3000/auth -H "Content-Type: application/json" -d '{"username": "<username>", "password": "<password>"}'curl -i -X POST http://127.0.0.1:3000/auth --user "<username>:<password>"