@mark01/express-utils
Version:
npm package that contains utilities for express.js
80 lines (79 loc) • 2.5 kB
JavaScript
import { decodeJwt, importPKCS8, importSPKI, jwtVerify, SignJWT } from 'jose';
import { z } from 'zod';
import { AppError } from '../error';
export const signHS256JWT = async (secret, issuer, audience, jti, sub, expiration) => {
const secretEncoded = new TextEncoder().encode(secret);
const payload = {
aud: audience,
exp: Math.floor(Date.now() / 1000) + expiration * 60,
iat: Math.floor(Date.now() / 1000),
iss: issuer,
jti,
nbf: Math.floor(Date.now() / 1000),
sub,
};
const headers = {
alg: 'HS256',
typ: 'JWT',
};
return new SignJWT(payload).setProtectedHeader(headers).sign(secretEncoded);
};
export const signEdDSAJWT = async (privateKey, issuer, audience, jti, sub, expiration) => {
const privateKeyEncoded = await importPKCS8(privateKey, 'EdDSA');
const payload = {
aud: audience,
exp: Math.floor(Date.now() / 1000) + expiration * 60,
iat: Math.floor(Date.now() / 1000),
iss: issuer,
jti,
nbf: Math.floor(Date.now() / 1000),
sub,
};
const headers = {
alg: 'EdDSA',
typ: 'JWT',
};
return new SignJWT(payload)
.setProtectedHeader(headers)
.sign(privateKeyEncoded);
};
export const verifyEdDSAJWT = async (token, publicKey, audience, issuer) => {
try {
const publicKeyEncoded = await importSPKI(publicKey, 'EdDSA');
const options = {
audience,
issuer,
};
return jwtVerify(token, publicKeyEncoded, options);
}
catch (error) {
throw new AppError('Invalid JWT', 401, error);
}
};
export const extractJWTFromAuthHeader = (req) => {
const { authorization } = req.headers;
if (authorization?.startsWith('Bearer ')) {
return authorization.split(' ')[1];
}
return undefined;
};
export const validateJWTPayload = (jwtPayload) => {
const JWTPayloadSchema = z.object({
aud: z.string(),
exp: z.number(),
iat: z.number(),
iss: z.string(),
jti: z.string(),
nbf: z.number(),
sub: z.string(),
});
const validation = JWTPayloadSchema.safeParse(jwtPayload);
if (!validation.success) {
throw new AppError('Invalid JWT payload', 401, validation.error);
}
return validation.data;
};
export const decodeJWTPayload = (token) => {
const jwtPayload = decodeJwt(token);
return validateJWTPayload(jwtPayload);
};