Skip to content

Commit e006347

Browse files
fix(NODE-5289): prevent scram auth from throwing TypeError if saslprep is not a function (#3727)
1 parent dc068ac commit e006347

File tree

3 files changed

+70
-124
lines changed

3 files changed

+70
-124
lines changed

src/cmap/auth/scram.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ class ScramSHA extends AuthProvider {
3434
if (!credentials) {
3535
throw new MongoMissingCredentialsError('AuthContext must provide credentials.');
3636
}
37-
if (cryptoMethod === 'sha256' && saslprep == null) {
37+
if (
38+
cryptoMethod === 'sha256' &&
39+
('kModuleError' in saslprep || typeof saslprep !== 'function')
40+
) {
3841
emitWarning('Warning: no saslprep library specified. Passwords will not be sanitized');
3942
}
4043

@@ -140,7 +143,8 @@ async function continueScramConversation(
140143

141144
let processedPassword;
142145
if (cryptoMethod === 'sha256') {
143-
processedPassword = 'kModuleError' in saslprep ? password : saslprep(password);
146+
processedPassword =
147+
'kModuleError' in saslprep || typeof saslprep !== 'function' ? password : saslprep(password);
144148
} else {
145149
processedPassword = passwordDigest(username, password);
146150
}

test/integration/auth/scram_sha_256.test.js

-122
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { expect } from 'chai';
2+
import * as sinon from 'sinon';
3+
4+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
5+
import * as deps from '../../../src/deps';
6+
import { type MongoClient } from '../../mongodb';
7+
8+
describe('SCRAM_SHA_256', function () {
9+
beforeEach(function () {
10+
if (!this.configuration.parameters.authenticationMechanisms.includes('SCRAM-SHA-256')) {
11+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
12+
this.currentTest!.skipReason = 'Test requires that SCRAM-SHA-256 be enabled on the server.';
13+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
14+
this.currentTest!.skip();
15+
}
16+
});
17+
18+
context('when saslprep is not a function', () => {
19+
let client: MongoClient;
20+
21+
beforeEach(function () {
22+
sinon.stub(deps, 'saslprep').value({});
23+
client = this.configuration.newClient({ authMechanism: 'SCRAM-SHA-256' });
24+
});
25+
26+
afterEach(() => {
27+
sinon.restore();
28+
return client.close();
29+
});
30+
31+
it('does not throw an error', { requires: { auth: 'enabled' } }, async function () {
32+
await client.connect();
33+
});
34+
35+
it('emits a warning', { requires: { auth: 'enabled' } }, async function () {
36+
const warnings: Array<Error> = [];
37+
process.once('warning', w => warnings.push(w));
38+
await client.connect();
39+
expect(warnings).to.have.lengthOf(1);
40+
expect(warnings[0]).to.have.property(
41+
'message',
42+
'Warning: no saslprep library specified. Passwords will not be sanitized'
43+
);
44+
});
45+
});
46+
47+
context('when saslprep is a function', () => {
48+
let client: MongoClient;
49+
50+
beforeEach(function () {
51+
client = this.configuration.newClient({ authMechanism: 'SCRAM-SHA-256' });
52+
});
53+
54+
afterEach(() => client.close());
55+
56+
it('calls saslprep', { requires: { auth: 'enabled' } }, async function () {
57+
const spy = sinon.spy(deps, 'saslprep');
58+
59+
await client.connect();
60+
61+
expect(spy).to.have.been.called;
62+
});
63+
});
64+
});

0 commit comments

Comments
 (0)