MongoDB Docker URI does not have hostname, domain name and tld - node.js

I am trying to connect to my local MongoDB Database that is on docker with nodejs. My component are:
.env file
MONGODB_USERNAME = 'accountUser'
MONGODB_PASSWORD = 'password'
MONGODB_HOST = 'mongodb'
MONGODB_DATABASE = 'mydb'
Code:
const uri = `mongodb+srv://${process.env.MONGODB_USERNAME}:${process.env.MONGODB_PASSWORD}#${process.env.MONGODB_HOST}/${process.env.MONGODB_DATABASE}?retryWrites=true&w=majority`;
console.log(uri);
const client = new MongoClient(uri);
Console Output
mongodb+srv://accountUser:abc123#mongodb/mydb?retryWrites=true&w=majority
Error
MongoParseError: URI does not have hostname, domain name and tld
What can I be doing wrong?

You are trying to use an SRV URI when you should be using an ordirary URI.
SRV URIs have the additional security requirements on hostnames (that it contains 3 components minimum).
Remove +srv from your URI.

1). Go to the database, click edit password and generate a new password.
2). Go to the database, click edit password and give only characters and numbers.

If the username or password includes the following characters:
: / ? # [ ] #
You should simply replace those characters.

How to connect to MongoDB Atlas from a NestJS Application:
Under Deployment select Databases
Click on your database instance
Next to the name and status of the instance click Connect
Click Connect your application
Under DRIVER select Node.js
Under VERSION select 2.2.12 or later
Copy the full URI including all of the individual nodes and use that to connect instead
As D. SM said earlier you can't use a URI with +srv in it and rolling back the driver version is the only way to get a connection string generated without +srv.

Related

MongoDB custom user roles - "user is not allowed(...)"

I created a free tier cluster on MongoDB Atlas (it has 3 shards) and I want my Node.js app to connect with a database I created there, using a specific user, that will be restricted from using any other database than the one inteded for this app.
So step by step.
I create a database called, let's say, test.
I create a role here - I go to Security -> MongoDB Roles -> Add New Custom Role and I give it all Collection actions and all Database actions and roles to test
Time for a user, so again Security -> MongoDB Users -> Add New User and I assign a previously created role to it so it has access only to test database. So now I have 2 users - atlasAdmin and my created user.
That's where the problem occurs, when I use admin user in my app to connect, .find() or .create() it works fine all the time. With a user with custom role, it works for like 10mins/1 connection (until I shut down the local server I have my node app on) and the next time I get an error that "user is not allowed to perform action (...)".
I tried everything, tinkering with a string I use to connect, updating mongoose (I use it in my app), creating user and custom role using mongodb shell but nothing seems to work.
HOWEVER:
if I have this custom user, my app connects with it to the database and it works, then on the next connection it stops working AND I go here and just click UPDATE USER without changing anything there (I just click edit next to the user and then update) then wait for the cluster to make changes, it will work again for like +/- one connection.
everything works just fine if my app uses admin account
Anyone had similar problem? Screenshot of the error I was also thinking that it might be because of how many times I try to connect with mongo from the app (I use nodemon so everytime I save a file with changes, server restarts, thus connecting to database again) but I think that's not the case - if it was, why would I be able to make it work with admin user?
The string I use to connect with mongo:
// DATABASE SETUP
var dbURL = 'mongodb://[cluster0:port],[cluster1:port],[cluster2:port]/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true';
var options = {
useNewUrlParser: true,
dbName: "test"
user: [login],
pass: [pass]
};
mongoose.connect(dbURL, options);
I have also encountered this problem on Atlas Free tier, not just on NodeJS but Java as well
For now, you can try mitigating this problem by using a default role instead of having a custom one
On the MongoDB Users tab, click "Edit" on your user => Add Default Privileges
Picture 1
Then select "readWrite" and type your database name on the first field, then save the user
Picture 2
Or, if you want database administration, add another field with "dbAdmin" role
Picture 3
At least that's how I solved it. I hope this helps.
Side note: You can also use the shorter connection string (MongoDB+SRV) and it would still work.

How to specify a schema name in the Postgres URL for connecting to a PostgreSQL database on Heroku

I am connecting my parse-server application to a PostgreSQL database hosted on the Heroku-PostgreSQL service.
My database is with a schema called gc which is different to the default public schema on Postgresql.
I used the following to connect to the database from my parse-server application.
"postgres://{USERNAME}:{PASSWORD}#{HOSTNAME_ON_AWS}:5432/{DATABASE_NAME}?ssl=true"
But the issue was it was connected to the public schema but not the gc schema I wanted.
Is there a way to specify the schema name in Postgres URL?
I don't think you can,
what you can do however is associate a schema search path with a database user, so if you want a different schema you'd need to use a different username to connect as.
SQL:
alter user fred set search_path to 'gc';
I attach the parameter options=-csearch_path=XXX to the URI. It works.
psql "postgresql://user:pwd#127.0.0.1:6789/postgres?options=-csearch_path%3Dabc"
It shows the current schema below.
postgres=> show search_path;
search_path
-------------
abc
(1 row)
And take notice that I use the URLencode for the character =. Its URL encoding is %3D. Otherwise, you can't get the correct result in the shell.
Here are some references:
https://www.postgresql.org/docs/current/libpq-connect.html
https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS

mongoDB 4.0 / Compass: No hostname or hostnames provided in connection string

After coping the URI from cloud.mongodb, I'm trying to connect via compass (1.15.1) on windows 10, but I'm getting this strange error:
No hostname or hostnames provided in connection string
This is what I've done in the process (as you may see, I've filled out the Hostname input):
1. Copied the URI:
2. Pasted inside compass:
3. Added my IP to white list
UPDATE:
After setting the SRV Record as true, the error has been changed to:
URI does not have hostname, domain name and tld
you have to first copy to clipboard the connection string and then go to the MongoDB Compass and create a new connection (Connect -> Connect to..). The software will automatically complete the fields with that you had copied.
I started it by removing 'http://' prefix from Host address.
First copy the link altas gives you .
It might be the case when you have "#" in your password field. It breaks you password and alter the url for the host.
For eg : if your password contains "#" replace it with %40
I solved my problem with this.
It might be problem from some users.
Hope it helps

Authentication error when connecting to specific mongodb database

I am currently using nodejs with mongodb native driver. So my mongodb has been set with admin auth with root role, so I can log in using robomongo or command line just fine. So back to my project, I m able to connect to mongodb just fine if i set my connection string:
mongodb://admin:password#localhost:27017/
However, if I use this connection string:
mongodb://admin:password#localhost:27017/specificdb
It return as:
MongoError: Authentication failed
I am able to access the db using command and robomongo, is there anything I can do? I have added the admin user under the db, but still got the same problem.
The database you specify is the one you authenticate on. If the user is not known/has no roles for that database it cannot authenticate to it.
https://docs.mongodb.com/manual/reference/connection-string/
What you can do is either create the (or a new) user for that database or use an authentication database parameter.
this worked for me :
first solution on connection :
mongoose.connect('mongodb://....', {
// add this line
authSource:"admin",
....
})
or second solution add to the uri "?authSource=admin" :
mongodb://user:password#host/yourDB?authSource=admin
** to note that I am using mongoose and this is the documentation specefic statement and the url :
authSource - The database to use when authenticating with user and pass. In MongoDB, users are scoped to a database. If you are getting an unexpected login failure, you may need to set this option.
https://mongoosejs.com/docs/connections.html#options

"Login failed" connecting to SQL-Azure from node.js (msnodesql)

I followed the tutorial here for building a node.js website on Azure that connects to a SQL-Azure DB:
http://www.windowsazure.com/en-us/develop/nodejs/tutorials/web-site-with-sql-database/
Here's what my .js code looks like:
var sql = require('msnodesql'),
nconf = require('nconf');
exports.authenticate = function(req, res){
var select = "select userID, clientID from users where username_e = '?' AND pwd_e = '?'";
nconf.env().file({ file: 'config.json' });
var conn = nconf.get("SQL_CONN");
console.log(conn);
sql.query(conn, select, [req.param('username'), req.param('password')], function(err, results) {
if(err)
throw err;
console.log(results);
if(results.length == 0) {
// no match
res.redirect('/login?failed=true');
} else {
// authenticated
res.redirect('/start');
}
});
return;
};
But when I run it on my local node.js, I keep getting
"Login failed for user 'mylogin'"
I copied the ODBC connection string directly from the Azure management
site
I replaced {your password here} with my password
I quadruple-checked the username and password are correct (I can successfully log into the management tools, AND I can connect to the DB fine via SQL Server Management Studio from my local)
I added an IP exception for my public IP address for good measure
I tried editing the connection string here and there (changed username to mylogin instead of mylogin#server, tried using the ADO connection string instead)
I ALSO was able to connect successfully in Java using jdbc. Here's the jdbc connection string that worked:
jdbc:sqlserver://xxxmyserver.database.windows.net:1433;DatabaseName=mydb;user=mylogin#xxxmyserver;password=pwd
And here's the node.js ODBC connection string that does not work:
Driver={SQL Server Native Client 10.0};Server=tcp:xxxmyserver.database.windows.net,1433;Database=[mydb];Uid=mylogin#xxxmyserver;Pwd=pwd;Encrypt=yes;Connection Timeout=30;
I am just completely at a loss here, especially since I can connect fine from my local using SSMS. Anyone else run into the same issue?
In case it matters, I am using node.js v0.8.2 (since that's what's on Azure's VMs) and msnodesql v0.2.1
To anyone else stumbling across this and still getting the problem even after taking out the square brackets, there's a flag you need to set in the Azure management portal to enable other Azure services to connect to your Azure SQL database. To add confusion, when you first create it, it adds your IP address to the list, which is why you seem to be able to connect to it fine from your dev machine but not from your Azure instance.
Anyway, to do this, go into the database's settings in your Azure management portal, go to 'allowed IP addresses' and enable 'Windows Azure Services' under allowed services at the bottom.
Try your query without the quotes around the question mark parameters.
var select = "select userID, clientID from users where username_e = ? AND pwd_e = ?";
Quotes are not needed for string (or any type of) parameters. Parameters are sent out of band rather than substituted directly into the query. This is what makes them so much more secure, since they are never evaluated with the SQL.
The problem was with the Database section of my connection string - the square brackets around the database name were causing the problem. The ODBC connection string Azure tells you to use looks like this:
Driver={SQL Server Native Client 10.0};Server=tcp:xxxmyserver.database.windows.net,1433;Database=[mydb];Uid=mylogin#xxxmyserver;Pwd=pwd;Encrypt=yes;Connection Timeout=30;
When instead you need to use this:
Driver={SQL Server Native Client 10.0};Server=tcp:xxxmyserver.database.windows.net,1433;Database=mydb;Uid=mylogin#xxxmyserver;Pwd=pwd;Encrypt=yes;Connection Timeout=30;
Note the lack in square brackets around the database name.
This looks like it's a bug in Azure's management tool that will hopefully go away soon. Hope this saves someone else several hours of debugging.

Resources