-
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathauth.oauthCall.controller.unit.tests.js
More file actions
166 lines (132 loc) · 6.72 KB
/
Copy pathauth.oauthCall.controller.unit.tests.js
File metadata and controls
166 lines (132 loc) · 6.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/**
* Module dependencies.
*/
import { jest, describe, test, expect, beforeEach } from '@jest/globals';
import { setupAuthControllerMocks } from './fixtures/auth-controller.mock-setup.js';
/**
* Unit tests for auth.controller oauthCall() (issue #3900).
*
* Before this guard, `oauthCall` passed `req.params.strategy` straight into
* `passport.authenticate()` with no validation and no `{ session: false }`:
* - an unknown strategy name made passport throw synchronously ("Unknown
* authentication strategy") -> 500.
* - an allowlisted-but-unregistered provider hit the same throw.
* - a registered provider defaulted to `session: true`, which fails on this
* stateless JWT stack ("Login sessions require session support").
*
* These tests verify the new isEnabledOAuthProvider() guard turns the first
* two cases into a clean 404 and never reaches passport.authenticate(), and
* that the third case delegates with `{ session: false }`.
*/
describe('auth.controller oauthCall:', () => {
let mockPassport;
beforeEach(() => {
mockPassport = setupAuthControllerMocks();
});
test('unknown strategy (not in ALLOWED_PROVIDERS) is rejected with a 404, passport.authenticate is never called', async () => {
const { default: AuthController } = await import('../../../modules/auth/controllers/auth.controller.js');
const req = { params: { strategy: 'me' } };
const res = {};
const next = jest.fn();
AuthController.oauthCall(req, res, next);
expect(mockPassport.authenticate).not.toHaveBeenCalled();
expect(next).toHaveBeenCalledTimes(1);
const err = next.mock.calls[0][0];
expect(err).toBeInstanceOf(Error);
expect(err.status).toBe(404);
expect(err.code).toBe('OAUTH_PROVIDER_NOT_FOUND');
});
test('another unknown strategy segment (e.g. "callback") is rejected with a 404', async () => {
const { default: AuthController } = await import('../../../modules/auth/controllers/auth.controller.js');
const req = { params: { strategy: 'callback' } };
const res = {};
const next = jest.fn();
AuthController.oauthCall(req, res, next);
expect(mockPassport.authenticate).not.toHaveBeenCalled();
const err = next.mock.calls[0][0];
expect(err.status).toBe(404);
expect(err.code).toBe('OAUTH_PROVIDER_NOT_FOUND');
});
test('allowlisted but unregistered provider (not enabled in config) is rejected with a 404', async () => {
// passport._strategy() returns undefined by default in this suite's mock —
// simulating a provider that is in ALLOWED_PROVIDERS but was never
// passport.use()'d at boot (e.g. missing clientID/clientSecret).
const { default: AuthController } = await import('../../../modules/auth/controllers/auth.controller.js');
const req = { params: { strategy: 'google' } };
const res = {};
const next = jest.fn();
AuthController.oauthCall(req, res, next);
expect(mockPassport._strategy).toHaveBeenCalledWith('google');
expect(mockPassport.authenticate).not.toHaveBeenCalled();
const err = next.mock.calls[0][0];
expect(err.status).toBe(404);
expect(err.code).toBe('OAUTH_PROVIDER_NOT_FOUND');
});
test('enabled + allowlisted provider delegates to passport.authenticate with { session: false }', async () => {
mockPassport._strategy.mockReturnValue({ name: 'google' }); // simulate registered strategy
const authenticateMiddleware = jest.fn();
mockPassport.authenticate.mockReturnValue(authenticateMiddleware);
const { default: AuthController } = await import('../../../modules/auth/controllers/auth.controller.js');
const req = { params: { strategy: 'google' } };
const res = {};
const next = jest.fn();
AuthController.oauthCall(req, res, next);
expect(mockPassport.authenticate).toHaveBeenCalledWith('google', { session: false });
expect(authenticateMiddleware).toHaveBeenCalledWith(req, res, next);
expect(next).not.toHaveBeenCalled();
});
test('apple (the other allowlisted provider) also delegates when registered', async () => {
mockPassport._strategy.mockReturnValue({ name: 'apple' });
const authenticateMiddleware = jest.fn();
mockPassport.authenticate.mockReturnValue(authenticateMiddleware);
const { default: AuthController } = await import('../../../modules/auth/controllers/auth.controller.js');
const req = { params: { strategy: 'apple' } };
const res = {};
const next = jest.fn();
AuthController.oauthCall(req, res, next);
expect(mockPassport.authenticate).toHaveBeenCalledWith('apple', { session: false });
expect(authenticateMiddleware).toHaveBeenCalledWith(req, res, next);
});
});
/**
* Unit tests for auth.controller oauthCallback()'s isEnabledOAuthProvider guard
* (issue #3900). The integration suite (auth.integration.tests.js) covers the
* post-authenticate handling with `_strategy`/`authenticate` both stubbed truthy;
* these tests cover the guard's reject branch specifically — an unknown or
* allowlisted-but-unregistered strategy must 404 before passport.authenticate()
* is ever reached, mirroring the oauthCall reject-path tests above.
*/
describe('auth.controller oauthCallback:', () => {
let mockPassport;
beforeEach(() => {
mockPassport = setupAuthControllerMocks();
});
test('unknown strategy (not in ALLOWED_PROVIDERS) is rejected with a 404, passport.authenticate is never called', async () => {
const { default: AuthController } = await import('../../../modules/auth/controllers/auth.controller.js');
const req = { params: { strategy: 'me' }, body: {} };
const res = {};
const next = jest.fn();
await AuthController.oauthCallback(req, res, next);
expect(mockPassport.authenticate).not.toHaveBeenCalled();
expect(next).toHaveBeenCalledTimes(1);
const err = next.mock.calls[0][0];
expect(err).toBeInstanceOf(Error);
expect(err.status).toBe(404);
expect(err.code).toBe('OAUTH_PROVIDER_NOT_FOUND');
});
test('allowlisted but unregistered provider (not enabled in config) is rejected with a 404', async () => {
// passport._strategy() returns undefined by default in this suite's mock —
// simulating a provider that is in ALLOWED_PROVIDERS but was never
// passport.use()'d at boot (e.g. missing clientID/clientSecret).
const { default: AuthController } = await import('../../../modules/auth/controllers/auth.controller.js');
const req = { params: { strategy: 'google' }, body: {} };
const res = {};
const next = jest.fn();
await AuthController.oauthCallback(req, res, next);
expect(mockPassport._strategy).toHaveBeenCalledWith('google');
expect(mockPassport.authenticate).not.toHaveBeenCalled();
const err = next.mock.calls[0][0];
expect(err.status).toBe(404);
expect(err.code).toBe('OAUTH_PROVIDER_NOT_FOUND');
});
});