MongoDB Auth Fails to find username on Bitnami MEAN Stack Image - node.js

Trying to run a web app (MEAN) on Amazon EC2 Instance but am encountering the following problem. Can anyone help me with this?
node app.js The Server has started on 9091
/opt/bitnami/apps/YelpCamp/node_modules/mongodb-core/lib/auth/scram.js:128
username = username.replace('=', "=3D").replace(',', '=2C');
^
TypeError: Cannot read property 'replace' of undefined
at executeScram (/opt/bitnami/apps/SomeApp/node_modules/mongodb-core/lib/auth/scram.js:128:24)
at /opt/bitnami/apps/SomeApp/node_modules/mongodb-core/lib/auth/scram.js:277:7
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)

Mongoose can do auth in 2 ways:
1, Connection string:
mongoose.connect('mongodb://username:password#host:port(usually 27017)/db')
Where username and password are the respective username and password for that specific db, host would be the host where your db is hosted (so localhost or some domain/IP), port is the port mongo listens on, and db is the name of the db you want to connect to
2, Using options. From the docs:
var options = {
useMongoClinet: true,
auth: {authdb: 'admin'},
user: 'myUsername',
pass: 'myPassword',
}
mongoose.connect(uri, options);
I also faced the 'username undefined' error in the first approach, but I succeeded in the second approach.
[Reference] https://github.com/Automattic/mongoose/issues/4891

Related

Connection problem to mongoDB with nodeJS

I host a Mongo database on an ubuntu server. I created an admin user in order to be able to connect with Nodejs to create a database, add tables, etc. I can connect with mongoDB compass without problems but from nodeJS mongo returns an error.
connect function:
const mongoose = require("mongoose");
mongoose.set("strictQuery", true);
//connect to db
mongoose
.connect("mongodb://" + process.env.DB_USER_PASS + "#2.56.247.250:27017/?authMechanism=DEFAULT")
.then(() => console.log('Connecté a la base de donné'))
.catch((err) => console.log("Erreur de connexion :", err));
Here is the error:
Erreur de connexion : MongoServerError: Authentication failed.
at Connection.onMessage (C:\Users\arnau\Desktop\messIO\node_modules\mongodb\lib\cmap\connection.js:230:30)
at MessageStream.<anonymous> (C:\Users\arnau\Desktop\messIO\node_modules\mongodb\lib\cmap\connection.js:61:60)
at MessageStream.emit (node:events:513:28)
at processIncomingData (C:\Users\arnau\Desktop\messIO\node_modules\mongodb\lib\cmap\message_stream.js:125:16)
at MessageStream._write (C:\Users\arnau\Desktop\messIO\node_modules\mongodb\lib\cmap\message_stream.js:33:9)
at writeOrBuffer (node:internal/streams/writable:392:12)
at _write (node:internal/streams/writable:333:10)
at Writable.write (node:internal/streams/writable:337:10)
at Socket.ondata (node:internal/streams/readable:766:22)
at Socket.emit (node:events:513:28) {
ok: 0,
code: 18,
codeName: 'AuthenticationFailed',
connectionGeneration: 0,
[Symbol(errorLabels)]: Set(2) { 'HandshakeError', 'ResetPool' }
The error AuthenticationFailed means that there is a problem with your connection string and your driver cannot connect into it.
Check for all details here: https://www.mongodb.com/docs/manual/reference/connection-string/
Potential problems:
Special Chars: From the docs: If the username or password includes the following characters: / ? # [ ] # those characters must be converted using percent encoding.
username:password format check that your environmental variable is on the right format, with : between username and pass, and no spaces.
Check your auth database: When you created the user, you created on default ("admin" db is the default.) or created on a specific db, using the command use dbname. If you created on a specific db, you might need to add the auth db name on the connection string.
You can try all the above solutions, making a connection using the mongosh command, to verify that your connection string is fine.

Connection timed out while connecting to AWS DocumentDB outside the VPC

I'm trying create a very simple node app that can use DocumentDB. I'm not using Cloud9 neither Lambda, I'm coding locally. I was following this link https://docs.aws.amazon.com/documentdb/latest/developerguide/connect-from-outside-a-vpc.html and this link https://docs.aws.amazon.com/documentdb/latest/developerguide/connect-ec2.html
I created a poorly secured EC2 instance with the following inbound rules
port range
protocol
source
security group
22
TCP
0.0.0.0/0
demoEC2
This demoEC2 security group has the following inbound rules
type
protocol
port range
source
SSH
TCP
22
0.0.0.0/0
Then I created a DocumentDB cluster with 1 instance available that belongs to a security group that has the following inbound rules
type
protocol
port range
source
custom tcp
TCP
27017
demoEC2
After that, I open my terminal and created a tunnel:
ssh -i "mykeypair.pem" -L 27017:<CLUSTER ENDPOINT>:27017 ec2-user#<EC2 PUBLIC IPV4 DNS> -N
And, to test if my tunnel is working, I connect using mongoshell:
> mongo "mongodb://<MASTER USERNAME>:<MASTER PASSWORD>#localhost:27017/<DATABASE>" --tls --tlsAllowInvalidHostnames --tlsCAFile rds-combined-ca-bundle.pem
MongoDB shell version v4.2.13
connecting to: mongodb://localhost:27017/<DATABASE>?compressors=disabled&gssapiServiceName=mongodb
2021-07-29T10:10:59.309+0200 W NETWORK [js] The server certificate does not match the host name. Hostname: localhost does not match docdb-2021-07-27-10-32-49.ctuxybn342pe.eu-central-1.docdb.amazonaws.com docdb-2021-07-27-10-32-49.cluster-ctuxybn342pe.eu-central-1.docdb.amazonaws.com docdb-2021-07-27-10-32-49.cluster-ro-ctuxybn342pe.eu-central-1.docdb.amazonaws.com , Subject Name: C=US,ST=Washington,L=Seattle,O=Amazon.com,OU=RDS,CN=docdb-2021-07-27-10-32-49.ctuxybn342pe.eu-central-1.docdb.amazonaws.com
Implicit session: session { "id" : UUID("63340995-54ad-471b-aa8d-85763f3c7281") }
MongoDB server version: 4.0.0
WARNING: shell and server versions do not match
Warning: Non-Genuine MongoDB Detected
This server or service appears to be an emulation of MongoDB rather than an official MongoDB product.
Some documented MongoDB features may work differently, be entirely missing or incomplete, or have unexpected performance characteristics.
To learn more please visit: https://dochub.mongodb.org/core/non-genuine-mongodb-server-warning.
rs0:PRIMARY>
However, when I try to connect in my node app:
const mongoose = require('mongoose');
const fs = require('fs');
const path = require('path');
const username = ...
const password = ...
const database = ...
const connstring = `mongodb://${username}:${password}#localhost:27017/${database}?tls=true&replicaSet=rs0&readPreference=secondaryPreferred`;
const certFile = path.resolve(__dirname, './rds-combined-ca-bundle.pem');
const certFileBuf = fs.readFileSync(certFile); //I tried this one in tlsCAFile option as well
mongoose.connect(connstring,
{
tlsCAFile: certFile,
useNewUrlParser: true,
tlsAllowInvalidHostnames: true,
}
).then(() => console.log('Connection to DB successful'))
.catch((err) => console.error(err, 'Error'));
I get a connection timeout error after a while:
> > node .\index.js
(node:12388) [MONGODB DRIVER] Warning: Current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
MongoNetworkError: failed to connect to server [<CLUSTER ENDPOINT WITHOUT HAVING .cluster->:27017] on first connect [MongoNetworkTimeoutError: connection timed out
at connectionFailureError (D:\projects\documentdb-connect\node_modules\mongoose\node_modules\mongodb\lib\core\connection\connect.js:345:14)
at TLSSocket.<anonymous> (D:\projects\documentdb-connect\node_modules\mongoose\node_modules\mongodb\lib\core\connection\connect.js:313:16)
at Object.onceWrapper (events.js:421:28)
at TLSSocket.emit (events.js:315:20)
at TLSSocket.Socket._onTimeout (net.js:481:8)
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7)]
at Pool.<anonymous> (D:\projects\documentdb-connect\node_modules\mongoose\node_modules\mongodb\lib\core\topologies\server.js:441:11)
at Pool.emit (events.js:315:20)
at D:\projects\documentdb-connect\node_modules\mongoose\node_modules\mongodb\lib\core\connection\pool.js:564:14
at D:\projects\documentdb-connect\node_modules\mongoose\node_modules\mongodb\lib\core\connection\pool.js:1013:9
at D:\projects\documentdb-connect\node_modules\mongoose\node_modules\mongodb\lib\core\connection\connect.js:32:7
at callback (D:\projects\documentdb-connect\node_modules\mongoose\node_modules\mongodb\lib\core\connection\connect.js:283:5)
at TLSSocket.<anonymous> (D:\projects\documentdb-connect\node_modules\mongoose\node_modules\mongodb\lib\core\connection\connect.js:313:7)
at Object.onceWrapper (events.js:421:28)
at TLSSocket.emit (events.js:315:20)
at TLSSocket.Socket._onTimeout (net.js:481:8)
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7) Error
Since I could connect using mongoshell, I think the tunnel is working and I can even do some inserts on it, but why Mongoose can't connect? I tried also using the MongoClient (const MongoClient = require('mongodb').MongoClient and MongoClient.connect(same everything)) but it didn't worked, I'm still getting the same timeout error.
Turns out all I need to do is to pass the username and password through the options, not in the connection string:
const connstring = `mongodb://localhost:27017/${database}`;
const certFile = path.resolve(__dirname, './rds-combined-ca-bundle.pem');
const certFileBuf = fs.readFileSync(certFile);
mongoose.connect(connstring,
{
tls: true,
tlsCAFile: certFile,
useNewUrlParser: true,
tlsAllowInvalidHostnames: true,
auth: {
username,
password
}
}
)

Include Amazon RDS endpoint in Node JS error: An identifier or keyword cannot immediately follow a numeric literal

I was trying to connect my Node JS application with Amazon RDS following this tutorial Adding Node JS to RDS application, in my case I have the following:
const pool = mysql.createPool({
connectionLimit: 10,
host: process.env.factsDB.abcdefg.eu-west-2.rds.amazonaws.com,
user: process.env.johnDoe,
password: process.env.password123,
port: process.env.3306,
database: 'factsDB',
debug: false
});
However it gave me the following error:
An identifier or keyword cannot immediately follow a numeric literal
at rds at the host, and another error
',' expected
at env.3306 at port, any idea how to fix these?
The process.env in the link provided is used to read environmental variables. However, from what I understand, you provide your db details directly into createPool.
Thus you can try the following:
const pool = mysql.createPool({
connectionLimit: 10,
host: "factsDB.abcdefg.eu-west-2.rds.amazonaws.com",
user: "johnDoe",
password: "password123",
port: 3306,
database: 'factsDB',
debug: false
});

Managed DigitalOcean Redis instance giving Redis AbortError

I setup managed redis and managed postgres on digital ocean. Digital ocean gave me a .crt file, I don't know what to do with this, so didn't do anything with it. Can this be the root of the problem below:
Or do I have to allow docker container to reach outside of the container on the rediss protocol?
I dockerized a node app and then put this container onto my droplet. I have my droplet and managed redis and postgres in same region (SFO2). It connects to redis using this url:
url: 'rediss://default:REMOVED_THIS_PASSWORD#my-new-app-sfo2-do-user-5053627-0.db.ondigitalocean.com:25061/0',
I then did ran my docker container with docker run.
It then gives me error:
node_redis: WARNING: You passed "rediss" as protocol instead of the "redis" protocol!
events.js:186
throw er; // Unhandled 'error' event
^
AbortError: Connection forcefully ended and command aborted. It might have been processed.
at RedisClient.flush_and_error (/opt/apps/mynewapp/node_modules/redis/index.js:362:23)
at RedisClient.end (/opt/apps/mynewapp/node_modules/redis/lib/extendedApi.js:52:14)
at RedisClient.onPreConnectionEnd (/opt/apps/mynewapp/node_modules/machinepack-redis/machines/get-connection.js:157:14)
at RedisClient.emit (events.js:209:13)
at RedisClient.connection_gone (/opt/apps/mynewapp/node_modules/redis/index.js:590:14)
at Socket.<anonymous> (/opt/apps/mynewapp/node_modules/redis/index.js:293:14)
at Object.onceWrapper (events.js:298:28)
at Socket.emit (events.js:214:15)
at endReadableNT (_stream_readable.js:1178:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
Emitted 'error' event on RedisClient instance at:
at /opt/apps/mynewapp/node_modules/redis/index.js:310:22
at Object.callbackOrEmit [as callback_or_emit] (/opt/apps/mynewapp/node_modules/redis/lib/utils.js:89:9)
at Command.callback (/opt/apps/mynewapp/node_modules/redis/lib/individualCommands.js:199:15)
at RedisClient.flush_and_error (/opt/apps/mynewapp/node_modules/redis/index.js:374:29)
at RedisClient.end (/opt/apps/mynewapp/node_modules/redis/lib/extendedApi.js:52:14)
[... lines matching original stack trace ...]
at processTicksAndRejections (internal/process/task_queues.js:80:21) {
code: 'NR_CLOSED',
command: 'AUTH',
args: [ 'REMOVED_I_DONT_KNOW_IF_THIS_IS_SENSITIVE' ]
The redis protocol is different from rediss because the latter uses TLS connection. DigitalOcean Managed Redis requires the connections to be made over TLS, so you have to use rediss. However, I couldn't find any info about the TLS certificate provided by DigitalOcean to connect to the Managed Redis service.
Based on your error message, I presumed you're using this redis package. If that's the case, you can pass empty TLS object option in the connection string like so:
const Redis = require('redis')
const host = 'db-redis.db.ondigitalocean.com'
const port = '25061'
const username = 'user'
const password = 'secret'
const url = `${username}:${password}#${host}:${port}`
const client = Redis.createClient(url, {tls: {}})
Further reading/source:
SSL connections arrive for Redis on Compose
Connecting to IBM Cloud Databases for Redis from Node.js
I solved this. Below are snippets from config/env/production.js
Sockets
For sockets, to enable rediss you have to pass in all options through adapterOptions like this:
sockets: {
onlyAllowOrigins: ['https://my-website.com'],
// pass in as adapterOptions so it gets through to redis-adapter
// as i need it "rediss" but this url is not supported i get an error.
// so i need to pass in `tls` empty object. and i see he moves things into
// `adapterOptions` here here - https://github.com/balderdashy/sails-hook-sockets/blob/master/lib/configure.js#L128
adapterOptions: {
user: 'username',
pass: 'password',
host: 'host',
port: 9999,
db: 2, // pick a number
tls: {},
},
adapter: '#sailshq/socket.io-redis',
},
Session
For session, pass tls: {} empty object to config:
session: {
pass: 'password',
host: 'host',
port: 9999,
db: 1, // pick a number not used by sockets
tls: {},
cookie: {
secure: true,
maxAge: 24 * 60 * 60 * 1000, // 24 hours
},
},

Mongoose can't connect: Error: querySrv ENOTIMP mongodb.tcp.cluster1-owfxv.mongodb.net

Mongoose can't connect to mogodb Atlas. It every times give me this error:
Error: querySrv ENOTIMP _mongodb._tcp.cluster1-owfxv.mongodb.net
I am running inside kubernetes cluster inside minikube locally.
If I run project directly then it works perfectly but with minikube it alwasy give me error.
Following is my code:
const url = "mongodb+srv://name:password#cluster1-owfxv.mongodb.net/test?retryWrites=true";
const mongoDbOptions = {
useNewUrlParser: true,
reconnectTries: 10,
autoReconnect: true
};
mongoose.connect(url, mongoDbOptions).then((r) => { }).catch((e) => {
console.log(e);
});
Error message is not so clear to me. Its strange that it works directly but with kubernetes cluster it does not work.
I will really appreciate for any contribution.
Try using connection string compatible with mongo driver 2.2.12 or later i.e. one with mongodb://username:password#host1:port,host2:port,host3:port/databaseName
It's not clear why connection to mongodb is not working with new url.
Using older url, as stated by #cEeNikC, even works when mongoose is giving the following error-
Error: querySrv ETIMEOUT _mongodb._tcp.cluster0.aq9un.mongodb.net
at QueryReqWrap.onresolve [as oncomplete] (dns.js:203:19) {
errno: 'ETIMEOUT',
code: 'ETIMEOUT',
syscall: 'querySrv',
hostname: '_mongodb._tcp.cluster0.aq9un.mongodb.net'
}
go to your cluster setting and enable access from all IP addresses (if you doing this for a learning purpose because it's not safe) .
I add this "&w=majority" and worked:
Before: mongodb+srv://:#sdq25.lepde.mongodb.net/myFirstDatabase?retryWrites=true
After: mongodb+srv://:#sdq25.lepde.mongodb.net/myFirstDatabase?retryWrites=true&w=majority

Resources