206 lines
5.2 KiB
JavaScript
206 lines
5.2 KiB
JavaScript
import { suite, test } from 'node:test'
|
|
import assert from 'node:assert'
|
|
import { TokenManager } from '../server/server.js'
|
|
import fs from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
const __dirname = path.dirname(__filename)
|
|
|
|
// Import the securityEnhancer to test middleware
|
|
import { securityEnhancer } from '../index.js'
|
|
|
|
suite('Bearer token middleware integration', () => {
|
|
let tempDir
|
|
let tokenManager
|
|
let middleware
|
|
let testToken
|
|
let testUser
|
|
|
|
const setup = async () => {
|
|
tempDir = path.join(__dirname, 'temp-integration-' + Date.now())
|
|
await fs.mkdir(tempDir, { recursive: true })
|
|
|
|
tokenManager = new TokenManager(tempDir)
|
|
testUser = {
|
|
displayName: 'Test User',
|
|
email: 'test@example.com',
|
|
provider: 'github',
|
|
id: '12345'
|
|
}
|
|
|
|
// Create a test token
|
|
const result = await tokenManager.createToken(testUser, 'test-token')
|
|
testToken = result.token
|
|
|
|
// Create the enhancer and get middleware
|
|
const mockLog = console.log
|
|
const mockLoga = console.log
|
|
const mockArgv = { status: tempDir }
|
|
const mockBaseHandler = {
|
|
getUser: () => null,
|
|
isAuthorized: () => false
|
|
}
|
|
|
|
const enhancer = securityEnhancer(mockLog, mockLoga, mockArgv, mockBaseHandler)
|
|
middleware = enhancer.middleware
|
|
}
|
|
|
|
const cleanup = async () => {
|
|
if (tempDir) {
|
|
await fs.rm(tempDir, { recursive: true, force: true })
|
|
}
|
|
}
|
|
|
|
test('middleware works with standard Bearer header', async () => {
|
|
await setup()
|
|
try {
|
|
const req = {
|
|
headers: {
|
|
authorization: `Bearer ${testToken}`
|
|
}
|
|
}
|
|
const res = {}
|
|
const next = () => {}
|
|
|
|
await middleware(req, res, next)
|
|
|
|
assert(req.tokenAuth)
|
|
assert.deepEqual(req.tokenAuth.user, testUser)
|
|
assert.equal(req.tokenAuth.tokenName, 'test-token')
|
|
} finally {
|
|
await cleanup()
|
|
}
|
|
})
|
|
|
|
test('middleware works with case-insensitive headers', async () => {
|
|
await setup()
|
|
try {
|
|
const testCases = [
|
|
{ authorization: `Bearer ${testToken}` },
|
|
{ Authorization: `Bearer ${testToken}` },
|
|
{ AUTHORIZATION: `Bearer ${testToken}` },
|
|
{ AuThOrIzAtIoN: `Bearer ${testToken}` }
|
|
]
|
|
|
|
for (const headers of testCases) {
|
|
const req = { headers }
|
|
const res = {}
|
|
const next = () => {}
|
|
|
|
await middleware(req, res, next)
|
|
|
|
assert(req.tokenAuth, `Failed with headers: ${JSON.stringify(headers)}`)
|
|
assert.deepEqual(req.tokenAuth.user, testUser)
|
|
}
|
|
} finally {
|
|
await cleanup()
|
|
}
|
|
})
|
|
|
|
test('middleware works with case-insensitive Bearer scheme', async () => {
|
|
await setup()
|
|
try {
|
|
const testCases = [
|
|
`Bearer ${testToken}`,
|
|
`bearer ${testToken}`,
|
|
`BEARER ${testToken}`,
|
|
`BeArEr ${testToken}`
|
|
]
|
|
|
|
for (const authValue of testCases) {
|
|
const req = {
|
|
headers: { authorization: authValue }
|
|
}
|
|
const res = {}
|
|
const next = () => {}
|
|
|
|
await middleware(req, res, next)
|
|
|
|
assert(req.tokenAuth, `Failed with auth: ${authValue}`)
|
|
assert.deepEqual(req.tokenAuth.user, testUser)
|
|
}
|
|
} finally {
|
|
await cleanup()
|
|
}
|
|
})
|
|
|
|
test('middleware works with various whitespace patterns', async () => {
|
|
await setup()
|
|
try {
|
|
const testCases = [
|
|
`Bearer ${testToken}`,
|
|
` Bearer ${testToken}`,
|
|
` Bearer ${testToken}`,
|
|
`\tBearer ${testToken}`,
|
|
`Bearer ${testToken}`,
|
|
`Bearer ${testToken}`,
|
|
`Bearer\t${testToken}`,
|
|
` Bearer ${testToken} `,
|
|
`\tBEARER\t\t${testToken}\t`
|
|
]
|
|
|
|
for (const authValue of testCases) {
|
|
const req = {
|
|
headers: { authorization: authValue }
|
|
}
|
|
const res = {}
|
|
const next = () => {}
|
|
|
|
await middleware(req, res, next)
|
|
|
|
assert(req.tokenAuth, `Failed with auth: "${authValue}"`)
|
|
assert.deepEqual(req.tokenAuth.user, testUser)
|
|
}
|
|
} finally {
|
|
await cleanup()
|
|
}
|
|
})
|
|
|
|
test('middleware rejects invalid schemes and formats', async () => {
|
|
await setup()
|
|
try {
|
|
const testCases = [
|
|
`Basic ${testToken}`,
|
|
`Digest ${testToken}`,
|
|
`OAuth ${testToken}`,
|
|
`Bearer`,
|
|
`Bearerabc123`,
|
|
``,
|
|
`NotBearer ${testToken}`,
|
|
`Bearer${testToken}` // No space
|
|
]
|
|
|
|
for (const authValue of testCases) {
|
|
const req = {
|
|
headers: { authorization: authValue }
|
|
}
|
|
const res = {}
|
|
const next = () => {}
|
|
|
|
await middleware(req, res, next)
|
|
|
|
assert(!req.tokenAuth, `Should have failed with auth: "${authValue}"`)
|
|
}
|
|
} finally {
|
|
await cleanup()
|
|
}
|
|
})
|
|
|
|
test('middleware handles missing authorization header gracefully', async () => {
|
|
await setup()
|
|
try {
|
|
const req = { headers: {} }
|
|
const res = {}
|
|
const next = () => {}
|
|
|
|
await middleware(req, res, next)
|
|
|
|
assert(!req.tokenAuth)
|
|
} finally {
|
|
await cleanup()
|
|
}
|
|
})
|
|
})
|