Aktueller Stand

This commit is contained in:
2026-01-22 19:05:45 +01:00
parent 85dee61a4d
commit e280e4eadb
1967 changed files with 397327 additions and 74093 deletions

View File

@@ -13,9 +13,10 @@ const {
RSA_PKCS1_PADDING,
RSA_PSS_SALTLEN_MAX_SIGN,
RSA_PSS_SALTLEN_AUTO
}
},
sign: directSign,
verify: directVerify
} = require('node:crypto')
const { sign: directSign, verify: directVerify } = require('node:crypto')
const { joseToDer, derToJose } = require('ecdsa-sig-formatter')
const Cache = require('mnemonist/lru-cache')
const { TokenError } = require('./error')

View File

@@ -14,46 +14,12 @@ export type Algorithm =
| 'PS512'
| 'EdDSA'
export type TokenValidationErrorCode =
| 'FAST_JWT_INVALID_TYPE'
| 'FAST_JWT_INVALID_OPTION'
| 'FAST_JWT_INVALID_ALGORITHM'
| 'FAST_JWT_INVALID_CLAIM_TYPE'
| 'FAST_JWT_INVALID_CLAIM_VALUE'
| 'FAST_JWT_INVALID_KEY'
| 'FAST_JWT_INVALID_SIGNATURE'
| 'FAST_JWT_INVALID_PAYLOAD'
| 'FAST_JWT_MALFORMED'
| 'FAST_JWT_INACTIVE'
| 'FAST_JWT_EXPIRED'
| 'FAST_JWT_MISSING_KEY'
| 'FAST_JWT_KEY_FETCHING_ERROR'
| 'FAST_JWT_SIGN_ERROR'
| 'FAST_JWT_VERIFY_ERROR'
| 'FAST_JWT_MISSING_REQUIRED_CLAIM'
| 'FAST_JWT_MISSING_SIGNATURE'
export type TokenValidationErrorCode = typeof TOKEN_ERROR_CODES[keyof typeof TOKEN_ERROR_CODES]
declare class TokenError extends Error {
constructor(code: TokenValidationErrorCode, message?: string, additional?: { [key: string]: any });
static wrap(originalError: Error, code: TokenValidationErrorCode, message: string): TokenError
static codes: {
invalidType: 'FAST_JWT_INVALID_TYPE'
invalidOption: 'FAST_JWT_INVALID_OPTION'
invalidAlgorithm: 'FAST_JWT_INVALID_ALGORITHM'
invalidClaimType: 'FAST_JWT_INVALID_CLAIM_TYPE'
invalidClaimValue: 'FAST_JWT_INVALID_CLAIM_VALUE'
invalidKey: 'FAST_JWT_INVALID_KEY'
invalidSignature: 'FAST_JWT_INVALID_SIGNATURE'
invalidPayload: 'FAST_JWT_INVALID_PAYLOAD'
malformed: 'FAST_JWT_MALFORMED'
inactive: 'FAST_JWT_INACTIVE'
expired: 'FAST_JWT_EXPIRED'
missingKey: 'FAST_JWT_MISSING_KEY'
keyFetchingError: 'FAST_JWT_KEY_FETCHING_ERROR'
signError: 'FAST_JWT_SIGN_ERROR'
verifyError: 'FAST_JWT_VERIFY_ERROR'
missingRequiredClaim: 'FAST_JWT_MISSING_REQUIRED_CLAIM'
missingSignature: 'FAST_JWT_MISSING_SIGNATURE'
}
static codes: typeof TOKEN_ERROR_CODES
code: TokenValidationErrorCode;
[key: string]: any
@@ -148,6 +114,26 @@ export interface PrivateKey {
passphrase: string | undefined
}
export const TOKEN_ERROR_CODES: {
readonly invalidType: 'FAST_JWT_INVALID_TYPE';
readonly invalidOption: 'FAST_JWT_INVALID_OPTION';
readonly invalidAlgorithm: 'FAST_JWT_INVALID_ALGORITHM';
readonly invalidClaimType: 'FAST_JWT_INVALID_CLAIM_TYPE';
readonly invalidClaimValue: 'FAST_JWT_INVALID_CLAIM_VALUE';
readonly invalidKey: 'FAST_JWT_INVALID_KEY';
readonly invalidSignature: 'FAST_JWT_INVALID_SIGNATURE';
readonly invalidPayload: 'FAST_JWT_INVALID_PAYLOAD';
readonly malformed: 'FAST_JWT_MALFORMED';
readonly inactive: 'FAST_JWT_INACTIVE';
readonly expired: 'FAST_JWT_EXPIRED';
readonly missingKey: 'FAST_JWT_MISSING_KEY';
readonly keyFetchingError: 'FAST_JWT_KEY_FETCHING_ERROR';
readonly signError: 'FAST_JWT_SIGN_ERROR';
readonly verifyError: 'FAST_JWT_VERIFY_ERROR';
readonly missingRequiredClaim: 'FAST_JWT_MISSING_REQUIRED_CLAIM';
readonly missingSignature: 'FAST_JWT_MISSING_SIGNATURE';
};
export function createSigner<T = SignerPayload>(
options?: Partial<SignerOptions & { key: Bufferable | PrivateKey }>
): typeof SignerSync<T>

View File

@@ -235,7 +235,7 @@ module.exports = function createSigner(options) {
if (typeof expiresIn === 'string') {
expiresIn = parseMs(expiresIn)
}
if (typeof expiresIn !== 'number' || expiresIn < 0) {
if (typeof expiresIn !== 'number') {
throw new TokenError(
TokenError.codes.invalidOption,
'The expiresIn option must be a positive number or a valid string.'

View File

@@ -141,28 +141,22 @@ function validateAlgorithmAndSignature(input, header, signature, key, allowedAlg
}
}
function validateClaimType(values, claim, array, type) {
const typeFailureMessage = array
function validateClaimType(values, claim, allowArray, isArray, type) {
const typeFailureMessage = allowArray
? `The ${claim} claim must be a ${type} or an array of ${type}s.`
: `The ${claim} claim must be a ${type}.`
if (isArray && !allowArray) {
throw new TokenError(TokenError.codes.invalidClaimValue, typeFailureMessage)
}
if (values.map(v => typeof v).some(t => t !== type)) {
throw new TokenError(TokenError.codes.invalidClaimType, typeFailureMessage)
}
}
function validateClaimValues(values, claim, allowed, arrayValue) {
const failureMessage = arrayValue
? `Not all of the ${claim} claim values are allowed.`
: `The ${claim} claim value is not allowed.`
if (!values.every(v => allowed.some(a => a.test(v)))) {
throw new TokenError(TokenError.codes.invalidClaimValue, failureMessage)
}
}
function validateClaimArrayValues(values, claim, allowed, arrayValue) {
const failureMessage = arrayValue
function validateClaimValues(values, claim, allowed, isArray) {
const failureMessage = isArray
? `None of ${claim} claim values are allowed.`
: `The ${claim} claim value is not allowed.`
@@ -218,8 +212,8 @@ function verifyToken(
for (const { type, claim, allowed, array, modifier, greater, errorCode, errorVerb } of validators) {
const value = payload[claim]
const arrayValue = Array.isArray(value)
const values = arrayValue ? value : [value]
const isArray = Array.isArray(value)
const values = isArray ? value : [value]
// We have already checked above that all required claims are present
// Therefore we can skip this validator if the claim is not present
@@ -228,14 +222,12 @@ function verifyToken(
}
// Validate type
validateClaimType(values, claim, array, type === 'date' ? 'number' : 'string')
validateClaimType(values, claim, array, isArray, type === 'date' ? 'number' : 'string')
if (type === 'date') {
validateClaimDateValue(value, modifier, now, greater, errorCode, errorVerb)
} else if (array) {
validateClaimArrayValues(values, claim, allowed, arrayValue)
} else {
validateClaimValues(values, claim, allowed, arrayValue)
validateClaimValues(values, claim, allowed, isArray)
}
}
}