-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Unknown
-
None
-
Affects Version/s: 7.2.0
-
Component/s: Authentication
-
5
-
3
-
Not Needed
-
None
-
Not Needed
-
-
None
-
None
-
None
-
None
-
None
-
None
Use Case
As a developer using the MongoDB Node.js driver on Deno,
I want SCRAM authentication to work after the Web Crypto migration in 7.2.0,
So that I can connect to MongoDB Atlas without pinning to 7.1.0.
User Experience
SCRAM auth (both SHA-1 and SHA-256) fails with `MongoServerError: Authentication failed` (code 18) on Deno with mongodb 7.2.0. Same credentials work with 7.1.0 and with mongosh. Anyone using the driver on a non-Node runtime is blocked — the only workaround is pinning to 7.1.0.
Dependencies
Introduced by PR #4862 (NODE-7379), which moved SCRAM crypto from Node.js `crypto` to Web Crypto API. `clientFirstMessageBare` was changed from `Buffer.concat` to `ByteUtils.concat`, returning a `Uint8Array` instead of a `Buffer`.
Risks/Unknowns
This is standard JavaScript behavior, not a Deno bug. `Uint8Array.toString()` returns comma-separated byte values per spec. `Buffer.toString()` returns UTF-8 because Node overrides it. Any runtime where `ByteUtils.concat` returns a plain `Uint8Array` will hit this — Deno, likely Cloudflare Workers, possibly Bun.
There may be other places in the NODE-7379 changes where `Uint8Array` values get implicitly stringified expecting UTF-8 output.
Acceptance Criteria
Implementation Requirements
In `continueScramConversation` (lib/cmap/auth/scram.ts), the `authMessage` is built by joining an array:
const authMessage = [ clientFirstMessageBare(username, nonce), // Uint8Array in 7.2.0 payload.toString('utf8'), withoutProof ].join(',');
`Array.join()` calls `.toString()` on each element. For `Buffer`, that's UTF-8 text: `"n=orders,r=..."`. For `Uint8Array`, that's comma-separated byte values: `"110,61,111,114,100,101,114,115,..."`. The SCRAM proof is computed against the wrong `authMessage`, so the server rejects it.
Fix — decode the `Uint8Array` before joining:
const authMessage = [ new TextDecoder().decode(clientFirstMessageBare(username, nonce)), payload.toString('utf8'), withoutProof ].join(',');
Confirmed by patching scram.js to log `authMessage` — the first segment was byte values instead of UTF-8 text.
Testing Requirements
- A test that verifies `authMessage` is a valid UTF-8 string when `clientFirstMessageBare` returns a `Uint8Array` (not a `Buffer`). Running SCRAM auth against a non-Node runtime in CI would catch this class of issue going forward.
- Fix existing tests so that we aren't implicitly using Buffer in our tests (our bundler was targeting node instead of web)
- Add a test to ensure that we actually don't have access to node-specific APIs that we have explicitly moved away from after filling the sandbox with the minimum required APIs
Documentation Requirements
- None — regression fix.
Follow Up Requirements
- File a ticket in the Runtime Dependencies epic to check other locations changed in
NODE-7379for implicit `.toString()` on `Uint8Array` values that were previously `Buffer`. The `xor` function was also rewritten and may have similar issues on non-Node runtimes.
- is related to
-
NODE-7571 Audit Node driver to find implicit buffer-to-string conversions
-
- Needs Triage
-