Mongoose.connect() fails when database is specified in connection string - javascript

I'm running a local MongoDB server and am trying to connect to it from a node.js server using the Mongoose library.
I'm using SCRAM-SHA-1 as the authentication mechanism
I'm able to connect to it with the admin account when I don't specify a database to connect to, using a connection string such as:
mongodb://{username}:{password}#{address}:{port}?authMechanism=SCRAM-SHA-256
But when I try to specify which database to connect to, using a connection string such as:
mongodb://{username}:{password}#{address}:{port}/database123?authMechanism=SCRAM-SHA-256
the authentication fails.
For reference, my code looks like:
const mongoose = require('mongoose');
let conn_string = `mongodb://mongo_uname:mongo_pass#192.168.1.1:3000/database123?authMechanism=SCRAM-SHA-256`
mongoose
.connect(database_uri, {
useUnifiedTopology: true
})
.then(() => console.log('MongoDB database Connected...'))
.catch((err) => console.log(err))
Is there a different way to specify which database to connect to with mongoose, or is there something I can do differently when constructing the connection string to make it work?
Cheers.

Make sure that the database user you are using is configured to read and write to the database uou are trying to connect to.

import mongoose from "mongoose";
const mongoDB = "mongodb://localhost:27017/twlight";
mongoose.Promise = global.Promise;
mongoose.connect(mongoDB, { useNewUrlParser: true })
.then(() => {
console.log("Database is connected");
},
(err) => {
console.log("There is problem while connecting database " + err);
});
Please try
Note: twilight is database name

If you are using Mongoose v6+, you should NOT specify useUnifiedTopology.
That is deprecated and if you include it, Mongoose will throw the error. Try to include the connection string only:
mongoose.connect(database_uri)

My error ended up being in the configuration of the database user I was trying to connect with, they weren't even set up to read or write to the database I was attempting to connect to.

Related

mongodb connections and sessions not working as intended

for context I am fairly new to mongodb transactions, i was initially working with a standalone database but am using atlas now so that i can test my transactions without affecting my main database.
here is how i used to connect to the atlas database :
export var client = mongoose
.connect(CONNECTION_URL, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() =>
app.listen(PORT, () => console.log(`SERVER RUNNING ON PORT: ${PORT}`))
)
.catch(() => console.log("launch error, probably ip address on mongo db"));
however i keep getting a
TypeError: client.startSession is not a function
error so i changed my client to be like this :
export var client = await MongoClient.connect(CONNECTION_URL, { useNewUrlParser: true, useUnifiedTopology: true })
app.listen(PORT, () => console.log(`SERVER RUNNING ON PORT: ${PORT}`));
which is incorrect in a sense but it seems to get my session to start, however it fails all my model queries (the error is : usermodels.findOne() buffering timed out after 10000ms) and it only works as intended when i use my client to get a collection instead of using the model directly
const Collection = client.db("myFirstDatabase").collection("usermodels");
and then running
const user = await Collection.find({});
instead of
const user = await User.find({}); (where User is just the model i import)
I cant seem to understand why I am unable to use my models as i used to and have to call the collections each time I attempt to run a query on my DB, why isn't possible to run queries with models and collections at the same time ?
I tried going through the official and unofficial documentation about connections/sessions/transactions/queries and its been days since I've been reading but I feel like am on the wrong track or that I am missing something obvious, any help or pointers would be appreciated, I tried looking into previous SO questions but most of them are either unanswered or missing crucial context !

How to authentic connection using Mongoose to MongoDB [duplicate]

I can connect to the DB through terminal, but getting this error using mongoose and gulp.
mongoose/node_modules/mongodb/lib/mongodb/connection/base.js:246
MongoError: auth failed
My connection string is:
mongodb://usr:psw#localhost:27017/dbname
Any idea what it can be?
I installed MEAN from MEAN packaged by Bitnami for windows 7 using the following password: 123456
Syntax for connection string to connect to mongodb with mongoose module
mongoose.connect("mongodb://[usr]:[pwd]#localhost:[port]/[db]",{auth:{authdb:"admin"}});
If you don't have {auth:{authdb:"admin"}} in the connection string, you will get the following error: MongoError: Authentication failed.
JS Example: mongo-test/app.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://root:123456#localhost/test',{auth:{authdb:"admin"}});
mongoose.set('debug', true); // turn on debug
just add ?authSource=yourDB&w=1 to end of db url
mongoose.connect('mongodb://user:password#host/yourDB?authSource=yourDB&w=1')
this work for me . &w=1 is important
There is many ways to make it work. This is what worked for me [mongoose v5.9.15] :
mongoose.connect('mongodb://localhost:27017/', {
auth: {
user:'root',
password:'example'
},
authSource:"admin",
useUnifiedTopology: true,
useNewUrlParser: true
})
You might want to do something like this...
var opt = {
user: config.username,
pass: config.password,
auth: {
authdb: 'admin'
}
};
var connection = mongoose.createConnection(config.database.host, 'mydatabase', config.database.port, opt);
'authdb' option is the database you created the user under.
mongoose.connect("mongodb://[host]/[db]", { auth:{
authdb: "admin",
user: [username],
password: [pw]
}}).then(function(db){
// do whatever you want
mongoose.connection.close() // close db
})
Do you have a user set up for dbname? By default, no user is required to connect to the database unless you explicitly set one. If you haven't, you should just try to connect to mongodb://localhost:27017/dbname and see if you still get an error.
I have found the solution hier, looks like when you create an user from the mongo shell, it makes SCRAM-SHA-1 instead of MongoDB-CR. So the solution to create a new user with MongoDB-CR authentication.
MongoDB-CR Authentication failed
just make sure that your database is created.
and also if your user is not added in the admin database, then make sure to add it by putting
db.createUser(
... {user:'admin',pwd:'admin',roles:['root']}
... )
This worked for me for mongod --version = db version v3.6.13
mongoose.connect('mongodb://localhost/expressapi', {
auth: {
authdb: "admin",
user: "root",
password: "root",
}
});
mongo mongodb://usr:psw#localhost:27017/dbname
Password should be alphanumeric only
User should be also available in db 'dbname' (Note : Even if user is super admin)
With above changes it connected successfully.
mongoose.connect("mongodb://[usr]:[pwd]#localhost:[port]/[db]",{ authSource: 'admin', useNewUrlParser: true, useUnifiedTopology: true });
I was getting same error. Resolved by adding authSource option to connect function solved the issue. see above code.
The connection string will be like
mongodb://username:password#localhost:27017/yourdbname?authSource=admin

I am unable to save data to my mongodb Atlas database

Github repo. I am trying to use MongoDB Atlas database with my node JS Login & Signup app for storing data. The problem is that the data is not saving to the database or in other words the request isn't going through even if my app is connected to Atlas. Full code available on www.github.com/tahseen09/login
// Connection to mongodb atlas
const uri = "mongodb+srv://tahseen09:<PASSWORD>#cluster0-pirty.mongodb.net/userdb"
MongoClient.connect(uri, function(err, client) {
if(err) {
console.log('Error occurred while connecting to MongoDB Atlas...\n',err);
}
console.log('Connected to Atlas');
const collection = client.db("userdb").collection("credentials");
client.close();
});
//New User Registration
app.post('/register', function(req,res){
var cred= new credential();
cred.uname=req.body.uname;
const hash = bcrypt.hashSync(req.body.password, 10);
cred.password=hash;
collection.save(function(err,newuser){
if(err){
res.status(500).send("Username exists");
}
else{
res.status(200).send("New User Created");
}
})
})
The code that is important is attached as a snippet and the rest of the code is available on www.github.com/tahseen09/login
Note: I am running this app on localhost.
Let me describe your flow so you can understand wrong point there :)
Connect to MongoDB
Create reference to the collection
Close connection
When someone tries to access /register route, you already have closed connection by that time. Thus, any operation attempt to the database will end up with connection error.
From the documentation it's recommended calling MongoClient.connect once and reusing the database variable returned by the callback, i.e. do not close connection manually, driver will just create and use pool of connections, so don't worry about closing connection. Check out example code in the documentation.
Lets step through the code to see what happens:
MongoClient.connect(uri, function(err, client) {
A connection to mongodb is created, then somewhen the connection is established or it fails, then the callback gets called back. Now you create a local variable holding the database reference:
const collection = client.db("userdb").collection("credentials");
And then you close the connection:
client.close();
Then the callback ends:
});
which means that a variables inside (connection) can't be accessed anymore and get therefore recycled.
Now somewhen (that might even happen before the db connection gets established), someone requests the webpage and you try to do:
collection.save(/*...*/);
That won't work for various reasons:
1) The db might not even be opened
2) If it was opened already, it was also closed already.
3) Even if it is open at the moment, you still cannot access connection as it is not in scope.
Now to resolve that we have to:
1) only start the webserver when the db connection is establishee
2) don't close the connection
3) expose the connection so that it can be used elsewhere
For that it makes sense to create a function that establishes the connection and calls back with the db:
function withCredentials(callback) {
const uri = "mongodb+srv://tahseen09:<PASSWORD>#cluster0-pirty.mongodb.net/userdb"
MongoClient.connect(uri, function(err, client) {
if(err) {
console.log('Error occurred while connecting to MongoDB Atlas...\n',err);
} else {
console.log('Connected to Atlas');
const collection = client.db("userdb").collection("credentials");
callback(collection);
}
});
}
So now you can use that:
withCredentials(function(credentials) {
app.post('/register', function(req,res){
const cred = { };
cred.uname = req.body.uname;
cred.password = bcrypt.hashSync(req.body.password, 10);
credentials.insertOne(cred, function(err,newuser){
if(err){
res.status(500).send("Username exists");
} else {
res.status(200).send("New User Created");
}
})
});
});

Cannot Connect to SQL Server after hosting the app on heroku

I'm using mssql along with node.
I call a function to connect to the database:
const sql = require('mssql')
async () => {
try {
const pool = await sql.connect(`mssql://${process.env.DATAUSER}:${process.env.DATAPASS}#${process.env.SERVER}`)
} catch(err) {
console.log(err)
}
}
This works perfectly fine when i'm on a localhost but after i've hosted it to heroku and add the env variables. The error I get is (I changed the ip address to 5's):
ConnectionError: Failed to connect to 55.5.5.555:1433 in 15000ms
My process.env.SERVER = 55.5.5.555/SpecificDatabase and If that means anything
I don't see any reference to your specific database or schema in this code. It may be possible that your local implementation of the data server differs from the heroku implementation in respect to the default schema or database to which a user is directed. Therefore, you may need to add a database or schema field to your connection call.
For example, my pool code to connect to the OSU server is:
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 10,
host : 'classmysql.engr.oregonstate.edu',
user : 'username',
password : 'password',
database : 'database_name',
multipleStatements: true
});
module.exports.pool = pool;
Though my implementation here was with mysql and not mssql, it may hold true that you need to explicitly name a specific database or schema.

mongoose connection can´t handle errors

I am building my first test API rest with Mongo and Node
I am opening a connection to the database, and it works right... but I can´t handle the error case. Despite i write a wrong URI, it makes a successful connection. Tried with promises, callbacks, and events, but nothing works:
For example:
const mongoose=require('mongoose');
mongoose.Promise = global.Promise;
const express=require('express');
const bodyParser=require('body-parser');
const portApp=1300;
const app=express();
app.listen(portApp,'localhost',()=>{
console.log(`server works fine at ${portApp}`);
mongoose.connect('mongodb://localhost:27017/RIGHTdbname')
.then((res)=>
{
console.log(`successful connection to BBDD`);
//console.log(res);
})
.catch((error)=>{
console.log("error"+error.message);
});
});
That´s ok, it throws "successful connection to BBDD"... the problem is, when I write a wrong database name, it throws the same!
I tried to with callback too. like suggested here:
mongoose.connect('mongodb://localhost:27017/WRONGdbname',function(err){
if(err)
{
throw err;
}
});
And tried to use these events (taken from here, and which I actually don´t understand, only used the .on() jquery method in the past, for event delegation tasks), but it does´t work either, because always the "connected" event fires, even if database name is wrong, again.
// When successfully connected
mongoose.connection.on('connected', function () {
console.log('Mongoose default connection opened);
});
// If the connection throws an error
mongoose.connection.on('error',function (err) {
console.log('Mongoose default connection error: ' + err);
});
Can someone explain me what I´´m doing wrong? Thanks
The "database" in the Mongo connection string is used for authentication, and is only relevant if you pass the username and password in the URL using the mongodb://user:pass#host:port/database syntax.
From the reference
/database Optional. The name of the database to authenticate if the connection string includes authentication credentials in the form of username:password#. If /database is not specified and the connection string includes credentials, the driver will authenticate to the admin database.

Categories