-
Notifications
You must be signed in to change notification settings - Fork 997
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix dbAuth middleware and update tests
- Loading branch information
Showing
2 changed files
with
205 additions
and
154 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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' | ||
import { | ||
MiddlewareRequest as MWRequest, | ||
MiddlewareRequest, | ||
|
@@ -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: '[email protected]', | ||
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', | ||
|
@@ -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: '[email protected]' } | ||
}), | ||
dbAuthHandler: vi.fn(), | ||
extractRoles: vi.fn(() => ['f1driver']), | ||
} | ||
const [middleware] = initDbAuthMiddleware(options) | ||
|
||
|
@@ -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: '[email protected]', | ||
id: 'mocked-current-user-1', | ||
}, | ||
hasError: false, | ||
isAuthenticated: true, | ||
loading: false, | ||
userMetadata: { | ||
email: '[email protected]', | ||
id: 'mocked-current-user-1', | ||
}, | ||
roles: ['f1driver'], | ||
}) | ||
|
||
expect(options.extractRoles).toHaveBeenCalledWith({ | ||
currentUser: { | ||
email: '[email protected]', | ||
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: '[email protected]' } | ||
}), | ||
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: '[email protected]', | ||
id: 'mocked-current-user-1', | ||
|
@@ -90,6 +164,7 @@ describe('initDbAuthMiddleware()', () => { | |
email: '[email protected]', | ||
id: 'mocked-current-user-1', | ||
}, | ||
// No extract roles function, so it should be empty | ||
roles: [], | ||
}) | ||
|
||
|
@@ -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: '[email protected]' } } | ||
|
||
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: | ||
|
@@ -300,13 +408,12 @@ describe('initDbAuthMiddleware()', () => { | |
const req = new MWRequest(request) | ||
|
||
const options: DbAuthMiddlewareOptions = { | ||
cookieName: 'session_8911', | ||
getCurrentUser: async () => { | ||
return { user: { id: 100, email: '[email protected]' } } | ||
}, | ||
dbAuthHandler: async () => { | ||
return { | ||
body: '', | ||
body: 'getTokenResponse', | ||
headers: {}, | ||
statusCode: 200, | ||
} | ||
|
@@ -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: '[email protected]' }, | ||
}) | ||
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', | ||
|
@@ -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: '[email protected]' } }, | ||
challenge: 'challenge', | ||
|
@@ -387,7 +490,7 @@ describe('initDbAuthMiddleware()', () => { | |
}, | ||
dbAuthHandler: async () => { | ||
return { | ||
body, | ||
body: regOptionsBody, | ||
headers: {}, | ||
statusCode: 200, | ||
} | ||
|
@@ -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 () => { | ||
|
@@ -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: '[email protected]' } } | ||
|
||
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 = { | ||
|
@@ -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', | ||
|
@@ -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: '[email protected]' } } | ||
}, | ||
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: '[email protected]' }, | ||
}) | ||
}) | ||
|
||
it('handles a GET request with incorrect cookies (bad decrypt)', async () => { | ||
const request = new Request( | ||
|
Oops, something went wrong.