MongoError: Authentication Failed

What’s happening:
I have this error:

MongoError: Authentication failed.
    at MessageStream.messageHandler (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/cmap/connection.js:268:20)
    at MessageStream.emit (events.js:315:20)
    at processIncomingData (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/cmap/message_stream.js:144:12)
    at MessageStream._write (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/cmap/message_stream.js:42:5)
    at doWrite (_stream_writable.js:403:12)
    at writeOrBuffer (_stream_writable.js:387:5)
    at MessageStream.Writable.write (_stream_writable.js:318:11)
    at TLSSocket.ondata (_stream_readable.js:717:22)
    at TLSSocket.emit (events.js:315:20)
    at addChunk (_stream_readable.js:295:12) {
  ok: 0,
  code: 8000,
  codeName: 'AtlasError'
}
(node:129) UnhandledPromiseRejectionWarning: Error: Unable to Connect to Database

My code so far

"use strict";
require("dotenv").config();
const express = require("express");
const myDB = require("./connection");
const fccTesting = require("./freeCodeCamp/fcctesting.js");
const session = require("express-session");
const passport = require("passport");
const ObjectID = require("mongodb").ObjectID;

const app = express();

fccTesting(app); //For FCC testing purposes
app.use("/public", express.static(`${process.cwd()}/public`));

app.set("view engine", "pug");

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: true,
  saveUninitialized: true,
  cookie: { secure: false }
}));

app.use(passport.initialize());
app.use(passport.session());

app.route("/").get((req, res) => {
  res.render(`${process.cwd()}/views/pug/index`, {
    title: "Hello", message: "Please login"
  });
});

myDB(async client => {
  const usersDB = await client.db("usersDB").collection("users");

  app.route("/").get((req, res) => {
    res.render("pug", {
      title: "Connected to Database",
      message: "Please login"
    });
  });

  passport.serializeUser((user, done) => {
    done(null, user._id);
  });

  passport.deserializeUser((id, done) => {
    myDatabase.findOne({ _id: new ObjectID(id) }, (err, doc) => {
      done(null, doc);
    });
  }).catch(e => {
    app.route("/").get((req, res) => {
      res.render("pug", {
        title: e,
        message: "Unable to login"
      });
    });
  });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Listening on port ${PORT}`);
});

My browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36 Edg/90.0.818.42.

Challenge: Implement the Serialization of a Passport User

Link to the challenge:

Any help would be appreciated. Thanks in advance.

I surrounded the value for MONGO_URI in double quotes in the Secrets file on Repl and it made the “Authentication failed” error go away.

But I still have two other problems:

TypeError: Cannot read property 'split' of null
    at parseSrvConnectionString (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/core/uri_parser.js:44:23)
    at parseConnectionString (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/core/uri_parser.js:587:12)
    at connect (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/operations/connect.js:282:3)
    at /home/runner/boilerplate-advancednode/node_modules/mongodb/lib/mongo_client.js:223:5
    at maybePromise (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/utils.js:662:3)
    at MongoClient.connect (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/mongo_client.js:219:10)
    at main (/home/runner/boilerplate-advancednode/connection.js:11:22)
    at Object.<anonymous> (/home/runner/boilerplate-advancednode/server.js:36:1)
    at Module._compile (internal/modules/cjs/loader.js:1138:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
Listening on port 8080
(node:290) UnhandledPromiseRejectionWarning: Error: Unable to Connect to Database

I noticed that the “Unable to Connect to Database” error message is from here:

require("dotenv").config();
const { MongoClient } = require("mongodb");

async function main(callback) {
    const URI = process.env.MONGO_URI; // Declare MONGO_URI in your .env file
    const client = new MongoClient(URI, { useNewUrlParser: true, useUnifiedTopology: true });

    try {
        // Connect to the MongoDB cluster
        await client.connect();

        // Make the appropriate DB calls
        await callback(client);

    } catch (e) {
        // Catch any errors
        console.error(e);
        throw new Error("Unable to Connect to Database")
    }
}

module.exports = main;

in connection.js. I need help in figuring where the other error is coming from. It seems to be from the uri_parser library, but I don’t see that library being required in server.js. Maybe it’s being required through one of the libraries there as a dependency.

Could someone help me out?

Also, which of the libraries being required in server.js are the likeliest to be using uri_parser as a dependency (asking so I can narrow it down)?

Okay, with my current code (showed in previous comment), I actually have one of the tests passing on FCC.

This is the test that doesn’t pass:

Database connection should be present.

This one passes:

Deserialization should now be correctly using the DB and done(null, null) should be called with the doc.

Code again:

"use strict";
require("dotenv").config();
const express = require("express");
const myDB = require("./connection");
const fccTesting = require("./freeCodeCamp/fcctesting.js");
const session = require("express-session");
const passport = require("passport");
const ObjectID = require("mongodb").ObjectID;

const app = express();

fccTesting(app); //For FCC testing purposes
app.use("/public", express.static(`${process.cwd()}/public`));

app.set("view engine", "pug");

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: true,
  saveUninitialized: true,
  cookie: { secure: false }
}));

app.use(passport.initialize());
app.use(passport.session());

app.route("/").get((req, res) => {
  res.render(`${process.cwd()}/views/pug/index`, {
    title: "Hello", message: "Please login"
  });
});

myDB(async client => {
  const usersDB = await client.db("usersDB").collection("users");

  app.route("/").get((req, res) => {
    res.render("pug", {
      title: "Connected to Database",
      message: "Please login"
    });
  });

  passport.serializeUser((user, done) => {
    done(null, user._id);
  });

  passport.deserializeUser((id, done) => {
    myDatabase.findOne({ _id: new ObjectID(id) }, (err, doc) => {
      done(null, doc);
    });
  }).catch(e => {
    app.route("/").get((req, res) => {
      res.render("pug", {
        title: e,
        message: "Unable to login"
      });
    });
  });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Listening on port ${PORT}`);
});

Here’s the Repl link. So what could be the reason I can’t connect to the database? Would someone please help? Thanks.

Hello there,

Just getting here now.

The instructions expect:

myDB(async client => {
  const myDataBase = await client.db('database').collection('users');

Hope this helps

Thanks for the reply.

So now I have two questions:

  1. Does the name of the Cluster matter?
  2. Do I have to have a schema defined in the code already (I currently don’t)?

Please answer. Thanks.

No, it does not. There are restrictions on the cluster name, but this is handled by Mongodb, and unrelated to these challenges.

As you are working with Mongodb (a no-sql database), and these lessons do not use Mongoose, there is no need for a schema.

Hope this clarifies

I still can’t connect to the database, though.

Here’s my current code:

"use strict";
require("dotenv").config();
const express = require("express");
const myDB = require("./connection");
const fccTesting = require("./freeCodeCamp/fcctesting.js");
const session = require("express-session");
const passport = require("passport");
const ObjectID = require("mongodb").ObjectID;

const app = express();

fccTesting(app); //For FCC testing purposes
app.use("/public", express.static(`${process.cwd()}/public`));

app.set("view engine", "pug");

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: true,
  saveUninitialized: true,
  cookie: { secure: false }
}));

app.use(passport.initialize());
app.use(passport.session());

app.route("/").get((req, res) => {
  res.render(`${process.cwd()}/views/pug/index`, {
    title: "Hello", message: "Please login"
  });
});

myDB(async client => {
  const myDataBase = await client.db("database").collection("users");

  app.route("/").get((req, res) => {
    res.render("pug", {
      title: "Connected to Database",
      message: "Please login"
    });
  });

  passport.serializeUser((user, done) => {
    done(null, user._id);
  });

  passport.deserializeUser((id, done) => {
    myDatabase.findOne({ _id: new ObjectID(id) }, (err, doc) => {
      done(null, doc);
    });
  }).catch(e => {
    app.route("/").get((req, res) => {
      res.render("pug", {
        title: e,
        message: "Unable to login"
      });
    });
  });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Listening on port ${PORT}`);
});

The password that has to be put in the DB URI only has to be put in there, right? Not on the MongoDB site anywhere (if using Atlas)?

This is all you need to do (other than the code):

add your database’s connection string (for example: mongodb+srv://:@cluster0-jvwxi.mongodb.net/?retryWrites=true&w=majority ) to the environment variable MONGO_URI .

If you have done that, then it might be worth a try commenting out the require("dotenv").config() code.

It is difficult to help with the environment variable stuff, because we cannot see your secrets on Replit, unless you specifically invite us to, which you probably should not.

Hope this helps

I could show the MONGO_URI value here while hiding the password.

MONGO_URI:

"mongodb+srv://DragonOsman:***************@users.fdirm.mongodb.net/myDataBase?retryWrites=true&w=majority"

(I put quotes around it in the Secrets file because it gives me an “Authentication failed” error otherwise.)

Anyway, any help is appreciated. Thanks.

Probably not related as you have already worked with mongodb before this, but just in case, did you whitelist the IPs? Adding 0.0.0.0/0 allows access from anywhere.

I just took a closer look at your code:

  • The catch block is connected to the wrong function.

Pay attention to the placement of your {} and ().

Hope this helps

I have 0.0.0.0/0 as my IP address.

This is my code now after moving the catch code:

"use strict";
require("dotenv").config();
const express = require("express");
const myDB = require("./connection");
const fccTesting = require("./freeCodeCamp/fcctesting.js");
const session = require("express-session");
const passport = require("passport");
const ObjectID = require("mongodb").ObjectID;

const app = express();

fccTesting(app); //For FCC testing purposes
app.use("/public", express.static(`${process.cwd()}/public`));

app.set("view engine", "pug");

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: true,
  saveUninitialized: true,
  cookie: { secure: false }
}));

app.use(passport.initialize());
app.use(passport.session());

app.route("/").get((req, res) => {
  res.render(`${process.cwd()}/views/pug/index`, {
    title: "Hello", message: "Please login"
  });
});

myDB(async client => {
  const myDataBase = await client.db("database").collection("users");

  app.route("/").get((req, res) => {
    res.render("pug", {
      title: "Connected to Database",
      message: "Please login"
    });
  });

  passport.serializeUser((user, done) => {
    done(null, user._id);
  });

  passport.deserializeUser((id, done) => {
    myDatabase.findOne({ _id: new ObjectID(id) }, (err, doc) => {
      done(null, doc);
    });
  });
}).catch(e => {
  app.route("/").get((req, res) => {
    res.render("pug", {
      title: e,
      message: "Unable to login"
    });
  });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Listening on port ${PORT}`);
});

The test for a database connection still fails. I don’t have the “Can’t Connect to Database” error anymore, though.

Something else: Move app.set("view engine", "pug") to above the fccTesting(app) line.

There is a typo here.


A few of these mistakes would be caught by a modern text editor. I suggest you switch to using either a local editor, or something more feature rich like CodeSandbox.

Still the same result; the database connection fails.

Current code:

"use strict";
require("dotenv").config();
const express = require("express");
const myDB = require("./connection");
const fccTesting = require("./freeCodeCamp/fcctesting.js");
const session = require("express-session");
const passport = require("passport");
const ObjectID = require("mongodb").ObjectID;

const app = express();

app.set("view engine", "pug");

fccTesting(app); //For FCC testing purposes
app.use("/public", express.static(`${process.cwd()}/public`));

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: true,
  saveUninitialized: true,
  cookie: { secure: false }
}));

app.use(passport.initialize());
app.use(passport.session());

app.route("/").get((req, res) => {
  res.render(`${process.cwd()}/views/pug/index`, {
    title: "Hello", message: "Please login"
  });
});

myDB(async client => {
  const myDataBase = await client.db("database").collection("users");

  app.route("/").get((req, res) => {
    res.render("pug", {
      title: "Connected to Database",
      message: "Please login"
    });
  });

  passport.serializeUser((user, done) => {
    done(null, user._id);
  });

  passport.deserializeUser((id, done) => {
    myDataBase.findOne({ _id: new ObjectID(id) }, (err, doc) => {
      done(null, doc);
    });
  });
}).catch(e => {
  app.route("/").get((req, res) => {
    res.render("pug", {
      title: e,
      message: "Unable to login"
    });
  });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Listening on port ${PORT}`);
});

I have VS Code to use as a local editor, but I wanted to try this online so I have to have any files locally. I’ll try to look at CodeSandBox. Thanks.

But for now I’ll keep trying with the current setup.

I wonder if this error is the reason it keeps failing that database connection test:

TypeError: Cannot read property 'split' of null
    at parseSrvConnectionString (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/core/uri_parser.js:44:23)
    at parseConnectionString (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/core/uri_parser.js:587:12)
    at connect (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/operations/connect.js:282:3)
    at /home/runner/boilerplate-advancednode/node_modules/mongodb/lib/mongo_client.js:223:5
    at maybePromise (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/utils.js:662:3)
    at MongoClient.connect (/home/runner/boilerplate-advancednode/node_modules/mongodb/lib/mongo_client.js:219:10)
    at main (/home/runner/boilerplate-advancednode/connection.js:11:22)
    at Object.<anonymous> (/home/runner/boilerplate-advancednode/server.js:36:1)
    at Module._compile (internal/modules/cjs/loader.js:1138:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)

Here’s my code again:

"use strict";
require("dotenv").config();
const express = require("express");
const myDB = require("./connection");
const fccTesting = require("./freeCodeCamp/fcctesting.js");
const session = require("express-session");
const passport = require("passport");
const ObjectID = require("mongodb").ObjectID;

const app = express();

app.set("view engine", "pug");

fccTesting(app); //For FCC testing purposes
app.use("/public", express.static(`${process.cwd()}/public`));

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: true,
  saveUninitialized: true,
  cookie: { secure: false }
}));

app.use(passport.initialize());
app.use(passport.session());

app.route("/").get((req, res) => {
  res.render(`${process.cwd()}/views/pug/index`, {
    title: "Hello", message: "Please login"
  });
});

myDB(async client => {
  const myDataBase = await client.db("database").collection("users");

  app.route("/").get((req, res) => {
    res.render("pug", {
      title: "Connected to Database",
      message: "Please login"
    });
  });

  passport.serializeUser((user, done) => {
    done(null, user._id);
  });

  passport.deserializeUser((id, done) => {
    myDataBase.findOne({ _id: new ObjectID(id) }, (err, doc) => {
      done(null, doc);
    });
  });
}).catch(e => {
  app.route("/").get((req, res) => {
    res.render("pug", {
      title: e,
      message: "Unable to login"
    });
  });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Listening on port ${PORT}`);
});

Any help is appreciated. Thanks.

Yes. that means that you haven’t set the connection string in the .env file correctly (if you hadn’t set it at all, I think it would be undefined instead of null).

Try without the quotes again for the connection string in the .env file.

There are also some rules for using percent-encoding characters if in the username or password (: / ? # [ ] @).

I tried that, but the test still fails now even though that error is gone.

Any other ideas?

But are you now connecting to the DB at least?

Edit: is it still the “Database connection should be present.” test that is failing?

Does removing the / route code before the myDB connection change anything?