Mongoose: Error connection to database if the password has the characters == in mongoose 5.0.1

Created on 26 Jan 2018  路  12Comments  路  Source: Automattic/mongoose

Do you want to request a feature or report a bug?

Reporting a bug.

What is the current behavior?

If I try to connect to my database with a connection string similar to: mongodb://azureusername:[email protected]:10255/?ssl=true

I get this error: Password contains an illegal unescaped character

If the current behavior is a bug, please provide the steps to reproduce.

To reproduce the issue, you have to have a password with the character =.

What is the expected behavior?

The connection to the database should be successful.

Please mention your node.js, mongoose and MongoDB version.

MongoDB: cosmosDB with mongodb.
node.js: 9.3.0
mongoose: 5.0.1

won't fix

Most helpful comment

This is a change in the v3.0.0 release of the mongodb node driver. Use the built-in encodeURIComponent() function to encode your password if you have any characters that are reserved according to the IETF URI spec. You can also just always use encodeURIComponent() to encode your username and password, there's no harm in doing so.

All 12 comments

This is a change in the v3.0.0 release of the mongodb node driver. Use the built-in encodeURIComponent() function to encode your password if you have any characters that are reserved according to the IETF URI spec. You can also just always use encodeURIComponent() to encode your username and password, there's no harm in doing so.

Ah I see!, Thanks @vkarpov15, for some reason, I was using the encoded password, but I was getting the same error, maybe something was cached. But now it is working fine.

Thanks!

You're welcome, thanks for upgrading to 5.0.0. Feel free to report any other bugs or weirdnesses you find :+1:

@vkarpov15 Is there is a chance of getting an option to mongooose.connect(), like encodeAuth. I have several tasks that share the same config and connect like this:

   mongoose.connect(config.get('mongodb.url'), config.get('mongodb.options'));

The same code base is used with 50+ databases, so it's not easy to encode every password string. All the connections worked fine until the attempted Mongoose 5 upgrade.

If I could store the encoding preference in my connection options, I believe that would minimize the chance of a team member accidentally trying to bypass the encoding.

I'm not sure this needs to be an option. Here's a solution that I think could be used all the time with connection strings that avoids the possibility of double-encoding:

 var url = require('url');

  url.parse(urlString).format();

Whether "urlString" starts out with encoded or un-encoded auth credentials, it gets re-built with proper encoding.

Since DB connections are rarely rare, the overhead of the parse()/format() cycle should be small.

Turns out the url module is insufficent to handle MongoDB's custom URI format, but this module with parse/format it correctly:

 `mongodb-uri`

@markstos can you put your username and password in the options rather than the connection uri? You only need to encode the username and password if they're in the URI.

@vkarpov15 I represent perhaps a less common use-case. Our app is used with 60+ customer configurations. For improved security, the connection details are stored in customer-specific environment variables, where they are conveniently stored as a single string, rather than several options.

Open source software might be a similar use-case: An product that depends on Mongoose might depend on a lot of different connection strings that are not easy to update all at once.

We have already patched our code to always parse and re-encode our connection strings when we connect, but it seems like a feature that would be of interest to a number users that might more naturally live in the Mongoose project then more or less repeated throughout a number of projects that depend on Mongoose.

If I'm the only one complaining, maybe it's a rare case.

That's a reasonable use case. The problem is that unfortunately how URIs are structured changed, so if mongoose were to encode auth credentials for you then mongoose would have to support a different connection string format than the MongoDB driver does. That's something I really don't want to do unless there's a lot of demand for it, but I appreciate you pointing out this issue.

@vkarpov15 Just so it's clear

Like this?

const options = { user: 'sam', pass: 'p@ssword' };
const dbConn = mongoose.connect('mongodb://localhost', options);

I've always found the formatting of this this doc a bit confusing. The bullet list makes it look like the function actually takes that number of parameters.

@vprasanth that is correct. You make a good point, we should use a nested list for options

You can also just always use encodeURIComponent() to encode your username and password, there's no harm in doing so.

If your password is has already been encoded, calling encodeURIComponent() will double encode it, while MongoDB will only decode it once. I'm not suggesting Mongoose should do anything different here, just noting to others who find this Issue that they should be careful about this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bendytree picture bendytree  路  53Comments

fundon picture fundon  路  42Comments

dcolens picture dcolens  路  44Comments

wshaver picture wshaver  路  50Comments

saudelog picture saudelog  路  79Comments