Post

Improving the Node.js Driver’s SCRAM-SHA-256 Support

Cross posted from the MongoDB Blog

MongoDB always strives to offer best-in-class features, functionality, and security. A number of authentication mechanisms currently exist to verify the identity of a connecting client to your cluster, and when using the Salted Challenge Response Authentication Mechanism (SCRAM) there are two possible hashing functions: SCRAM-SHA-1 and SCRAM-SHA-256.

The MongoDB Driver Authentication Specification outlines that when attempting to authenticate using SCRAM:

“If SCRAM-SHA-256 is present in the list of mechanism, then it MUST be used as the default; otherwise, SCRAM-SHA-1 MUST be used as the default […]”.

A MongoDB Server (mongos or mongod) can be configured with a list of possible authenticationMechanisms. As a result, MongoDB can be configured to return new authentication mechanisms which can upgrade already running applications to more secure authentication. This is the case when SCRAM-SHA-256 is added to a cluster that previously only supported SCRAM-SHA-1.

Prior to hashing passwords with SHA-256, they will first be prepared using SASLprep. The MongoDB Node.js driver leverages an external library (saslprep) for this functionality, which was an optional dependency and only used if available. Though a number of checks were in place to ensure the library was available (and loaded), an edge case was found where these checks could fail and report availability incorrectly.

Potential Issue

Most applications won’t experience this issue, however if your Node.js project is being bundled using an alternate bundler (such as webpack) it’s possible a variation of this issue may surface.

If your application was affected, it would be unable to connect to your MongoDB cluster. The stack trace from the error that would be thrown should include a call to continueScramConversation similar to the following examples:

1
2
3
4
5
6
7
8
9
{
  "errorType": "TypeError",
  "errorMessage": "saslprep is not a function",
  "stack": [
    "TypeError: saslprep is not a function",
    "    at continueScramConversation ([...]/index.js:xxx:yyy)",
    [...]
  ]
}
1
2
TypeError: l is not a function
    at continueScramConversation (/app/webpack:[...]/mongodb/lib/core/auth/scram.js:xxx:yy)

Note that Mongoose applications can also be affected, as Mongoose wraps the Node.js driver:

1
2
TypeError: (0 , o.saslprep) is not a function
    at continueScramConversation (/app/webpack:[...]/mongoose/node_modules/mongodb/lib/cmap/auth/scram.js:xxx:yy)

Next Steps

The underlying issue was addressed in versions 5.7.0, 4.17.0 and 3.7.4 of the MongoDB Node.js driver, so depending on the version of the driver being used by your application a minor version update will address this.

Upgrading your application’s libraries and deploying to production may not always be possible in a timely fashion. If this is the case and you happen to hit the issue described above a workaround would be to append the authMechanism option to your connection string with a value of SCRAM-SHA-1 as follows:

1
mongodb+srv://xyz.mongodb.net/test?authMechanism=SCRAM-SHA-1

This will force the driver to attempt authorization using the SCRAM-SHA-1 hashing algorithm. Note that connection string changes would still require the application to be restarted for those changes to take effect.

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.