JWT plugin
This plugin adds support for using JWT in Elysia handlers.
Install with:
bun add @elysia/jwt@nextSet JWT_SECRET to a private signing secret before starting the server. The routes below demonstrate signing and verification; a real sign-in endpoint must verify credentials before issuing a token.
Then use it:
import { Elysia } from 'elysia'import { jwt } from '@elysia/jwt'
const app = new Elysia() .use( jwt({ name: 'jwt', secret: process.env.JWT_SECRET! }) ) .get('/sign/:name', async ({ jwt, params: { name }, cookie: { auth } }) => { const value = await jwt.sign({ name })
auth!.set({ value, httpOnly: true, secure: true, sameSite: 'lax', maxAge: 7 * 86400, path: '/profile', })
return `Sign in as ${value}` }) .get('/profile', async ({ jwt, status, cookie: { auth } }) => { const profile = await jwt.verify(auth!.value)
if (!profile) return status(401, 'Unauthorized')
return `Hello ${profile.name}` }) .listen(3000)import { Elysia } from 'elysia'import { jwt } from '@elysia/jwt'
const app = new Elysia() .use( jwt({ name: 'jwt', secret: process.env.JWT_SECRET! }) ) .get('/sign/:name', ({ jwt, params: { name } }) => { return jwt.sign({ name }) }) .get('/profile', async ({ jwt, status, headers: { authorization } }) => { const profile = await jwt.verify(authorization?.startsWith('Bearer ') ? authorization.slice(7) : undefined)
if (!profile) return status(401, 'Unauthorized')
return `Hello ${profile.name}` }) .listen(3000)These cookie settings require HTTPS. The header example expects Authorization: Bearer <token>.
Config
Section titled “Config”This plugin extends config from jose.
Below is a config that is accepted by the plugin.
Name to register the jwt function as.
For example, the jwt function will be registered with a custom name.
app .use( jwt({ name: 'myJWTNamespace', secret: process.env.JWT_SECRET! }) ) .get('/sign/:name', ({ myJWTNamespace, params }) => { return myJWTNamespace.sign(params) })Because some might need to use multiple jwt instances with different configs in a single server, explicitly registering the JWT function with a different name is needed.
secret
Section titled “secret”The private key to sign JWT payload with.
schema
Section titled “schema”Strict type validation for JWT payload.
The following options describe JWT claims and JWS headers supported by jose.
Default: HS256
Signing Algorithm to sign JWT payload with.
Possible properties for jose are: HS256 HS384 HS512 PS256 PS384 PS512 RS256 RS384 RS512 ES256 ES256K ES384 ES512 EdDSA
The issuer claim identifies the principal that issued the JWT as per RFC7519
TLDR; it is usually (the domain) name of the signer.
The subject claim identifies the principal that is the subject of the JWT.
The claims in a JWT are normally statements about the subject as per RFC7519
The audience claim identifies the recipients that the JWT is intended for.
Each principal intended to process the JWT MUST identify itself with a value in the audience claim as per RFC7519
JWT ID claim provides a unique identifier for the JWT as per RFC7519
The “not before” claim identifies the time before which the JWT must not be accepted for processing as per RFC7519
The expiration time claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing as per RFC7519
The “issued at” claim identifies the time at which the JWT was issued.
This claim can be used to determine the age of the JWT as per RFC7519
This JWS Extension Header Parameter modifies the JWS Payload representation and the JWS Signing input computation as per RFC7797.
A hint indicating which key was used to secure the JWS.
This parameter allows originators to explicitly signal a change of key to recipients as per RFC7515
(X.509 certificate SHA-1 thumbprint) header parameter is a base64url-encoded SHA-1 digest of the DER encoding of the X.509 certificate RFC5280 corresponding to the key used to digitally sign the JWS as per RFC7515
(X.509 certificate chain) header parameter contains the X.509 public key certificate or certificate chain RFC5280 corresponding to the key used to digitally sign the JWS as per RFC7515
(X.509 URL) header parameter is a URI RFC3986 that refers to a resource for the X.509 public key certificate or certificate chain [RFC5280] corresponding to the key used to digitally sign the JWS as per RFC7515
The jwk header contains the public JSON Web Key corresponding to the signing key. The separate jku header is a URL for a JWK Set. See RFC7515.
The typ (type) Header Parameter is used by JWS applications to declare the media type [IANA.MediaTypes] of this complete JWS.
This is intended for use by the application when more than one kind of object could be present in an application data structure that can contain a JWS as per RFC7515
Content-Type parameter is used by JWS applications to declare the media type [IANA.MediaTypes] of the secured content (the payload).
This is intended for use by the application when more than one kind of object could be present in the JWS Payload as per RFC7515
Handler
Section titled “Handler”Below are the values added to the handler.
jwt.sign
Section titled “jwt.sign”Signs a payload to create a JWT.
Type:
sign(payload: Omit<Claims, 'nbf' | 'exp' | 'iat'> & JWTPayloadInput): Promise<string>Claims is the shape of schema, or any record when no schema is set. JWTPayloadInput holds the registered claims iss, sub, aud, jti, nbf, exp and iat; a value set here overrides the one from config.
jwt.verify
Section titled “jwt.verify”Verify a token with the provided JWT config
Type:
verify(jwt?: string, options?: JWTVerifyOptions): Promise<(Claims & Omit<JWTPayloadSpec, keyof Claims>) | false>Returns the decoded payload, or false when the token is missing or invalid. JWTPayloadSpec holds the registered claims iss, sub, aud, jti, nbf, exp and iat as decoded values. options is passed to jose’s jwtVerify.
Pattern
Section titled “Pattern”Below you can find the common patterns to use the plugin.
Set JWT expiration date
Section titled “Set JWT expiration date”Set exp to control token expiration. A cookie’s lifetime and a JWT’s expiration are separate settings.
const app = new Elysia() .use( jwt({ name: 'jwt', secret: process.env.JWT_SECRET!, exp: '7d' }) ) .get('/sign/:name', async ({ jwt, params }) => jwt.sign(params))This will sign a JWT with an expiration date 7 days from now.