Skip to content

Commit 7a4ffee

Browse files
committed
test: add preliminary oidc auth tests
1 parent c495d36 commit 7a4ffee

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

test/testOidcAuth.test.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
const chai = require('chai');
2+
const expect = chai.expect;
3+
const sinon = require('sinon');
4+
const proxyquire = require('proxyquire');
5+
6+
describe('OIDC auth method', () => {
7+
let dbStub, passportStub, discoveryStub, fetchUserInfoStub, StrategyStub, strategyCallback;
8+
9+
const configStub = {
10+
getAuthMethods: () => ([
11+
{
12+
type: 'openidconnect',
13+
oidcConfig: {
14+
issuer: 'https://test.com',
15+
clientID: 'test-client-id',
16+
clientSecret: 'test-client-secret',
17+
callbackURL: 'http://localhost:3000/auth/callback',
18+
scope: 'openid profile email',
19+
}
20+
}
21+
])
22+
};
23+
24+
const mockUserInfo = {
25+
sub: 'test-sub',
26+
27+
name: 'Test User',
28+
};
29+
30+
beforeEach(async () => {
31+
dbStub = {
32+
findUserByOIDC: sinon.stub(),
33+
createUser: sinon.stub(),
34+
};
35+
36+
passportStub = {
37+
use: sinon.stub(),
38+
serializeUser: sinon.stub(),
39+
deserializeUser: sinon.stub(),
40+
};
41+
42+
discoveryStub = sinon.stub().resolves({});
43+
fetchUserInfoStub = sinon.stub().resolves(mockUserInfo);
44+
45+
StrategyStub = class {
46+
constructor(options, callback) {
47+
strategyCallback = callback;
48+
this.options = options;
49+
}
50+
51+
name = 'oidc';
52+
authenticate = () => {};
53+
};
54+
55+
const { configure } = proxyquire('../src/service/passport/oidc', {
56+
'../../db': dbStub,
57+
'../../config': configStub,
58+
'openid-client': {
59+
discovery: discoveryStub,
60+
fetchUserInfo: fetchUserInfoStub,
61+
},
62+
'openid-client/passport': {
63+
Strategy: StrategyStub,
64+
}
65+
});
66+
67+
await configure(passportStub);
68+
})
69+
70+
it('should authenticate a new user and create them in the DB', async () => {
71+
if (!strategyCallback) {
72+
throw new Error('strategyCallback is not defined');
73+
}
74+
75+
dbStub.findUserByOIDC.resolves(null); // same result as new user flow
76+
dbStub.createUser.resolves({
77+
username: 'test',
78+
79+
oidcId: 'test-sub'
80+
});
81+
82+
const done = sinon.spy();
83+
84+
// Workaround for the async callback
85+
await new Promise((resolve, reject) => {
86+
strategyCallback({
87+
claims: () => ({ sub: 'test-sub' }),
88+
email: '[email protected]',
89+
name: 'Test User'
90+
}, (...args) => {
91+
done(...args);
92+
resolve();
93+
});
94+
});
95+
96+
expect(done.calledOnce).to.be.true;
97+
98+
const [err, user] = done.firstCall.args;
99+
expect(err).to.be.null;
100+
expect(user).to.have.property('username', 'test');
101+
expect(user).to.have.property('email', '[email protected]');
102+
expect(user).to.have.property('oidcId', 'test-sub');
103+
104+
expect(dbStub.createUser.calledOnce).to.be.true;
105+
expect(dbStub.createUser.firstCall.args[0]).to.equal('test');
106+
});
107+
108+
it('should return an existing user from the DB', async () => {
109+
if (!strategyCallback) {
110+
throw new Error('strategyCallback is not defined');
111+
}
112+
113+
const existingUser = {
114+
username: 'existing',
115+
116+
oidcId: 'test-sub'
117+
};
118+
dbStub.findUserByOIDC.resolves(existingUser);
119+
120+
const done = sinon.spy();
121+
122+
await strategyCallback({ claims: () => ({ sub: 'test-sub' }), access_token: 'access' }, done);
123+
124+
expect(done.calledOnce).to.be.true;
125+
const [err, user] = done.firstCall.args;
126+
expect(err).to.be.null;
127+
expect(user).to.deep.equal(existingUser);
128+
129+
expect(dbStub.createUser.notCalled).to.be.true;
130+
});
131+
});

0 commit comments

Comments
 (0)