0

I am using Google OAuth to authenticate users via a node.js script called user.js which is run on my AWS Instance (a VM) which calls a Amazon DocumentDB Mongo Database. The database is still fresh, I have not created any databases or users within it. What is happening is whenever I browse to the Google URL to authenticate, script times out in connecting to the Amazon DocumentDB. However if I try to connect manually to the DB from the AWS Instance, it connects just fine.

I have allowed port 27017 into the database:

This is the error I receive when I try to browse to my Google OAuth:

MongooseError: Operation `users.findOne()` buffering timed out after 10000ms
    at Timeout.<anonymous> (/home/ubuntu/JobApply-Pro/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js:185:23)
    at listOnTimeout (node:internal/timers:573:17)
    at process.processTimers (node:internal/timers:514:7)

This is my user.js file:

const express = require('express');
const bcrypt = require('bcryptjs');
const rateLimit = require('express-rate-limit');
const session = require('express-session');
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const { body, validationResult } = require('express-validator');
const fs = require('fs');
const path = require('path');

const router = express.Router();

const User = require('../models/user');

const mongoose = require('mongoose');
const MONGO_URI = 'mongodb://username:password@aws-documentdb-cluster-url:27017/jobapplypro';

// SSL options for mongoose connection
const sslOptions = {
    ssl: true,
    sslValidate: true,
    sslCA: [fs.readFileSync(path.resolve(__dirname, '../certs/global-bundle.pem'))],
    useNewUrlParser: true,
    useUnifiedTopology: true
};

mongoose.connect(MONGO_URI, sslOptions)
    .then(() => {
        console.log('Connected to the Database.');
    })
    .catch((error) => {
        console.error(`Error on connecting to the database: ${error}`);
    });

// Additional logging
mongoose.connection.on('connected', function() {
  console.log('Mongoose connection is open');
});

mongoose.connection.on('error', function(err) {
  console.log('Mongoose connection has occured ' + err + ' error');
});

mongoose.connection.on('disconnected', function() {
  console.log('Mongoose connection is disconnected');
});

process.on('SIGINT', function() {
  mongoose.connection.close(function() {
    console.log('Mongoose connection is disconnected due to application termination');
    process.exit(0)
  });
});

// Session management
router.use(session({
    secret: '[hidden]',
    resave: false,
    saveUninitialized: true
}));

// Passport setup
router.use(passport.initialize());
router.use(passport.session());

passport.use(new GoogleStrategy({
    clientID: '816672868893-0atl08ucn7m2hh3gftdsem0i3belv86q.apps.googleusercontent.com',
    clientSecret: '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',
    callbackURL: 'http://app.jobapplypro.infinitisoftwaresolutions.com:5000/user/google/callback'
    },
    async function(accessToken, refreshToken, profile, done) {
        try {
            let user = await User.findOne({ googleId: profile.id });

            if (!user) {
                user = new User({
                    googleId: profile.id,
                    // add other properties if needed
                });
                await user.save();
            }

            done(null, user);
        } catch (err) {
            done(err, null);
        }
    }
));

// Route for initiating Google OAuth
router.get('/google',
  passport.authenticate('google', { scope: ['profile', 'email'] }));

// Google OAuth callback route
router.get('/google/callback', 
  passport.authenticate('google', { failureRedirect: '/login' }),
  function(req, res) {
    // Successful authentication, redirect home.
    res.redirect('/');
  });

// Similarly, setup strategies and routes for Apple and Outlook OAuth

// Rate limiting
const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 100 // limit each IP to 100 requests per windowMs
});

// Apply the rate limit to all requests
router.use(limiter);

// Get all users
router.get('/', async (req, res) => {
    // Add your own error handling here
});

// Get one user
router.get('/:id', getUser, (req, res) => {
    // Add your own error handling here
});

// Create one user
router.post('/',
    // Add input validation
    body('password').isLength({ min: 5 }).withMessage('Password must be at least 5 characters long'),
    body('email').isEmail().withMessage('Email must be a valid email address'),
    async (req, res) => {
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            return res.status(400).json({ errors: errors.array() });
        }

        // Hash the password
        const hashedPassword = await bcrypt.hash(req.body.password, 10);

        const user = new User({
            email: req.body.email,
            password: hashedPassword,
            // add other properties here
        });

        try {
            const newUser = await user.save();
            res.status(201).json(newUser);
        } catch(err) {
            res.status(400).json({ message: err.message });
        }
    }
);

// Update a user
router.put('/:id', getUser, async (req, res) => {
    // Update user properties here

    try {
        const updatedUser = await res.user.save();
        res.json(updatedUser);
    } catch(err) {
        res.status(400).json({ message: err.message });
    }
});

// Middleware function for getting user by ID
async function getUser(req, res, next) {
    let user;

    try {
        user = await User.findById(req.params.id);
        if (user == null) {
            return res.status(404).json({ message: 'Cannot find user' });
        }
    } catch(err) {
        return res.status(500).json({ message: err.message });
    }

    res.user = user;
    next();
}

module.exports = router;

and this is my successful manual connection showing my AWS Instance is able to reach the DocumentDB instance:

$ mongo --host aws-documentdb-cluster-url:27017 -u username -p 'password' --tls --tlsCAFile ./certs/global-bundle.pem
MongoDB shell version v4.4.22
connecting to: mongodb://aws-documentdb-cluster-url:27017/?compressors=disabled&gssapiServiceName=mongodb
{"t":{"$date":"2023-07-13T03:54:18.346Z"},"s":"I",  "c":"NETWORK",  "id":5490002, "ctx":"thread1","msg":"Started a new thread for the timer service"}
Implicit session: session { "id" : UUID("7fb19d43-8475-498e-9125-931fd25de7b6") }
MongoDB server version: 5.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>

What is going wrong?

I am expecting a successful connection between my AWS instance and my AWS DocumentDB cluster using node.js

  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Jul 13 '23 at 15:57
  • Anyone have any ideas? – IT-Biscuit Jul 21 '23 at 05:21

0 Answers0