Skip to content
loco
v1.0
★ 6.9k Get started

Configure Where Loco Looks for the JWT

Goal: control where the JWT and JWTWithUser<T> extractors look for the token in an incoming request — the Authorization header (default), a query string parameter, a cookie, or a fallback list of several.

This setting is auth.jwt.location in your config file. It applies only to the JWT extractors (auth::JWT, auth::JWTWithUser<T>); it has no effect on auth::ApiToken<T>, which always reads a Bearer header regardless of this config — see Protect a route with an API key.

If you haven’t set up JWT auth yet, start with Protect a route with JWT; this page only covers the location key.

Default: no configuration needed

If you omit location entirely, Loco reads the token from the Authorization: Bearer <token> header:

auth:
jwt:
secret: "{{ get_env(name='JWT_SECRET') }}"
expiration: 604800
# location omitted => Bearer header

Single location

Set location to one map with a from: tag. The three variants:

Bearer header (equivalent to the default, spelled out explicitly):

auth:
jwt:
location:
from: Bearer
secret: "{{ get_env(name='JWT_SECRET') }}"
expiration: 604800

Query parameter — reads a named query-string value, e.g. for links that can’t carry custom headers (email verification links, WebSocket handshakes):

auth:
jwt:
location:
from: Query
name: token
secret: "{{ get_env(name='JWT_SECRET') }}"
expiration: 604800
Terminal window
curl 'http://127.0.0.1:5150/api/protected?token=<TOKEN>'

Cookie — reads a named cookie, e.g. for server-rendered apps using session-style cookies:

auth:
jwt:
location:
from: Cookie
name: auth_token
secret: "{{ get_env(name='JWT_SECRET') }}"
expiration: 604800
Terminal window
curl 'http://127.0.0.1:5150/api/protected' --cookie 'auth_token=<TOKEN>'

Multiple locations (tried in order)

Set location to a YAML list instead of a single map. Loco tries each location in the order listed and uses the first one that yields a token — useful when, say, browser clients send a cookie but API clients send a Bearer header:

auth:
jwt:
location:
- from: Cookie
name: auth_token
- from: Query
name: token
- from: Bearer
secret: "{{ get_env(name='JWT_SECRET') }}"
expiration: 604800

With this config, a request is accepted if it carries a valid token in the auth_token cookie, or (if that’s absent) a token query parameter, or (if both are absent) an Authorization: Bearer header — checked in that order. If none of the configured locations yields a token, the request is rejected with 401 Unauthorized.

Verify it works

For a Multiple config like the one above, confirm each location independently:

Terminal window
# via cookie
curl 'http://127.0.0.1:5150/api/protected' --cookie 'auth_token=<TOKEN>'
# via query parameter
curl 'http://127.0.0.1:5150/api/protected?token=<TOKEN>'
# via Bearer header
curl 'http://127.0.0.1:5150/api/protected' --header 'Authorization: Bearer <TOKEN>'

Each should succeed independently; a request with no token in any of the three should return 401 Unauthorized.