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
Authorizationheader) - 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
Replace your-domain.auth0.com and https://your-api.com with your actual values.
Handling Key Rotation
Identity providers rotate their signing keys from time to time. The router refreshes the JWKS
every polling_interval, so a token signed with a brand-new key can be rejected until the next
refresh. To accept rotated keys immediately, set refresh_on_unknown_kid on the remote provider:
When a token carries a kid that is not in the cached key set, the router re-fetches the JWKS right
away and verifies the token against the fresh keys. The value is a cooldown scoped to each remote
provider: for a given provider, at most one such re-fetch happens per 30 seconds, no matter how many
unknown kids arrive. If you configure several providers with refresh_on_unknown_kid, each of
them may fetch once per window, because an unknown kid is checked against all of their key sets.
Within that bound, the setting is safe to enable on a public endpoint. See the
refresh_on_unknown_kid reference for details.
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.
What your subgraphs receive:
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.
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:
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:
You can generate development keys using tools like jwt.io or your identity provider’s development tools.
Security Best Practices
- Always validate claims: Set
audiencesandissuersto 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_algorithmsto 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.