JWT Authentication
Most production GraphQL APIs need to authenticate requests, and JWT tokens are one of the most common ways to do this. Hive Router has built-in JWT support that can validate tokens and protect your entire federated graph.
This guide shows you how to set up JWT authentication for real-world scenarios. For the complete
configuration reference, see jwt
configuration.
How JWT Authentication Works
When a request comes in with JWT authentication enabled, here’s what happens:
- Find the token: The router looks for a JWT in the places you’ve configured (usually the
Authorization
header) - Verify the signature: Using keys from your identity provider, the router checks that the token is legitimate and hasn’t been tampered with
- Check the claims: The router validates that the token isn’t expired and matches your configured audience and issuer requirements
- Allow or reject: Valid tokens get through, invalid ones get rejected with an authentication error
- Forward claims (optional): The router can pass user information from the token to your subgraphs
Common Setup: Auth0, Okta, or Similar
This is the most typical setup - you’re using a hosted identity provider that exposes a JWKS endpoint.
What you want:
- Require valid JWTs on all requests
- Validate tokens using your provider’s public keys
- Make sure tokens are meant for your API
jwt:
# Reject requests without valid tokens
require_authentication: true
# Where to get the keys for validation
jwks_providers:
- source: remote
url: https://your-domain.auth0.com/.well-known/jwks.json
prefetch: true # Fetch keys on startup
polling_interval: '15m' # Refresh keys every 15 minutes
# Make sure tokens are for your API
audiences:
- 'https://your-api.com'
# Make sure tokens come from your provider
issuers:
- 'https://your-domain.auth0.com/'
# Only allow secure algorithms
allowed_algorithms:
- RS256
Replace your-domain.auth0.com
and https://your-api.com
with your actual values.
Passing User Info to Subgraphs
Your subgraphs often need to know who the user is to handle authorization or return personalized data. The router can extract this information from the JWT and pass it along.
{
"sub": "user-123",
"email": "user@example.com",
"role": "admin",
"tenant_id": "company-abc"
}
jwt:
require_authentication: true
jwks_providers:
- source: remote
url: https://your-domain.auth0.com/.well-known/jwks.json
# Send user info to subgraphs
forward_claims_to_upstream_extensions:
enabled: true
field_name: 'user' # Access as extensions.user in subgraphs
What your subgraphs receive:
{
"query": "{ me { name } }",
"extensions": {
"user": {
"sub": "user-123",
"email": "user@example.com",
"role": "admin",
"tenant_id": "company-abc"
}
}
}
Now your subgraph resolvers can access extensions.user.sub
to identify the current user.
Optional Authentication
Sometimes you want to allow both authenticated and anonymous requests. Set
require_authentication: false
and your subgraphs can check if user claims were provided.
jwt:
require_authentication: false # Allow anonymous requests
jwks_providers:
- source: remote
url: https://your-domain.auth0.com/.well-known/jwks.json
forward_claims_to_upstream_extensions:
enabled: true
field_name: 'user'
Anonymous requests won’t have extensions.user
, while authenticated requests will. Your subgraphs
can adapt their behavior accordingly.
Multiple Token Locations
By default, the router looks for tokens in the Authorization
header with a Bearer
prefix. You
can configure it to check multiple places:
jwt:
require_authentication: true
jwks_providers:
- source: remote
url: https://your-domain.auth0.com/.well-known/jwks.json
lookup_locations:
# Check Authorization header first
- source: header
name: authorization
prefix: 'Bearer '
# Fall back to a cookie
- source: cookies
name: auth_token
# Check a custom header (no prefix)
- source: header
name: x-api-token
The router checks these in order and uses the first token it finds.
Local Development
For development, you might want to use a local JWKS file instead of hitting a remote endpoint:
jwt:
require_authentication: false # More flexible for dev
jwks_providers:
- source: file
path: ./dev-jwks.json
audiences:
- 'localhost:4000'
You can generate development keys using tools like jwt.io or your identity provider’s development tools.
Security Best Practices
- Always validate claims: Set
audiences
andissuers
to prevent token substitution attacks where someone tries to use a token meant for a different API. - Use specific algorithms: If you know your provider only uses
RS256
, specify it inallowed_algorithms
to reduce the attack surface. - Require authentication in production: Unless your API is truly public, set
require_authentication: true
. - Use HTTPS everywhere: Your JWKS endpoint must use HTTPS, and your router should too.
- Monitor token validation: Keep an eye on authentication error rates - a sudden spike might indicate an attack or configuration issue.