import jwt from '@ahmeducf/s-jwt';
// Generate a JWT token
const jwtToken = jwt.generateSync({ foo: 'bar' }, { secretKey: 'secret' });
// Verify a JWT token
try {
const decodedPayload = jwt.verifySync(jwtToken, { secretKey: 'secret' });
console.log(decodedPayload); // { foo: 'bar', iat: <timestamp> }
} catch (error) {
// Handle error
}
- Introduction
- Features
- Installation
- Usage Examples
- Generate a JWT
- Synchronous generation with default (HMAC SHA256) algorithm
- Synchronous generation with HMAC SHA512 algorithm
- Generate a token with asymmetric key algorithm
- Asynchronous generation
- (Async/Await) Asynchronous generation
- Generate a token with backdated
iat
claim - Generate a token with 1 hour expiration time
- Generate a token with 1 hour expiration time (using
expiresIn
) - Generate a token with 2 weeks expiration time
- Verify a JWT
- Generate a JWT
- API Reference
- Errors Codes
- Supported Algorithms
- Contributing
- License
S-JWT, S for Simple, Secure, and Salah (my name), is a TypeScript library that implements the JSON Web Token (JWT), JSON Web Signature (JWS), and JSON Web Algorithms (JWA) standards defined in RFC 7519, RFC 7515, and RFC 7518 respectively. It provides a simple and easy-to-use API for generating and verifying JWTs, with support for various algorithms and options.
- Simple: The API is simple and easy to use.
- Secure: The library is written in TypeScript and uses the latest ES standards. It is also fully tested and linted.
- Flexible: The library supports various algorithms (symmetric & asymmetric) and options.
- Highly Configurable: The library is highly configurable and allows you to customize the generated JWTs and the verification process.
- Dual Package Support: The library supports both CommonJS and ES Modules.
- Well Documented: The library is well documented and has a detailed API reference and usage examples.
Install with npm:
npm install @ahmeducf/s-jwt
Install with yarn:
yarn add @ahmeducf/s-jwt
This section contains some examples of how to use the library API.
import jwt from '@ahmeducf/s-jwt';
const jwtToken = jwt.generateSync({ foo: 'bar' }, { secretKey: 'secret' });
import jwt from '@ahmeducf/s-jwt';
try {
const jwtToken = jwt.generateSync(
{ foo: 'bar' },
{ secretKey: 'secret', algorithm: 'HS512' },
);
} catch (error) {
// Handle error
}
import fs from 'fs';
import jwt, { GenerateOptions } from '@ahmeducf/s-jwt';
const rsaPrivateKey: Buffer = fs.readFileSync('rsa.private.key');
const options: GenerateOptions = {
privateKey: rsaPrivateKey,
algorithm: 'RS256',
};
try {
const jwtToken = jwt.generateSync({ foo: 'bar' }, options);
} catch (error) {
// Handle error
}
import jwt from '@ahmeducf/s-jwt';
const jwtToken = jwt
.generate({ foo: 'bar' }, { secretKey: 'secret' })
.then((jwtToken) => {
// Handle success
})
.catch((error) => {
// Handle error
});
import jwt from '@ahmeducf/s-jwt';
async function generateAsync(payload: Payload, options: GenerateOptions): void {
try {
const jwtToken = await jwt.generate(payload, options);
// Handle success
} catch (error) {
// Handle error
}
}
generateAsync({ foo: 'bar' }, { secretKey: 'secret' });
import jwt from '@ahmeducf/s-jwt';
try {
const jwtToken = jwt.generateSync(
{ foo: 'bar', iat: Math.floor(Date.now() / 1000) - 30 },
{ secretKey: 'secret' },
);
} catch (error) {
// Handle error
}
import jwt, { Payload } from '@ahmeducf/s-jwt';
const payload: Payload = {
foo: 'bar',
exp: Math.floor(Date.now() / 1000) + 3600,
};
try {
const jwtToken: string = jwt.generateSync(payload, { secretKey: 'secret' });
} catch (error) {
// Handle error
}
import jwt, { GenerateOptions} from '@ahmeducf/s-jwt';
const options: GenerateOptions = {
secretKey: 'secret'
expiresIn: '1h',
}
try {
const jwtToken: string = jwt.generateSync({ foo: 'bar' }, options);
} catch (error) {
// Handle error
}
import jwt, { GenerateOptions } from '@ahmeducf/s-jwt';
const options: GenerateOptions = {
secretKey: 'secret',
expiresIn: '2 weeks', // equivalent to 1209600, '14 days', '336h', '20160m', '1209600s', '2016000000'
};
try {
const jwtToken: string = jwt.generateSync({ foo: 'bar' }, options);
} catch (error) {
// Handle error
}
import jwt from '@ahmeducf/s-jwt';
try {
const decodedPayload = jwt.verifySync(jwtToken, { secretKey: 'secret' });
} catch (error) {
// Handle error
}
import fs from 'fs';
import jwt, { VerifyOptions } from '@ahmeducf/s-jwt';
const rsaPublicKey: Buffer = fs.readFileSync('rsa.public.key');
const options: VerifyOptions = {
publicKey: rsaPublicKey,
algorithms: ['RS256'],
};
try {
const decodedPayload = jwt.verifySync(jwtToken, options);
} catch (error) {
// Handle error
}
import jwt from '@ahmeducf/s-jwt';
const decodedPayload = jwt
.verify(token, { secretKey: 'secret' })
.then((decodedPayload) => {
// Handle success
})
.catch((error) => {
// Handle error
});
import jwt, { VerifyOptions } from '@ahmeducf/s-jwt';
async function verifyAsync(token: string, options: VerifyOptions): void {
try {
const decodedPayload = await jwt.verify(token, options);
// Handle success
} catch (error) {
// Handle error
}
}
verifyAsync({ foo: 'bar' }, { secretKey: 'secret' });
import jwt from '@ahmeducf/s-jwt';
try {
const decodedPayload = jwt.verifySync(token, {
secretKey: 'secret',
ignoreExpiration: true,
});
} catch (error) {
// Handle error
}
import jwt from '@ahmeducf/s-jwt';
try {
const decodedPayload = jwt.verifyAsync(token, {
secretKey: 'secret',
algorithms: ['HS256'],
});
} catch (error) {
// If the algorithm in the token header is not HS256, error === SjwtVerificationError
}
import jwt from '@ahmeducf/s-jwt';
try {
const decodedPayload = jwt.verifySync(token, {
secretKey: 'secret',
audience: 'foo',
});
} catch (error) {
// If the audience in the token payload is not foo, error === SjwtVerificationError
}
import jwt from '@ahmeducf/s-jwt';
try {
const decodedPayload = jwt.verifySync(token, {
secretKey: 'secret',
issuer: ['foo', 'bar'],
});
} catch (error) {
// If the issuer in the token payload is not foo or bar, error === SjwtVerificationError
}
import jwt from '@ahmeducf/s-jwt';
try {
const decodedPayload = jwt.verifySync(token, {
secretKey: 'secret',
jwtId: 'foo',
});
} catch (error) {
// If the JWT ID in the token payload is not foo, error === SjwtVerificationError
}
import jwt from '@ahmeducf/s-jwt';
try {
const decodedPayload = jwt.verifySync(token, {
secretKey: 'secret',
subject: 'foo',
});
} catch (error) {
// If the subject in the token payload is not foo, error === SjwtVerificationError
}
The library has a simple and easy-to-use API. It provides two functions for generating and verifying JWTs, accompanied by a set of types and interfaces.
The library provides the following types and interfaces:
The Algorithm
type is an alias for the supported algorithms.
type Algorithm =
| 'HS256'
| 'HS384'
| 'HS512'
| 'RS256'
| 'RS384'
| 'RS512'
| 'ES256'
| 'ES384'
| 'ES512'
| 'PS256'
| 'PS384'
| 'PS512';
The HmacAlgorithm
type is an alias for the supported HMAC algorithms.
type HmacAlgorithm = 'HS256' | 'HS384' | 'HS512';
The RsaAlgorithm
type is an alias for the supported RSA algorithms.
type RsaAlgorithm = 'RS256' | 'RS384' | 'RS512';
The PssAlgorithm
type is an alias for the supported PSS algorithms.
type PssAlgorithm = 'PS256' | 'PS384' | 'PS512';
The EcdsaAlgorithm
type is an alias for the supported ECDSA algorithms.
type EcdsaAlgorithm = 'ES256' | 'ES384' | 'ES512';
The AsymmetricKeyAlgorithm
type is an alias for the supported asymmetric key algorithms.
type AsymmetricKeyAlgorithm = RsaAlgorithm | PssAlgorithm | EcdsaAlgorithm;
The SecondsNumber
type is an alias for a number representing a timespan in seconds.
type SecondsNumber = number;
The Payload
type is an interface representing the payload of a JWT.
interface Payload {
iss?: string; // Issuer
sub?: string; // Subject
aud?: string | string[]; // Audience
exp?: SecondsNumber; // Expiration Time
iat?: SecondsNumber; // Issued At
jti?: string; // JWT ID
[key: string]: unknown; // Any additional properties
}
Warning
The standard for JWT defines exp
and iat
as NumericDate:
A JSON numeric value representing the number of seconds from 1970-01-01T00:00:00Z UTC until the specified UTC date/time, ignoring leap seconds. This is equivalent to the IEEE Std 1003.1, 2013 Edition [POSIX.1] definition "Seconds Since the Epoch", in which each day is accounted for by exactly 86400 seconds, other than that non-integer values can be represented. See RFC 3339 [RFC3339] for details regarding date/times in general and UTC in particular.
The BaseGenerateOptions
type is an interface representing the base options for generating a JWT.
interface BaseGenerateOptions {
algorithm?: Algorithm; // Algorithm
expiresIn?: string | SecondsNumber; // Expiration Time
audience?: string | string[]; // Audience
issuer?: string; // Issuer
jwtId?: string; // JWT ID
subject?: string; // Subject
noTimestamp?: boolean; // Do not include the `iat` claim
}
Note
expiresIn
is expressed in seconds or a string describing a time span vercel/ms.
Eg: 1000
, "2 days"
, "10h"
, "7d"
. A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120"
is equal to "120ms"
).
Note
If any of the claims expiresIn
, audience
, issuer
, subject
, or jwtId
are specified in both GenerateOptions
and Payload
, the value in GenerateOptions
will be used.
The GenerateOptionsWithSecretKey
type is an interface representing the options for generating a JWT with a secret key.
interface GenerateOptionsWithSecretKey extends BaseGenerateOptions {
secretKey?: string | Buffer | crypto.KeyObject; // Secret Key for HMAC algorithms
}
The GenerateOptionsWithPrivateKey
type is an interface representing the options for generating a JWT with a private key.
interface GenerateOptionsWithPrivateKey extends BaseGenerateOptions {
privateKey?: string | Buffer | crypto.KeyObject; // Private Key for asymmetric key algorithms
}
The GenerateOptions
type is an interface representing the options for generating a JWT.
type GenerateOptions =
| GenerateOptionsWithSecretKey
| GenerateOptionsWithPrivateKey;
Warning
Generated JWTs will include an iat
(issued at) claim by default unless GenerateOptions.noTimestamp
is specified. If iat
is inserted in the payload, it will be used instead of the real timestamp for calculating other things like exp
given a timespan in GenerateOptions.expiresIn
.
If both GenerateOptions.noTimestamp
and Payload.iat
are specified, an SjwtTypeError
will be thrown.
The BaseVerifyOptions
type is an interface representing the base options for verifying a JWT.
interface BaseVerifyOptions {
algorithms?: Algorithm[]; // Algorithms to accept in `alg` claim
audience?: string | RegExp | Array<string | RegExp>; // Audience(s) to accept in `aud` claim
issuer?: string | string[]; // Issuer(s) to accept in `iss` claim
jwtId?: string; // JWT ID to accept in `jti` claim
subject?: string; // Subject to accept in `sub` claim
ignoreExpiration?: boolean; // If true, do not validate the `exp` claim
maxAge?: string | SecondsNumber; // The maximum allowed age for tokens to still be valid.
clockTimestamp?: SecondsNumber; // The time in seconds that should be used as the current time for all necessary comparisons.
clockTolerance?: SecondsNumber; // Number of seconds to tolerate when checking the `exp` claim, to deal with small clock differences among different servers.
}
Note
maxAge
is expressed in seconds or a string describing a time span vercel/ms.
Eg: 1000
, "2 days"
, "10h"
, "7d"
. A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120"
is equal to "120ms"
).
The VerifyOptionsWithSecretKey
type is an interface representing the options for verifying a JWT with a secret key.
interface VerifyOptionsWithSecretKey extends BaseVerifyOptions {
secretKey?: string | Buffer | crypto.KeyObject; // Secret Key for HMAC algorithms
}
The VerifyOptionsWithPublicKey
type is an interface representing the options for verifying a JWT with a public key.
interface VerifyOptionsWithPublicKey extends BaseVerifyOptions {
publicKey?: string | Buffer | crypto.KeyObject; // Public Key for asymmetric key algorithms
}
The VerifyOptions
type is an interface representing the options for verifying a JWT.
type VerifyOptions = VerifyOptionsWithSecretKey | VerifyOptionsWithPublicKey;
The SjwtError
type is an interface representing a generic error thrown by the library.
interface SjwtError extends Error {
name: string;
message: string;
}
The SjwtTypeError
type is an interface representing a type error thrown by the library.
Property name
is always SjwtTypeError
.
type SjwtTypeError = SjwtError;
The SjwtValidationError
type is an interface representing a validation error thrown by the library.
Property name
is always SjwtValidationError
.
type SjwtValidationError = SjwtError;
The SjwtVerificationError
type is an interface representing a verification error thrown by the library.
Property name
is always SjwtVerificationError
.
type SjwtVerificationError = SjwtError;
The SjwtExpiredTokenError
type is an interface representing an expired token error thrown by the library during verification. It extends SjwtVerificationError
.
Property name
is always SjwtExpiredTokenError
. It also has a expiredAt
property which is the date at which the token expired.
interface SjwtExpiredTokenError extends SjwtVerificationError {
expiredAt: Date;
}
The library provides the following functions:
generateSync(payload: Payload, options: GenerateOptions): string
The generateSync
function is a synchronous function that generates a JWT.
It takes a payload and options as arguments and returns a JWT string.
generate(payload: Payload, options: GenerateOptions): Promise<string>
The generate
function is promise-based asynchronous version of generateSync
.
-
payload
: The payload of the JWT. -
options
: The options for generating the JWT.-
secretKey
: The secret key to use for generating the JWT. Used only for HMAC algorithms. -
privateKey
: The private key to use for generating the JWT. Used only for asymmetric key algorithms.[!WARNING]
If both
GenerateOptions.secretKey
andGenerateOptions.privateKey
are specified, anSjwtValidationError
will be thrown. You also have to use the appropriate algorithm for the key type. See Supported Algorithms to know which algorithms are supported for each key type. -
algorithm
: The algorithm to use for generating the JWT. Defaults toHS256
. -
expiresIn
: The expiration time of the JWT. If defined it overrides theexp
claim in the payload.[!IMPORTANT]
expiresIn
is expressed in seconds or a string describing a time span vercel/ms.Eg:
1000
,"2 days"
,"10h"
,"7d"
. A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120"
is equal to"120ms"
). -
audience
: The audience(s) that the JWT is intended for. If defined it overrides theaud
claim in the payload. -
issuer
: The issuer of the JWT. If defined it overrides theiss
claim in the payload. -
jwtId
: The ID of the JWT. If defined it overrides thejti
claim in the payload. -
subject
: The subject of the JWT. If defined it overrides thesub
claim in the payload. -
noTimestamp
: Iftrue
, the generated JWT will not include aniat
claim.[!WARNING]
Generated JWTs will include an
iat
(issued at) claim by default unlessGenerateOptions.noTimestamp
is specified. Ifiat
is inserted in the payload, it will be used instead of the real timestamp for calculating other things likeexp
given a timespan inGenerateOptions.expiresIn
. If bothGenerateOptions.noTimestamp
andPayload.iat
are specified, anSjwtValidationError
will be thrown.
-
-
Returns: In case of successful generation, the generated JWT is returned. Otherwise, an error is thrown.
verifySync(token: string, options: VerifyOptions): Payload
The verifySync
function is a synchronous function that verifies a JWT.
It takes a JWT string and options as arguments and returns the decoded payload.
verify(token: string, options: VerifyOptions): Promise<Payload>
The verify
function is promise-based asynchronous version of verifySync
.
-
token
: The JWT string to verify. -
options
: The options for the verification process.-
secretKey
: The secret key to use for verifying the JWT. Used only for HMAC algorithms. -
publicKey
: The public key to use for verifying the JWT. Used only for asymmetric key algorithms.[!WARNING]
If both
VerifyOptions.secretKey
andVerifyOptions.publicKey
are specified, anSjwtValidationError
will be thrown. You also have to use the appropriate algorithm for the key type. See Supported Algorithms to know which algorithms are supported for each key type. -
algorithms
: List of algorithms to accept in thealg
claim. Example:['HS256', 'HS384']
.[!NOTE]
If not specified a defaults will be used based on the type of key provided.
- Secret key:
['HS256', 'HS384', 'HS512']
- RSA public key:
['RS256', 'RS384', 'RS512']
- RSA-PSS public key:
['PS256', 'PS384', 'PS512']
- ECDSA public key:
['ES256', 'ES384', 'ES512']
- Secret key:
-
audience
: The audience(s) to accept in theaud
claim. if you want to check audience(aud)
claim, provide a value here. -
issuer
: string or array of strings of valid values for the iss field. if you want to check issuer(iss)
claim, provide a value here. -
jwtId
: The JWT ID to accept in thejti
claim. If you want to check the JWT ID, provide a value here. -
subject
: The subject to accept in thesub
claim. If you want to check the subject, provide a value here. -
ignoreExpiration
: Iftrue
, theexp
claim will not be validated. -
maxAge
: The maximum allowed age for tokens to still be valid.[!NOTE]
maxAge
is expressed in seconds or a string describing a time span vercel/ms.Eg:
1000
,"2 days"
,"10h"
,"7d"
. A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120"
is equal to"120ms"
). -
clockTimestamp
: The time in seconds that should be used as the current time for all necessary comparisons. -
clockTolerance
: Number of seconds to tolerate when checking theexp
claim, to deal with small clock differences among different servers.
-
-
Returns: In case of successful verification, the decoded payload is returned. Otherwise, an error is thrown.
The library may throw the following errors:
Thrown when the provided RSA/RSA-PSS private key is invalid.
Error Type: SjwtTypeError
Error Object:
name
: 'RsaPrivateKeyInvalid'message
: 'Invalid RSA private key: The provided private key is not supported.'
Thrown when the provided ECDSA private key is invalid.
Error Type: SjwtTypeError
Error Object:
name
: 'EcdsaPrivateKeyInvalid'message
: 'Invalid ECDSA private key: The provided private key is not supported.'
Thrown when the JWT token header is invalid.
Error Type: SjwtTypeError
Error Object:
name
: 'JwtTokenHeaderInvalid'message
: 'Invalid JWT token header: The header is not a valid JSON object encoded in base64url format.'
Thrown when the JWT token payload is invalid.
Error Type: SjwtTypeError
Error Object:
name
: 'JwtTokenPayloadInvalid'message
: 'Invalid JWT token payload: The payload is not a valid JSON object encoded in base64url format.'
Thrown when the JWT token signature is invalid.
Error Type: SjwtTypeError
Error Object:
name
: 'JwtTokenSignatureInvalid'message
: 'Invalid JWT token signature: The signature is not a valid base64url string.'
Thrown when the JWT token string is malformed.
Error Type: SjwtTypeError
Error Object:
name
: 'JwtTokenMalformed'message
: 'Invalid JWT token: The token is not a valid JSON Web Token.'
Thrown when any of the API arguments does not meet the validation criteria.
Error Type: SjwtValidationError
Error Object:
name
: 'SjwtValidationError'message
: '<Error message describing the validation error>'
Thrown during token verification when the token type is not JWT
.
Error Type: SjwtVerificationError
Error Object:
name
: 'InvalidTokenType'message
: 'Token type is not JWT'
Thrown during token verification when the algorithm in the token header is not in the list of allowed algorithms.
Error Type: SjwtVerificationError
Error Object:
name
: 'InvalidAlgorithm'message
: 'Algorithmheader.alg
is not included in the list of allowed "algorithms"options.algorithms
'
Thrown during token verification when the issuer in the token payload is not in the list of allowed issuers.
Error Type: SjwtVerificationError
Error Object:
name
: 'InvalidIssuer'message
: 'jwt issuer invalid. expected: <options.issuer
>'
Thrown during token verification when the subject in the token payload is not the specified allowed subjects.
Error Type: SjwtVerificationError
Error Object:
name
: 'InvalidSubject'message
: 'jwt subject invalid. expected: <options.subject
>'
Thrown during token verification when the audience in the token payload is not in the list of allowed audiences.
Error Type: SjwtVerificationError
Error Object:
name
: 'InvalidAudience'message
: 'jwt audience invalid'
Thrown during token verification when the JWT ID in the token payload is not the specified allowed JWT ID.
Error Type: SjwtVerificationError
Error Object:
name
: 'InvalidJwtId'message
: 'jwt jwtId invalid. expected: <options.jwtId
>'
Thrown during token verification when the token is expired.
Error Type: SjwtExpiredTokenError
Error Object:
name
: 'SjwtExpiredTokenError'message
:- 'Expired token: jwt expired': If
options.ignoreExpiration
isfalse
and the token is expired. - 'Expired token: jwt maxAge exceeded': If
options.maxAge
is specified and the token age exceeds the maximum allowed age.
- 'Expired token: jwt expired': If
Thrown during token verification when the signature is invalid.
Error Type: SjwtVerificationError
Error Object:
name
: 'InvalidSignature'message
: 'signature verification failed'
The library supports the following algorithms:
alg Parameter Value | Digital Signature or MAC Algorithm |
---|---|
HS256 | HMAC using SHA-256 hash algorithm |
HS384 | HMAC using SHA-384 hash algorithm |
HS512 | HMAC using SHA-512 hash algorithm |
RS256 | RSASSA-PKCS1-v1_5 using SHA-256 hash algorithm |
RS384 | RSASSA-PKCS1-v1_5 using SHA-384 hash algorithm |
RS512 | RSASSA-PKCS1-v1_5 using SHA-512 hash algorithm |
PS256 | RSASSA-PSS using SHA-256 hash algorithm (only node ^6.12.0 OR >=8.0.0) |
PS384 | RSASSA-PSS using SHA-384 hash algorithm (only node ^6.12.0 OR >=8.0.0) |
PS512 | RSASSA-PSS using SHA-512 hash algorithm (only node ^6.12.0 OR >=8.0.0) |
ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm |
ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm |
ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm |
Contributions are welcome! Please read CONTRIBUTING.md for more information.