Authentication error when connecting to specific mongodb database - node.js

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

Related

How to delete a database using node.js and MongoDB Atlas?

I'm new to MongoDB and node.js and I want to know how to delete a database.
I've searched for and I found that it is done with the dropDatabase() method. The problem is that it shows a MongoError: user is not allowed to do action [dropDatabase] on [test.]. I also searched for this error and the answer I found is that the user needs to be registered as Data Access Read Write. However, my user in mongo atlas is registred as Project Owner and as the answer says. I removed Project Owner and it still displays the error.
MongoClient.connect(uri, { useNewUrlParser: true }, (err, client)=>{
if(err) throw err;
console.log("Connected...");
const db = client.db("test");
db.dropDatabase();
console.log("asdfghj")
client.close();
});
In fact, whenever i searched to fix the problem typing Mongo atlas in the search bar, the results are like How to delete cluster in mongo atlas even though i'm typing delete database in mongo atlas. So i don't know if a database can be deleted in mongo atlas.
Thank you in advance.
Looks like you are confusing "Atlas Project" security with "Database Access".
If you are looking for removing a database from an Atlas Cluster, the "Database User" you are using to login in your Mongo Client needs to have "dbAdmin" role in the related database. You can then perform related operations using your database user via your Mongo client programmatically.
You can refer to https://docs.atlas.mongodb.com/security-add-mongodb-users/ for managing database users and security roles.
You can log into Atlas, click the cluster name, click the "collections" tab, then when you hover over the database name on the left, there will appear a garbage can icon, which will delete the DB (assuming your user has proper permissions)
If you want to delete the db in code, there's no way to do it directly from mongoose, but you can if you access the underlying mongodb driver:
mongoose.connection.db.dropDatabase(cb)

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

Relation does not exist error with pg-promise and postgresql?

I am using pg-promise on Node 7.2.1 with PostgreSQL 9.4. I am using the code below to connect to the PostgreSQL server:
// pg-promise connection elements.
// Database initialization options.
const pg_options = {
// Initialization options.
};
// Create an instance of the pg-promise library.
const g_pg_promise = require('pg-promise')(pg_options);
// Connection string for a local connection to the 'summarize' database.
const g_pg_connection =
{
host: 'localhost',
port: 5432,
database: 'db_stats',
user: 'db_user',
password: '{password here}'
}
// Connect to the database.
const g_pg_database = g_pg_promise(g_pg_connection);
// Expose the database object globally. The database object should only
// be instantiated once and then shared.
module.exports = {
g_pg_promise: g_pg_promise,
g_pg_database: g_pg_database
};
I know the connection parameters are valid because I use the exact same values in other non-Node.JS apps to connect to the same PostgreSQL server. I also know that db_stats is a valid database name. I have worked with that database for quite a while with other non Node.JS apps and via pgAdmin 3.x.
However, when I attempt to connect using pg-promise I get the following error:
error: relation "db_stats" does not exist
I did see the SO post below:
Unable to query PostgreSQL database in NodeJS using pg-promise - "relation does not exist"
But that post did not make sense to me because I believe Vitaly, the author of pg-promise, was telling the poster that he did not have a table called users, when it looks to me that the poster was trying to access the database called users and he definitely had a database with that name.
In any case, I definitely have a database named db_stats so I'm not sure why I am getting this error. How can I solve this?
error: relation "db_stats" does not exist
The error you get from PostgreSQL is not referring to a database named "db_stats", but to a relation (either a table or a view) with that name.
That is, db_stats most probably appears in the FROM clause of a SELECT query (although it may be also a INSERT, UPDATE, DELETE, ...).
There is neither a db_stats table nor a view in your database. Or, maybe, it exists, but it exists in a schema that is not part of your current search_path.
To find out, check two things:
SELECT
*
FROM
information_schema.tables
WHERE
table_name = 'db_stats' ;
If there is a table there... you already know which schema(s) contains it/them.
Then, make sure that this schema is part of your search_path by means of:
SHOW search_path ;
You might have to execute this SQL statements by adding the adequate code to your application, and use a debugger to check what's returned in that environment.

Mongodb authentication shell/ console

I have a Node JS program, which uses Mongo DB as my dbs. Now... everyone can access the mongo shell with no issues at all.
Is this how it is meant to be? I want to keep the mongo shell away from anyone else, i.e. you have to authenticate before using the shell.The reason being is that I dont want people deleting tables in the database, and insert/ modifying documents through the console.
Is there a way to do this? I had a look at https://docs.mongodb.com/manual/security/ However I am not sure how to implement this to my Node Js program (keeping the password a secret).
Any help would be appreciated. Thanks
A few solutions :
Restrict access to your db to only the required IP addresses. If your app and database are on the same machine, that would be 127.0.0.1 only + maybe your PC so you can run queries in a GUI.
enforce authentication as in this link, with a strong password.
To keep the password 'secret' in your Node program, which I understand as "not hardcoded", make it an env variable and give it to node at runtime, or write it in a file that doesn't live in your repo (.gitignore works too).
With a valid user/password, here's how to authenticate to mongodb using Node :
A mongodb address has 7 components :
protocol:"mongodb://",
host:"localhost",
user: "user",
password : "password",
options: "?authMechanism=MONGODB-CR",
port:"27017",
db:"db_name"
Which all together give a string like :
mongodb://user:password#localhost:27017/db_name?authMechanism=MONGODB-CR,
That should be enough for Node to connect using the native Mongo driver.
And to authenticate in the shell :
use db_name
db.auth("user", "password" )
or, directly on connection :
mongo -u "user" -p "password" --authenticationDatabase "db_name"

Resources