{"id":17441,"library":"koa-jwt","title":"Koa JWT Middleware","description":"koa-jwt is a middleware for Koa.js applications designed to authenticate HTTP requests using JSON Web Tokens (JWTs). It parses and validates JWTs typically provided in the `Authorization` header, or optionally from a cookie or a custom `getToken` function. Upon successful validation, the decoded JWT payload is exposed on `ctx.state.user` (by default) for subsequent middleware to use for authorization and access control. The current stable version is 4.0.4. Releases are driven by dependency updates (especially `jsonwebtoken`) and bug fixes, with major versions tied to Node.js support or significant internal changes. It differentiates itself by providing a streamlined, Koa-idiomatic approach to JWT authentication, leveraging Koa's async/await middleware pattern, and integrates well with `koa-unless` for path-based exclusion. It supports single or multiple secrets, including rolling secrets or mixed authentication methods (e.g., Auth0 PEM files and shared secrets).","status":"active","version":"4.0.4","language":"javascript","source_language":"en","source_url":"git://github.com/koajs/jwt","tags":["javascript","auth","authn","authentication","authz","authorization","http","jwt","json","typescript"],"install":[{"cmd":"npm install koa-jwt","lang":"bash","label":"npm"},{"cmd":"yarn add koa-jwt","lang":"bash","label":"yarn"},{"cmd":"pnpm add koa-jwt","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core dependency for signing and verifying JSON Web Tokens. `koa-jwt` wraps its functionality.","package":"jsonwebtoken","optional":false},{"reason":"Peer dependency; `koa-jwt` is a middleware designed specifically for Koa.js applications.","package":"koa","optional":false}],"imports":[{"note":"This package exports a default function. For TypeScript and modern Node.js, use ESM `import`. CommonJS `require` (e.g., `const jwt = require('koa-jwt');`) is also fully supported.","wrong":"const { jwt } = require('koa-jwt');","symbol":"jwt","correct":"import jwt from 'koa-jwt';"},{"note":"Use this type to strictly define the configuration object passed to the `koa-jwt` middleware function.","symbol":"Options","correct":"import type { Options } from 'koa-jwt';"},{"note":"The middleware augments `Koa.Context` by adding the decoded JWT payload to `ctx.state.user`. For full type safety in TypeScript, you might need to declare module augmentations in your project to extend Koa's Context type.","symbol":"Koa.Context augmentation","correct":"import type { Context } from 'koa'; // ... and koa-jwt adds ctx.state.user"}],"quickstart":{"code":"import Koa from 'koa';\nimport jwt from 'koa-jwt';\nimport Router from '@koa/router';\nimport bodyParser from 'koa-bodyparser';\nimport { sign } from 'jsonwebtoken';\n\nconst app = new Koa();\nconst router = new Router();\n\n// A secret key for signing and verifying tokens. In a real app, use environment variables.\nconst SUPER_SECRET_KEY = process.env.JWT_SECRET ?? 'your-super-secret-jwt-key';\n\napp.use(bodyParser());\n\n// Unprotected route for login\nrouter.post('/login', async (ctx) => {\n  const { username, password } = ctx.request.body as { username?: string, password?: string };\n\n  if (username === 'test' && password === 'password') {\n    // In a real app, you'd fetch user from DB and sign a token with user-specific data.\n    const token = sign({ id: 1, username: 'test' }, SUPER_SECRET_KEY, { expiresIn: '1h' });\n    ctx.body = { token };\n  } else {\n    ctx.status = 401;\n    ctx.body = { message: 'Invalid credentials' };\n  }\n});\n\n// JWT middleware protects all routes after this point, except those explicitly excluded.\n// For this example, we'll manually exclude /login and /public using .unless() or a custom conditional middleware.\n// A more robust solution often involves the 'koa-unless' package.\napp.use(async (ctx, next) => {\n  if (ctx.path.startsWith('/public') || ctx.path.startsWith('/login')) {\n    await next();\n  } else {\n    return jwt({ secret: SUPER_SECRET_KEY, debug: true })(ctx, next);\n  }\n});\n\n// Error handling for JWT authentication failures\napp.use(async (ctx, next) => {\n  try {\n    await next();\n  } catch (err: any) {\n    if (401 === err.status) {\n      ctx.status = 401;\n      ctx.body = {\n        error: 'Protected resource, use Authorization header to get access',\n        details: err.originalError ? err.originalError.message : err.message\n      };\n    } else {\n      throw err;\n    }\n  }\n});\n\n// Protected route\nrouter.get('/protected', async (ctx) => {\n  // ctx.state.user will contain the decoded JWT payload if authentication succeeded\n  ctx.body = `Hello, ${(ctx.state as any).user.username}! This is a protected route.`;\n});\n\n// Public route\nrouter.get('/public', async (ctx) => {\n  ctx.body = 'This is a public route, no token needed.';\n});\n\napp.use(router.routes());\napp.use(router.allowedMethods());\n\nconst PORT = 3000;\napp.listen(PORT, () => {\n  console.log(`Server running on http://localhost:${PORT}`);\n  console.log('Try POST /login with {username: \"test\", password: \"password\"} in body');\n  console.log('Then GET /protected with \"Authorization: Bearer <token>\" header');\n  console.log('Or GET /public without any token');\n});","lang":"typescript","description":"This quickstart demonstrates how to set up `koa-jwt` to protect routes in a Koa application, including token generation, login, public and protected endpoints, and basic error handling."},"warnings":[{"fix":"Ensure your Node.js environment is version 8 or higher. For Koa 2 with Node < 7.6, use `koa-jwt@2`. For Koa 1, use `koa-jwt@1`.","message":"Version 4.0.0 and above of `koa-jwt` require Node.js >= 8 due to the adoption of `async`/`await`. Prior versions (e.g., v3.x) required Node.js >= 7.6, and older versions (v2.x) supported Node.js < 7.6. Running on an unsupported Node.js version will lead to syntax errors or unexpected behavior.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Review your custom `getToken` or `isRevoked` implementations if they directly call `jsonwebtoken` functions. Ensure your Node.js environment meets `jsonwebtoken` v9's minimum requirements (Node.js >= 12).","message":"Version 4.0.4 updated its underlying `jsonwebtoken` dependency from v8.5.1 to v9.0.0. This major update in `jsonwebtoken` introduces breaking changes, notably affecting the `jwt.verify` callback signature (error is now the first argument) and `jwt.decode` no longer throwing errors for invalid tokens (it returns `null` instead). While `koa-jwt` attempts to abstract this, custom `getToken` or `isRevoked` functions that directly interact with `jsonwebtoken`'s `verify` or `decode` might need adjustments. Additionally, `jsonwebtoken` v9 dropped Node.js v10 support, impacting minimum compatible Node.js versions for downstream projects.","severity":"breaking","affected_versions":">=4.0.4"},{"fix":"Always set `debug: false` in production environments. Implement custom error handling middleware to provide generic 401 messages without exposing internal details. If `debug: true` is needed for development, ensure it's not enabled in deployed applications.","message":"When the `debug` option is set to `true` (or implicitly `false` in older versions), `koa-jwt` might expose more detailed error messages on authentication failures, including potentially sensitive information about the token or verification process. This can be a security risk in production environments by aiding attackers in probing for vulnerabilities. Since v3.2.0, when `debug` is `false`, all thrown errors have the same generic message for security reasons.","severity":"gotcha","affected_versions":"*"},{"fix":"Be explicit about your token source. If using `opts.getToken`, ensure it correctly handles all expected scenarios and returns `null` if no token is found from its custom source, allowing fallback to cookie or header if desired. Otherwise, rely on the default order.","message":"The middleware resolves tokens in a specific order: `opts.getToken` function, then `opts.cookie`, then the `Authorization` header. If `opts.getToken` is provided, it takes precedence. Overlooking this order can lead to unexpected token validation issues, where a token is picked from an undesired source.","severity":"gotcha","affected_versions":"*"},{"fix":"Be mindful of `ctx.state.secret`. If you intend to use a single secret, ensure no preceding middleware modifies `ctx.state.secret`. If you use dynamic secrets, carefully manage how `ctx.state.secret` is populated and its lifecycle.","message":"If `ctx.state.secret` is set by an earlier middleware, `koa-jwt` will use it instead of the `secret` provided in its options. This can be powerful for per-request secrets but can also lead to misconfigurations if an unintended secret is set on the context state, bypassing the middleware's configured secret.","severity":"gotcha","affected_versions":"*"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Provide a `secret` string or buffer in the `koa-jwt` middleware options, e.g., `app.use(jwt({ secret: 'your-secret' }))`. Alternatively, if using dynamic secrets, ensure a preceding middleware correctly sets `ctx.state.secret`.","cause":"The `secret` option was not provided to the `koa-jwt` middleware, or `ctx.state.secret` was not set, and a token requiring verification was present.","error":"`koa-jwt` failed to verify token: secret or public key must be provided"},{"fix":"The client needs to obtain a new, valid (unexpired) JWT from your authentication endpoint. On the server side, you can catch `TokenExpiredError` specifically in your error handling middleware to return a more informative response.","cause":"The JSON Web Token presented in the request has expired according to its `exp` claim.","error":"TokenExpiredError: jwt expired"},{"fix":"Ensure the `secret` used by `koa-jwt` on the server matches *exactly* the secret used to sign the token. Check for environmental variable mismatches, trimming issues, or different keys for different services.","cause":"The signature of the JWT does not match the computed signature, indicating the token has been tampered with or signed with a different secret than the one `koa-jwt` is using for verification.","error":"JsonWebTokenError: invalid signature"},{"fix":"For ESM, ensure you are using `import jwt from 'koa-jwt';`. For CommonJS, `const jwt = require('koa-jwt');` is correct. Avoid `import { jwt } from 'koa-jwt';` as it is a default export.","cause":"Incorrect import statement for `koa-jwt` in an ESM context, or attempting to `require` an ESM-only module in a CommonJS context, or incorrect destructuring of the default export.","error":"`TypeError: jwt is not a function`"}],"ecosystem":"npm","meta_description":null}