@nestjs/jwt
semver
>=9.0.0 <12.0.0postconditions7functions4last verified2026-06-24coverage score100%Postconditions: what we check
- verifyAsync · verify-no-try-catcherrorWhentoken is expired, has invalid signature, is malformed, or fails audience/issuer/subject checksThrows
JsonWebTokenError | TokenExpiredError | NotBeforeErrorRequired handlingMUST wrap in try-catch. In production, expired and invalid tokens are expected inputs (not programmer errors). Unhandled rejection crashes the request handler and leaks 500 errors to clients.costhighin prodimmediate exceptionusers seeauthentication failurevisibilityvisible - verifyAsync · verify-async-misconfigured-secret-unhandled-rejectionwarningWhenJwtService instantiated without a secret/publicKey/secretOrKeyProvider AND verifyAsync() called without per-call secret overrideThrows
Error('secret or public key must be provided') from jsonwebtoken — Promise rejection, NOT a sync throwRequired handlingMUST validate JwtModule configuration at boot time (registerAsync useFactory should throw if secret resolution returns undefined). When config-validation is not feasible, every verifyAsync() call site must attach a .catch() or be wrapped in try-catch on await. Misconfigured JwtService is a deployment-time hazard that only fires on first verify call — easy to ship to staging undetected, common cause of '500 on /auth/me' incidents post-deploy.costmediumin proddelayed failureusers seeauthentication failurevisibilityvisible - verify · verify-sync-no-try-catcherrorWhentoken is expired, has invalid signature, is malformed, or fails claim checksThrows
JsonWebTokenError | TokenExpiredError | NotBeforeErrorRequired handlingMUST wrap in try-catch. Throws synchronously — same error types as verifyAsync.costhighin prodimmediate exceptionusers seeauthentication failurevisibilityvisibleSources[1] - signAsync · sign-async-no-try-catchwarningWhenasync secretOrKeyProvider fails, or invalid algorithm/key configurationThrows
Error (from secretOrKeyProvider rejection or jsonwebtoken signing failure)Required handlingSHOULD wrap in try-catch when using async secretOrKeyProvider. Low-risk when using static secret strings.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - signAsync · sign-async-sync-throw-on-string-payload-with-optionserrorWhensignAsync() called with string payload AND signOptions containing keys other than 'secret' or 'privateKey' (e.g. expiresIn, audience, issuer)Throws
Error('Payload as string is not allowed with the following sign options: <keys>') — thrown SYNCHRONOUSLY before the Promise is constructedRequired handlingMUST wrap signAsync() call in try-catch (not just .catch()) when payload may be a string and signOptions vary at runtime. signAsync(payload, opts).catch() CANNOT catch this synchronous throw because the Promise never gets constructed. The .catch() handler runs against a Promise that throws during its own creation, leaving an unhandled exception that crashes the request handler.costmediumin prodimmediate exceptionusers seeauthentication failurevisibilityvisible - sign · sign-sync-wrong-secret-providererrorWhensecretOrKeyProvider option is async (returns Promise) but sync sign() is called instead of signAsync()Throws
WrongSecretProviderError — extends Error, thrown synchronously before jwt.sign() is calledRequired handlingMUST use signAsync() when secretOrKeyProvider is async. Using sign() with an async provider throws immediately and the token is never generated.costmediumin prodimmediate exceptionusers seeauthentication failurevisibilityvisibleSources[3] - sign · sign-sync-string-payload-with-optionswarningWhenpayload is a string AND sign options contain keys other than 'secret' or 'privateKey' (e.g. expiresIn, audience, issuer)Throws
Error('Payload as string is not allowed with the following sign options: <keys>')Required handlingMUST use object or Buffer payload when setting sign options like expiresIn, audience, or issuer. String payloads only accept secret/privateKey overrides.costlowin prodimmediate exceptionusers seeauthentication failurevisibilityvisibleSources[3]
Sources
Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.
Official documentation
- [2]docs.nestjs.com/security/authenticationAuthentication
Source code
- [1]github.com/auth0/node-jsonwebtokenauth0/node-jsonwebtoken
- [3]github.com/nestjs/jwt/blobnestjs/jwt · jwt.service.ts
- [4]github.com/nestjs/jwt/blobnestjs/jwt · jwt.service.ts
- [5]github.com/auth0/node-jsonwebtoken/blobauth0/node-jsonwebtoken · verify.js
- [6]github.com/nestjs/jwt/blobnestjs/jwt · jwt.service.ts
Research notes
Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.
@nestjs/jwt Contract Sources
Package Overview
@nestjs/jwt is a NestJS module wrapping the jsonwebtoken library for JWT token signing and verification.
It provides JwtService with async and sync variants of sign() and verify().
Key Error Types
From jsonwebtoken (the underlying library):
JsonWebTokenError— invalid signature, malformed token, audience/issuer/subject mismatchTokenExpiredError— token'sexpclaim is in the pastNotBeforeError— token'snbfclaim is in the future
@nestjs/jwt also adds:
WrongSecretProviderError— whenverify()(sync) encounters an asyncsecretOrKeyProvider
Detection
detection.type_names: [JwtService] — tracks class instances created via constructor injection.
The scanner detects this.jwtService.verifyAsync(), this.jwtService.verify(), etc.
Evidence
- Official NestJS sample:
nestjs/sample/19-auth-jwt—signAsync()without try-catch (TP) - Hoppscotch backend: 9 checks, 0 violations — correct usage of try-catch
- Real-world precision: 100% (1 TP, 0 FP across 2 repos)
Sources
Need a different package?
Request a profile