Skip to content

Commit

Permalink
test: Add tests for authentication strategies (#64)
Browse files Browse the repository at this point in the history
Co-authored-by: Lukas Jost <[email protected]>
  • Loading branch information
meyfa and lusu007 authored Jul 18, 2024
1 parent 9898dac commit 8807d20
Show file tree
Hide file tree
Showing 2 changed files with 179 additions and 0 deletions.
84 changes: 84 additions & 0 deletions backend/test/auth/local-strategy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { makeLocalStrategy } from '../../src/auth/local-strategy.js'
import assert from 'node:assert'

describe('auth/local-strategy.ts', () => {
describe('makeLocalStrategy()', () => {
it('has name "local"', async () => {
const strategy = await makeLocalStrategy({ username: 'admin', password: 'password' })
assert.strictEqual(strategy.name, 'local')
})

it('denies access if the admin user has no password', async () => {
const mockRequest = {
body: {
username: 'admin',
password: ''
}
}
const strategy = await makeLocalStrategy({ username: 'admin', password: '' })
const promise = new Promise<void>((resolve, reject) => {
strategy.fail = () => resolve()
strategy.success = () => reject(new Error('should not have succeeded'))
})
strategy.authenticate(mockRequest as any)
await promise
})

it('denies access if the username is incorrect', async () => {
const mockRequest = {
body: {
username: 'aaaaa',
password: 'password'
}
}
const strategy = await makeLocalStrategy({ username: 'admin', password: 'password' })
const promise = new Promise<void>((resolve, reject) => {
strategy.fail = () => resolve()
strategy.success = () => reject(new Error('should not have succeeded'))
})
strategy.authenticate(mockRequest as any)
await promise
})

it('denies access if the password is incorrect', async () => {
const mockRequest = {
body: {
username: 'admin',
password: 'wrongpassword'
}
}
const strategy = await makeLocalStrategy({ username: 'admin', password: 'password' })
const promise = new Promise<void>((resolve, reject) => {
strategy.fail = () => resolve()
strategy.success = () => reject(new Error('should not have succeeded'))
})
strategy.authenticate(mockRequest as any)
await promise
})

it('allows access if the username and password are correct', async () => {
const mockRequest = {
body: {
username: 'admin',
password: 'password'
}
}
const strategy = await makeLocalStrategy({ username: 'admin', password: 'password' })
const promise = new Promise<void>((resolve, reject) => {
strategy.fail = () => reject(new Error('should not have failed'))
strategy.success = (user, info) => {
assert.deepStrictEqual(user, {
strategy: 'local',
username: 'admin',
createdAt: user.createdAt
})
assert.ok(Math.abs(user.createdAt - Date.now()) < 1000)
assert.strictEqual(info, undefined)
resolve()
}
})
strategy.authenticate(mockRequest as any)
await promise
})
})
})
95 changes: 95 additions & 0 deletions backend/test/auth/oidc-strategy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { fastify, FastifyInstance } from 'fastify'
import { makeOidcStrategy } from '../../src/auth/oidc-strategy.js'
import assert from 'node:assert'
import { Strategy } from 'openid-client'

describe('auth/oidc-strategy.ts', () => {
describe('makeOidcStrategy()', () => {
let app: FastifyInstance | undefined

afterEach(async () => {
await app?.close()
app = undefined
})

it('performs issuer discovery', async () => {
app = fastify()
let called = false
app.get('/.well-known/openid-configuration', async (req, reply) => {
called = true
return { issuer: 'http://127.0.0.1:58080' }
})
await app.listen({ host: '127.0.0.1', port: 58080 })
const strategy = await makeOidcStrategy({
issuer: 'http://127.0.0.1:58080',
clientId: 'foobar',
clientSecret: 'bazqux',
redirectUri: 'http://localhost:3000/oidc/callback'
})
assert.ok(strategy instanceof Strategy)
assert.ok(called)
})

it('accepts issuer URL with full .well-known path', async () => {
app = fastify()
let called = false
app.get('/.well-known/openid-configuration', async (req, reply) => {
called = true
return { issuer: 'http://127.0.0.1:58080' }
})
await app.listen({ host: '127.0.0.1', port: 58080 })
const strategy = await makeOidcStrategy({
issuer: 'http://127.0.0.1:58080/.well-known/openid-configuration',
clientId: 'foobar',
clientSecret: 'bazqux',
redirectUri: 'http://localhost:3000/oidc/callback'
})
assert.ok(strategy instanceof Strategy)
assert.ok(called)
})

it('redirects unauthenticated users to the OIDC provider', async () => {
app = fastify()
app.get('/.well-known/openid-configuration', async (req, reply) => {
return {
// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
issuer: 'http://127.0.0.1:58080',
authorization_endpoint: 'http://127.0.0.1:58080/authorize',
token_endpoint: 'http://127.0.0.1:58080/token',
jwks_uri: 'http://127.0.0.1:58080/jwks',
response_types_supported: ['code']
}
})
await app.listen({ host: '127.0.0.1', port: 58080 })
const strategy = await makeOidcStrategy({
issuer: 'http://127.0.0.1:58080',
clientId: 'foobar',
clientSecret: 'bazqux',
redirectUri: 'http://localhost:3000/oidc/callback'
})
const mockRequest = {
method: 'GET',
url: '/',
body: {},
session: {}
}
const promise = new Promise<void>((resolve, reject) => {
strategy.error = (err: any) => reject(err)
strategy.fail = () => reject(new Error('should not have failed'))
strategy.success = () => reject(new Error('should not have succeeded'))
strategy.pass = () => reject(new Error('should not have passed'))
strategy.redirect = (url: string) => {
const urlObj = new URL(url)
assert.strictEqual(urlObj.origin, 'http://127.0.0.1:58080')
assert.strictEqual(urlObj.pathname, '/authorize')
assert.strictEqual(urlObj.searchParams.get('client_id'), 'foobar')
assert.strictEqual(urlObj.searchParams.get('response_type'), 'code')
assert.strictEqual(urlObj.searchParams.get('redirect_uri'), 'http://localhost:3000/oidc/callback')
resolve()
}
})
strategy.authenticate(mockRequest as any)
await promise
})
})
})

0 comments on commit 8807d20

Please sign in to comment.