Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions packages/middleware/auth-express-middleware/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ export default {
testEnvironment: 'node',
testPathIgnorePatterns: ['dist/'],
modulePathIgnorePatterns: ['<rootDir>/dist/'], // Add this to ignore dist/ for module mapping
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1'
},
transform: {
'^.+\\.ts$': ['ts-jest', {
diagnostics: false,
tsconfig: {
moduleResolution: 'node',
strict: false,
strictNullChecks: false,
noImplicitAny: false
}
}]
},
// Integration tests use fixed ports and multi-round-trip auth protocol
// exchanges that require sequential execution to avoid worker event-loop
// scheduling issues and port conflicts.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ import {
*/
export class MockWallet extends ProtoWallet
implements WalletInterface {

keyDeriver: KeyDeriver
constructor(rootKeyOrKeyDeriver: PrivateKey | 'anyone' | KeyDeriverApi) {
constructor (rootKeyOrKeyDeriver: PrivateKey | 'anyone' | KeyDeriverApi) {
super(rootKeyOrKeyDeriver)

if (rootKeyOrKeyDeriver instanceof KeyDeriver) {
Expand Down Expand Up @@ -110,16 +109,15 @@ export class MockWallet extends ProtoWallet
/**
* Add a master certificate to the wallet for testing purposes.
*/
addMasterCertificate(masterCertificate: MasterCertificate): void {
addMasterCertificate (masterCertificate: MasterCertificate): void {
this.storedCertificates.push(masterCertificate)
}


/**
* Given a certificate and fields to reveal, this method creates a keyring
* for the verifier by leveraging the masterCertificate’s capabilities.
*/
async proveCertificate(args: ProveCertificateArgs, originator?: OriginatorDomainNameStringUnder250Bytes): Promise<ProveCertificateResult> {
async proveCertificate (args: ProveCertificateArgs, originator?: OriginatorDomainNameStringUnder250Bytes): Promise<ProveCertificateResult> {
const storedCert = this.storedCertificates.find(sc =>
sc.type === args.certificate.type &&
sc.subject === args.certificate.subject &&
Expand Down Expand Up @@ -149,15 +147,15 @@ export class MockWallet extends ProtoWallet
* Mock implementation of internalizeAction.
* Logs the provided action details and returns a successful response.
*/
async internalizeAction(args: InternalizeActionArgs, originator?: OriginatorDomainNameStringUnder250Bytes): Promise<InternalizeActionResult> {
async internalizeAction (args: InternalizeActionArgs, originator?: OriginatorDomainNameStringUnder250Bytes): Promise<InternalizeActionResult> {
console.log('Mock internalizeAction called with:', { args, originator })
return await Promise.resolve({ accepted: true })
}

/**
* Returns any certificates whose certifier and type match the requested sets.
*/
async listCertificates(args: ListCertificatesArgs,
async listCertificates (args: ListCertificatesArgs,
originator?: OriginatorDomainNameStringUnder250Bytes): Promise<ListCertificatesResult> {
// Filter certificates by requested certifiers and types
const filtered = this.storedCertificates.filter(cert => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
PrivateKey,
RequestedCertificateTypeIDAndFieldList,
Utils,
AuthFetch,
AuthFetch
} from '@bsv/sdk'
import { Server } from 'http'
import { startServer } from './testExpressServer'
Expand Down Expand Up @@ -101,9 +101,9 @@ describe('AuthFetch and AuthExpress Integration Tests', () => {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
'x-bsv-test': 'this is a test header',
'x-bsv-test': 'this is a test header'
},
body: new URLSearchParams({ message: 'hello!', type: 'form-data' }).toString(),
body: new URLSearchParams({ message: 'hello!', type: 'form-data' }).toString()
}
)
expect(result.status).toBe(200)
Expand All @@ -120,9 +120,9 @@ describe('AuthFetch and AuthExpress Integration Tests', () => {
method: 'POST',
headers: {
'content-type': 'text/plain',
'x-bsv-test': 'this is a test header',
'x-bsv-test': 'this is a test header'
},
body: 'Hello, this is a plain text message!',
body: 'Hello, this is a plain text message!'
}
)
expect(result.status).toBe(200)
Expand All @@ -139,9 +139,9 @@ describe('AuthFetch and AuthExpress Integration Tests', () => {
method: 'POST',
headers: {
'content-type': 'application/octet-stream',
'x-bsv-test': 'this is a test header',
'x-bsv-test': 'this is a test header'
},
body: Utils.toArray('Hello from binary!'),
body: Utils.toArray('Hello from binary!')
}
)
expect(result.status).toBe(200)
Expand Down Expand Up @@ -182,9 +182,9 @@ describe('AuthFetch and AuthExpress Integration Tests', () => {
method: 'PUT',
headers: {
'content-type': 'application/json',
'x-bsv-test': 'this is a test header',
'x-bsv-test': 'this is a test header'
},
body: JSON.stringify({ key: 'value', action: 'update' }),
body: JSON.stringify({ key: 'value', action: 'update' })
}
)
expect(result.status).toBe(200)
Expand All @@ -200,7 +200,7 @@ describe('AuthFetch and AuthExpress Integration Tests', () => {
{
method: 'DELETE',
headers: {
'x-bsv-test': 'this is a test header',
'x-bsv-test': 'this is a test header'
}
}
)
Expand All @@ -216,7 +216,7 @@ describe('AuthFetch and AuthExpress Integration Tests', () => {
const result = await authFetch.fetch('http://localhost:3000/large-upload', {
method: 'POST',
headers: {
'content-type': 'application/octet-stream',
'content-type': 'application/octet-stream'
},
body: largeBuffer
})
Expand All @@ -242,15 +242,14 @@ describe('AuthFetch and AuthExpress Integration Tests', () => {
const result = await authFetch.fetch('http://localhost:3000/custom-headers', {
method: 'GET',
headers: {
'x-bsv-custom-header': 'CustomHeaderValue',
'x-bsv-custom-header': 'CustomHeaderValue'
}
})
expect(result.status).toBe(200)
const textResponse = await result.text()
expect(textResponse).toBeDefined()
})


// --------------------------------------------------------------------------
// Edge-Case Tests
// --------------------------------------------------------------------------
Expand All @@ -262,7 +261,7 @@ describe('AuthFetch and AuthExpress Integration Tests', () => {
authFetch.fetch('http://localhost:3000/no-content-type-endpoint', {
method: 'POST',
// Intentionally no 'content-type' header
body: 'This should fail if your code requires Content-Type for POST.',
body: 'This should fail if your code requires Content-Type for POST.'
})
).rejects.toThrow()
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
}

const privKey = new PrivateKey(2)
const mockWallet = new MockWallet(privKey);
const mockWallet = new MockWallet(privKey)

// Asynchronous setup for certificates — exposed as server.ready
const ready = (async () => {
Expand Down Expand Up @@ -79,7 +79,7 @@
})

// Add the mutual authentication middleware
app.use(authMiddleware)

Check failure

Code scanning / CodeQL

Missing rate limiting High test

This route handler performs
authorization
, but is not rate-limited.

app.get('/', (req: Request, res: Response) => {
res.send('Hello, world!')
Expand All @@ -87,7 +87,7 @@

app.post('/cert-protected-endpoint', async (req: Request, res: Response) => {
console.log('Received POST body:', req.body)
//wait a moment for the certificates to be received
// wait a moment for the certificates to be received
await new Promise(resolve => {
const t = setTimeout(resolve, 5000)
if (typeof t.unref === 'function') t.unref()
Expand All @@ -111,7 +111,7 @@

const server = app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`)
}) as ReturnType<typeof app.listen> & { ready: Promise<void> }
})
server.ready = ready
return server
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
PrivateKey,
RequestedCertificateTypeIDAndFieldList,
AuthFetch,
MasterCertificate,
MasterCertificate
} from '@bsv/sdk'
import { Server } from 'http'
import { startCertServer } from './testCertExpressServer'
Expand Down Expand Up @@ -61,14 +61,13 @@ describe('AuthFetch and AuthExpress Certificates Tests', () => {
})
})


test('Test 12: Certificate request', async () => {
const requestedCertificates: RequestedCertificateSet = {
certifiers: [
'03caa1baafa05ecbf1a5b310a7a0b00bc1633f56267d9f67b1fd6bb23b3ef1abfa',
'03caa1baafa05ecbf1a5b310a7a0b00bc1633f56267d9f67b1fd6bb23b3ef1abfa'
],
types: {
'z40BOInXkI8m7f/wBrv4MJ09bZfzZbTj2fJqCtONqCY=': ['firstName'],
'z40BOInXkI8m7f/wBrv4MJ09bZfzZbTj2fJqCtONqCY=': ['firstName']
}
}
const walletWithRequests = new MockWallet(privKey)
Expand All @@ -85,7 +84,6 @@ describe('AuthFetch and AuthExpress Certificates Tests', () => {
// Add further assertions based on expected certificates
}, 30000)


test('Test 16: Simple POST on /cert-protected-endpoint', async () => {
const walletWithCerts = new MockWallet(privKey)

Expand All @@ -106,18 +104,18 @@ describe('AuthFetch and AuthExpress Certificates Tests', () => {
try {
res = await authFetch.fetch(
'http://localhost:3001/cert-protected-endpoint', {
method: 'POST', headers: {
'content-type': 'application/json'
},
body: JSON.stringify({ message: 'Hello protected Route!' })
})
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({ message: 'Hello protected Route!' })
})
} catch (error) {
console.error('Error during fetch:', error)
}
expect(res!.status).toBe(200)
const body = await res!.text()
expect(res.status).toBe(200)
const body = await res.text()
expect(body).toBeDefined()
console.log(body)

}, 300000)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
}

const privKey = new PrivateKey(1)
const mockWallet = new MockWallet(privKey);
const mockWallet = new MockWallet(privKey)
const sessionManager = new SessionManager();

// Asynchronous setup for certificates and middleware
Expand Down Expand Up @@ -92,12 +92,12 @@
sessionManager,
onCertificatesReceived: (_senderPublicKey: string, certs: VerifiableCertificate[], req: Request, res: Response, next: NextFunction) => {
console.log('Certificates received:', certs)
},
}
// certificatesToRequest
})

// Add the mutual authentication middleware
app.use(authMiddleware)

Check failure

Code scanning / CodeQL

Missing rate limiting High test

This route handler performs
authorization
, but is not rate-limited.

app.get('/', (req: Request, res: Response) => {
res.send('Hello, world!')
Expand All @@ -119,9 +119,9 @@
res.status(200).send({ message: 'This is another endpoint. 😅' })
})

app.post('/cert-protected-endpoint', (req: Request, res: Response) => {
console.log('Received POST body:', req.body)
res.status(200).send({ message: 'You must have certs!' })
app.post('/cert-protected-endpoint', (req: Request, res: Response) => {
console.log('Received POST body:', req.body)
res.status(200).send({ message: 'You must have certs!' })
// await (res as any).sendCertificateRequest(certsToRequest, identityKey)
})

Expand Down
Loading
Loading