Skip to content

Commit

Permalink
Fix dbAuth middleware and update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dac09 committed May 22, 2024
1 parent 71fd715 commit 5f47249
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from 'node:path'

import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'

import { dbAuthSession } from '@redwoodjs/auth-dbauth-api'

Check failure on line 5 in packages/auth-providers/dbAuth/middleware/src/__tests__/initDbAuthMiddleware.test.ts

View workflow job for this annotation

GitHub Actions / 🏗 Build, lint, test / ubuntu-latest / node 20 latest

'dbAuthSession' is defined but never used. Allowed unused vars must match /^_/u
import {
MiddlewareRequest as MWRequest,
MiddlewareRequest,
Expand All @@ -18,13 +19,36 @@ const FIXTURE_PATH = path.resolve(

beforeAll(() => {
process.env.RWJS_CWD = FIXTURE_PATH

// Mock the session decryption
vi.mock('@redwoodjs/auth-dbauth-api', async (importOriginal) => {
const original = (await importOriginal()) as any
return {
...original,
dbAuthSession: vi.fn().mockImplementation((req, cookieName) => {
if (
req.headers
.get('Cookie')
.includes(`${cookieName}=this_is_the_only_correct_session`)
) {
return {
currentUser: {
email: 'user-1@example.com',
id: 'mocked-current-user-1',
},
mockedSession: 'this_is_the_only_correct_session',
}
}
}),
}
})
})

afterAll(() => {
delete process.env.RWJS_CWD
})

describe('initDbAuthMiddleware()', () => {
describe('dbAuthMiddleware', () => {
it('When no cookie headers, pass through the response', async () => {
const options: DbAuthMiddlewareOptions = {
cookieName: '8911',
Expand Down Expand Up @@ -53,15 +77,14 @@ describe('initDbAuthMiddleware()', () => {
})

it('When it has a cookie header, decrypts and sets server auth context', async () => {
const cookieHeader =
'session=ko6iXKV11DSjb6kFJ4iwcf1FEqa5wPpbL1sdtKiV51Y=|cQaYkOPG/r3ILxWiFiz90w=='
const cookieHeader = 'session=this_is_the_only_correct_session'

const options: DbAuthMiddlewareOptions = {
cookieName: '8911',
getCurrentUser: vi.fn(async () => {
return { id: 'mocked-current-user-1', email: 'user-1@example.com' }
}),
dbAuthHandler: vi.fn(),
extractRoles: vi.fn(() => ['f1driver']),
}
const [middleware] = initDbAuthMiddleware(options)

Expand All @@ -77,8 +100,59 @@ describe('initDbAuthMiddleware()', () => {
const res = await middleware(mwReq, MiddlewareResponse.next())

expect(mwReq.serverAuthState.get()).toEqual({
cookieHeader:
'session=ko6iXKV11DSjb6kFJ4iwcf1FEqa5wPpbL1sdtKiV51Y=|cQaYkOPG/r3ILxWiFiz90w==',
cookieHeader: 'session=this_is_the_only_correct_session',
currentUser: {
email: 'user-1@example.com',
id: 'mocked-current-user-1',
},
hasError: false,
isAuthenticated: true,
loading: false,
userMetadata: {
email: 'user-1@example.com',
id: 'mocked-current-user-1',
},
roles: ['f1driver'],
})

expect(options.extractRoles).toHaveBeenCalledWith({
currentUser: {
email: 'user-1@example.com',
id: 'mocked-current-user-1',
},
mockedSession: 'this_is_the_only_correct_session',
})

// Allow react render, because body is not defined, and status code not redirect
expect(res).toHaveProperty('body', undefined)
expect(res).toHaveProperty('status', 200)
})

it('Will use the cookie name option correctly', async () => {
const cookieHeader = 'bazinga_8911=this_is_the_only_correct_session'

const options: DbAuthMiddlewareOptions = {
getCurrentUser: vi.fn(async () => {
return { id: 'mocked-current-user-1', email: 'user-1@example.com' }
}),
dbAuthHandler: vi.fn(),
cookieName: 'bazinga_%port%',
}
const [middleware] = initDbAuthMiddleware(options)

const mwReq = new MiddlewareRequest(
new Request('http://bazinga.new/kittens', {
method: 'GET',
headers: {
Cookie: cookieHeader,
},
}),
)

const res = await middleware(mwReq, MiddlewareResponse.next())

expect(mwReq.serverAuthState.get()).toEqual({
cookieHeader: 'bazinga_8911=this_is_the_only_correct_session',
currentUser: {
email: 'user-1@example.com',
id: 'mocked-current-user-1',
Expand All @@ -90,6 +164,7 @@ describe('initDbAuthMiddleware()', () => {
email: 'user-1@example.com',
id: 'mocked-current-user-1',
},
// No extract roles function, so it should be empty
roles: [],
})

Expand All @@ -98,6 +173,39 @@ describe('initDbAuthMiddleware()', () => {
expect(res).toHaveProperty('status', 200)
})

it('handles a currentUser request', async () => {
const cookieHeader = 'session=this_is_the_only_correct_session'
const request = new Request(
'http://localhost:8910/middleware/dbauth/currentUser',
{
method: 'GET',
headers: {
Cookie: cookieHeader,
},
},
)

const req = new MWRequest(request)
const cookie = req.headers.get('Cookie')

expect(cookie).toBe(cookieHeader)

const currentUser = { user: { id: 100, email: 'currentUser@example.com' } }

const options: DbAuthMiddlewareOptions = {
getCurrentUser: async () => {
return currentUser
},
dbAuthHandler: vi.fn(),
}
const [middleware] = initDbAuthMiddleware(options)

const res = await middleware(req, MiddlewareResponse.next())

expect(res).toBeDefined()
expect(res?.body).toBe(JSON.stringify({ currentUser }))
})

describe('handle all supported dbAuth verbs (aka methods) and their HTTP methods', async () => {
/**
* Supported verbs and their corresponding HTTP methods:
Expand Down Expand Up @@ -300,13 +408,12 @@ describe('initDbAuthMiddleware()', () => {
const req = new MWRequest(request)

const options: DbAuthMiddlewareOptions = {
cookieName: 'session_8911',
getCurrentUser: async () => {
return { user: { id: 100, email: 'tolkienUser@example.com' } }
},
dbAuthHandler: async () => {
return {
body: '',
body: 'getTokenResponse',
headers: {},
statusCode: 200,
}
Expand All @@ -316,14 +423,9 @@ describe('initDbAuthMiddleware()', () => {

const res = await middleware(req, MiddlewareResponse.next())
expect(res).toBeDefined()

const serverAuthState = req.serverAuthState.get()
expect(serverAuthState.isAuthenticated).toBe(true)
expect(serverAuthState.currentUser).toEqual({
user: { id: 100, email: 'tolkienUser@example.com' },
})
expect(serverAuthState.cookieHeader).toBe(cookieHeader)
expect(res?.body).toBe('getTokenResponse')
})

it('handles a validateResetToken request', async () => {
const request = new Request(
'http://localhost:8911/middleware/dbauth/auth?method=validateResetToken',
Expand Down Expand Up @@ -361,8 +463,9 @@ describe('initDbAuthMiddleware()', () => {
const serverAuthState = req.serverAuthState.get()
expect(serverAuthState.isAuthenticated).toBe(false)
})

it('handles a webAuthnRegOptions request', async () => {
const body = JSON.stringify({
const regOptionsBody = JSON.stringify({
r: { id: 1 },
user: { user: { id: 100, email: 'user@example.com' } },
challenge: 'challenge',
Expand All @@ -387,7 +490,7 @@ describe('initDbAuthMiddleware()', () => {
},
dbAuthHandler: async () => {
return {
body,
body: regOptionsBody,
headers: {},
statusCode: 200,
}
Expand All @@ -396,10 +499,7 @@ describe('initDbAuthMiddleware()', () => {
const [middleware] = initDbAuthMiddleware(options)

const res = await middleware(req, MiddlewareResponse.next())
expect(res).toBeDefined()
// should the body be the webAuth reg options?
// but get requests need a cookie to be set?
// expect(res?.body).toBeDefined()
expect(res?.body).toBe(regOptionsBody)
})
// @todo: implement the following tests when try out webAuth
// it('handles a webAuthnRegister', async () => {
Expand All @@ -412,49 +512,6 @@ describe('initDbAuthMiddleware()', () => {
// //: 'POST',
// })
})
it('handles a currentUser request', async () => {
// encrypted session taken fom dbAuth tests
// I cannot figure out why the header here has to be session
// but the cookieName session_8911 to work properly
const cookieHeader =
'session=ko6iXKV11DSjb6kFJ4iwcf1FEqa5wPpbL1sdtKiV51Y=|cQaYkOPG/r3ILxWiFiz90w=='
const request = new Request(
'http://localhost:8911/middleware/dbauth/currentUser',
{
method: 'GET',
headers: {
Cookie: cookieHeader,
},
},
)

const req = new MWRequest(request)
const cookie = req.headers.get('Cookie')

expect(cookie).toBe(cookieHeader)

const currentUser = { user: { id: 100, email: 'currentUser@example.com' } }

const options: DbAuthMiddlewareOptions = {
cookieName: 'session_8911',
getCurrentUser: async () => {
return currentUser
},
dbAuthHandler: async () => {
return {
body: '',
headers: {},
statusCode: 200,
}
},
}
const [middleware] = initDbAuthMiddleware(options)

const res = await middleware(req, MiddlewareResponse.next())

expect(res).toBeDefined()
expect(res?.body).toBe(JSON.stringify({ currentUser }))
})

describe('handle exception cases', async () => {
const unauthenticatedServerAuthState = {
Expand All @@ -463,6 +520,11 @@ describe('initDbAuthMiddleware()', () => {
roles: [],
}

beforeAll(() => {
// So that we don't see errors in console when running negative cases
vi.spyOn(console, 'error').mockImplementation(() => {})
})

it('handles a POST that is not one of the supported dbAuth verbs and still build headers when passing along the request', async () => {
const request = new Request(
'http://localhost:8911/middleware/dbauth/unsupportedVerb',
Expand Down Expand Up @@ -502,48 +564,6 @@ describe('initDbAuthMiddleware()', () => {
const serverAuthState = req.serverAuthState.get()
expect(serverAuthState).toHaveProperty('isAuthenticated', false)
})
it('handles a GET request with correct cookies', async () => {
// encrypted session taken fom dbAuth tests
// I cannot figure out why the header here has to be session
// but the cookieName session_8911 to work properly
const cookieHeader =
'session=ko6iXKV11DSjb6kFJ4iwcf1FEqa5wPpbL1sdtKiV51Y=|cQaYkOPG/r3ILxWiFiz90w=='
const request = new Request('http://localhost:8911/functions/hello', {
method: 'GET',
headers: {
Cookie: cookieHeader,
},
})

const req = new MWRequest(request)
const cookie = req.headers.get('Cookie')

expect(cookie).toBe(cookieHeader)

const options: DbAuthMiddlewareOptions = {
cookieName: 'session_8911',
getCurrentUser: async () => {
return { user: { id: 100, email: 'hello@example.com' } }
},
dbAuthHandler: async () => {
return {
body: '',
headers: {},
statusCode: 200,
}
},
}
const [middleware] = initDbAuthMiddleware(options)

const res = await middleware(req, MiddlewareResponse.next())
const serverAuthState = req.serverAuthState.get()

expect(res).toBeDefined()
expect(serverAuthState.isAuthenticated).toBe(true)
expect(serverAuthState.currentUser).toEqual({
user: { id: 100, email: 'hello@example.com' },
})
})

it('handles a GET request with incorrect cookies (bad decrypt)', async () => {
const request = new Request(
Expand Down
Loading

0 comments on commit 5f47249

Please sign in to comment.