Projektstart

This commit is contained in:
2026-01-22 15:49:12 +01:00
parent 7212eb6f7a
commit 57e5f652f8
10637 changed files with 2598792 additions and 64 deletions

88
backend/node_modules/@fastify/jwt/test/helper.js generated vendored Normal file
View File

@@ -0,0 +1,88 @@
'use strict'
const crypto = require('node:crypto')
function generateKeyPair () {
const options = {
modulusLength: 2048,
publicExponent: 0x10001,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
}
return crypto.generateKeyPairSync('rsa', options)
}
function generateKeyPairProtected (passphrase) {
const options = {
modulusLength: 2048,
publicExponent: 0x10001,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase
}
}
return crypto.generateKeyPairSync('rsa', options)
}
function withResolvers () {
let promiseResolve, promiseReject
const promise = new Promise((resolve, reject) => {
promiseResolve = resolve
promiseReject = reject
})
return { promise, resolve: promiseResolve, reject: promiseReject }
}
function generateKeyPairECDSA () {
const options = {
modulusLength: 2048,
namedCurve: 'prime256v1',
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
}
return crypto.generateKeyPairSync('ec', options)
}
function generateKeyPairECDSAProtected (passphrase) {
const options = {
modulusLength: 2048,
namedCurve: 'prime256v1',
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase
}
}
return crypto.generateKeyPairSync('ec', options)
}
module.exports = {
generateKeyPair,
generateKeyPairProtected,
generateKeyPairECDSA,
generateKeyPairECDSAProtected,
withResolvers
}

View File

@@ -0,0 +1,134 @@
'use strict'
const { test } = require('node:test')
const Fastify = require('fastify')
const jwt = require('../jwt')
const { createSigner } = require('fast-jwt')
test('Async key provider should be resolved internally', async function (t) {
const fastify = Fastify()
fastify.register(jwt, {
secret: {
private: 'supersecret',
public: async () => Promise.resolve('supersecret')
},
verify: {
extractToken: (request) => request.headers.jwt,
key: () => Promise.resolve('supersecret')
}
})
fastify.get('/', async function (request, reply) {
const token = await reply.jwtSign({ user: 'test' })
request.headers.jwt = token
await request.jwtVerify()
return reply.send(request.user)
})
const response = await fastify.inject({
method: 'get',
url: '/',
headers: {
jwt: 'supersecret'
}
})
t.assert.ok(response)
t.assert.strictEqual(response.json().user, 'test')
})
test('Async key provider errors should be resolved internally', async function (t) {
const fastify = Fastify()
fastify.register(jwt, {
secret: {
public: async () => Promise.resolve('key used per request, false not allowed')
},
verify: {
extractToken: (request) => request.headers.jwt,
key: () => Promise.resolve('key not used')
}
})
fastify.get('/', async function (request, reply) {
const signSync = createSigner({ key: 'invalid signature error' })
request.headers.jwt = signSync({ sub: '1234567890', name: 'John Doe', iat: 1516239022 })
// call to local verifier without cache
await request.jwtVerify()
return reply.send(typeof request.user.then)
})
const response = await fastify.inject({
method: 'get',
url: '/'
})
t.assert.strictEqual(response.statusCode, 401)
})
test('Async key provider should be resolved internally with cache', async function (t) {
const fastify = Fastify()
fastify.register(jwt, {
secret: {
private: 'this secret reused from cache',
public: async () => false
},
verify: {
extractToken: (request) => request.headers.jwt,
key: () => Promise.resolve('this secret reused from cache')
}
})
fastify.get('/', async function (request, reply) {
const signSync = createSigner({ key: 'this secret reused from cache' })
request.headers.jwt = signSync({ sub: '1234567890', name: 'John Doe', iat: 1516239022 })
await new Promise((resolve, reject) => request.jwtVerify((err, payload) => {
if (err) {
reject(err)
return
}
resolve(payload)
}))
await new Promise((resolve, reject) => request.jwtVerify((err, payload) => {
if (err) {
reject(err)
return
}
resolve(payload)
}))
return reply.send(request.user)
})
const response = await fastify.inject({
method: 'get',
url: '/'
})
t.assert.strictEqual(response.statusCode, 200)
t.assert.strictEqual(response.json().name, 'John Doe')
})
test('Async key provider errors should be resolved internally with cache', async function (t) {
const fastify = Fastify()
fastify.register(jwt, {
secret: {
public: async () => false
},
verify: {
extractToken: (request) => request.headers.jwt,
key: () => Promise.resolve('this secret reused from cache')
}
})
fastify.get('/', async function (request, reply) {
const signSync = createSigner({ key: 'invalid signature error' })
request.headers.jwt = signSync({ sub: '1234567890', name: 'John Doe', iat: 1516239022 })
// request.headers.jwt =
// 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
// call to plugin root level verifier
await new Promise((resolve, reject) => request.jwtVerify((err, payload) => {
if (err) {
reject(err)
return
}
resolve(payload)
}))
return reply.send(typeof request.user.then)
})
const response = await fastify.inject({
method: 'get',
url: '/'
})
t.assert.strictEqual(response.statusCode, 401)
})

3004
backend/node_modules/@fastify/jwt/test/jwt.test.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
'use strict'
const { test } = require('node:test')
const Fastify = require('fastify')
const jwt = require('../jwt')
test('Unable to add the namespace twice', async function (t) {
t.plan(1)
const fastify = Fastify()
fastify.register(jwt, { secret: 'test', namespace: 'security', jwtVerify: 'securityVerify', jwtSign: 'securitySign' })
await t.assert.rejects(() => fastify.register(jwt, { secret: 'hello', namespace: 'security', jwtVerify: 'secureVerify', jwtSign: 'secureSign' })
.ready(), new Error('JWT namespace already used "security"'))
})
test('multiple namespace', async function (t) {
const fastify = Fastify()
fastify.register(jwt, { namespace: 'aaa', secret: 'test', verify: { extractToken: (request) => request.headers.customauthheader } })
fastify.register(jwt, { namespace: 'bbb', secret: 'sea', verify: { extractToken: (request) => request.headers.customauthheader }, jwtVerify: 'verifyCustom', jwtSign: 'signCustom', jwtDecode: 'decodeCustom' })
fastify.post('/sign/:namespace', async function (request, reply) {
switch (request.params.namespace) {
case 'aaa':
return reply.aaaJwtSign(request.body)
case 'bbb':
return reply.signCustom(request.body)
default:
reply.code(501).send({ message: `Namespace ${request.params.namespace} is not implemented correctly` })
}
})
fastify.get('/verify/:namespace', async function (request, reply) {
switch (request.params.namespace) {
case 'aaa':
return request.aaaJwtVerify()
case 'bbb':
return request.verifyCustom()
default:
reply.code(501).send({ message: `Namespace ${request.params.namespace} is not implemented correctly` })
}
})
fastify.get('/decode/:namespace', async function (request, reply) {
switch (request.params.namespace) {
case 'aaa':
return request.aaaJwtDecode()
case 'bbb':
return request.decodeCustom()
default:
reply.code(501).send({ message: `Namespace ${request.params.namespace} is not implemented correctly` })
}
})
await fastify.ready()
let signResponse
let verifyResponse
signResponse = await fastify.inject({
method: 'post',
url: '/sign/aaa',
payload: { foo: 'bar' }
})
const tokenA = signResponse.payload
t.assert.ok(tokenA)
verifyResponse = await fastify.inject({
method: 'get',
url: '/verify/aaa',
headers: {
customauthheader: tokenA
}
})
t.assert.strictEqual(verifyResponse.statusCode, 200)
t.assert.strictEqual(verifyResponse.json().foo, 'bar')
verifyResponse = await fastify.inject({
method: 'get',
url: '/verify/bbb',
headers: {
customauthheader: tokenA
}
})
t.assert.strictEqual(verifyResponse.statusCode, 401)
signResponse = await fastify.inject({
method: 'post',
url: '/sign/bbb',
payload: { foo: 'sky' }
})
const tokenB = signResponse.payload
t.assert.ok(tokenB)
verifyResponse = await fastify.inject({
method: 'get',
url: '/verify/bbb',
headers: {
customauthheader: tokenB
}
})
t.assert.strictEqual(verifyResponse.statusCode, 200)
t.assert.strictEqual(verifyResponse.json().foo, 'sky')
verifyResponse = await fastify.inject({
method: 'get',
url: '/verify/aaa',
headers: {
customauthheader: tokenB
}
})
t.assert.strictEqual(verifyResponse.statusCode, 401)
const decodeResponseAAA = await fastify.inject({
method: 'get',
url: '/decode/aaa',
headers: {
customauthheader: tokenA
}
})
t.assert.strictEqual(decodeResponseAAA.statusCode, 200)
t.assert.strictEqual(decodeResponseAAA.json().foo, 'bar')
const verifyResponseBBB = await fastify.inject({
method: 'get',
url: '/decode/bbb',
headers: {
customauthheader: tokenB
}
})
t.assert.strictEqual(verifyResponseBBB.statusCode, 200)
t.assert.strictEqual(verifyResponseBBB.json().foo, 'sky')
})

147
backend/node_modules/@fastify/jwt/test/options.test.js generated vendored Normal file
View File

@@ -0,0 +1,147 @@
'use strict'
const { test } = require('node:test')
const Fastify = require('fastify')
const jwt = require('../jwt')
const { AssertionError } = require('node:assert')
test('Options validation', async function (t) {
t.plan(3)
await t.test('Options are required', async function (t) {
t.plan(1)
const fastify = Fastify()
await t.assert.rejects(() => fastify.register(jwt).ready(), new AssertionError({ expected: true, operator: '==', message: 'missing secret' }))
})
await t.test('Request method aliases', async function (t) {
t.plan(6)
await t.test('jwtDecode fail', async function (t) {
t.plan(1)
const fastify = Fastify()
await t.assert.rejects(() => fastify.register(jwt, {
secret: 'sec',
jwtDecode: true
}).ready(), new AssertionError({ expected: true, operator: '==', message: 'Invalid options.jwtDecode', actual: false }))
})
await t.test('jwtDecode success', async function (t) {
const fastify = Fastify()
await fastify.register(jwt, {
secret: 'sec',
jwtDecode: 'hello'
})
})
await t.test('jwtVerify fail', async function (t) {
t.plan(1)
const fastify = Fastify()
await t.assert.rejects(() => fastify.register(jwt, {
secret: 'sec',
jwtVerify: 123
}).ready(), new AssertionError({ expected: true, operator: '==', message: 'Invalid options.jwtVerify', actual: false }))
})
await t.test('jwtVerify success', async function (t) {
const fastify = Fastify()
await fastify.register(jwt, {
secret: 'sec',
jwtVerify: String('hello')
}).ready()
})
await t.test('jwtSign fail', async function (t) {
t.plan(1)
const fastify = Fastify()
await t.assert.rejects(() => fastify.register(jwt, {
secret: 'sec',
jwtSign: {}
}).ready(), new AssertionError({ expected: true, operator: '==', message: 'Invalid options.jwtSign', actual: false }))
})
await t.test('jwtSign success', async function (t) {
const fastify = Fastify()
await fastify.register(jwt, {
secret: 'sec',
jwtSign: ''
}).ready()
})
})
await t.test('Secret formats', async function (t) {
t.plan(2)
await t.test('RS/ES algorithm in sign options and secret as string', async function (t) {
t.plan(2)
await t.test('RS algorithm (Must return an error)', async function (t) {
t.plan(1)
const fastify = Fastify()
await t.assert.rejects(() => fastify.register(jwt, {
secret: 'test',
sign: {
algorithm: 'RS256',
aud: 'Some audience',
iss: 'Some issuer',
sub: 'Some subject'
}
}).ready(), new Error('RSA Signatures set as Algorithm in the options require a private and public key to be set as the secret'))
})
await t.test('ES algorithm (Must return an error)', async function (t) {
t.plan(1)
const fastify = Fastify()
await t.assert.rejects(() => fastify.register(jwt, {
secret: 'test',
sign: {
algorithm: 'ES256',
aud: 'Some audience',
iss: 'Some issuer',
sub: 'Some subject'
}
}).ready(), new Error('ECDSA Signatures set as Algorithm in the options require a private and public key to be set as the secret'))
})
})
await t.test('RS/ES algorithm in sign options and secret as a Buffer', async function (t) {
t.plan(2)
await t.test('RS algorithm (Must return an error)', async function (t) {
t.plan(1)
const fastify = Fastify()
await t.assert.rejects(() => fastify.register(jwt, {
secret: Buffer.from('some secret', 'base64'),
sign: {
algorithm: 'RS256',
aud: 'Some audience',
iss: 'Some issuer',
sub: 'Some subject'
}
}).ready(), new Error('RSA Signatures set as Algorithm in the options require a private and public key to be set as the secret'))
})
await t.test('ES algorithm (Must return an error)', async function (t) {
t.plan(1)
const fastify = Fastify()
await t.assert.rejects(() => fastify.register(jwt, {
secret: Buffer.from('some secret', 'base64'),
sign: {
algorithm: 'ES256',
aud: 'Some audience',
iss: 'Some issuer',
sub: 'Some subject'
}
}).ready(), new Error('ECDSA Signatures set as Algorithm in the options require a private and public key to be set as the secret'))
})
})
})
})