Error: Authentication code missing (Mongoose-encryption) - javascript

im getting this error while login a registred user
ofcourse i got this error after using dotenv package to secure my database encryption key
but proccess.env.SECRET is working currectly
i guess my problem is here :
userSchema.plugin(encrypt, {
secret: process.env.SECRET,
encryptedFields: ["password"],
});
app.js :
require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require("mongoose");
const encrypt = require("mongoose-encryption");
const app = express();
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: true }));
mongoose.connect("mongodb://localhost:27017/userDB", {
useUnifiedTopology: true,
useNewUrlParser: true,
});
const userSchema = new mongoose.Schema({
email: String,
password: String,
});
//_
// encrypting password field // |
userSchema.plugin(encrypt, { // | i guess problem is here
secret: process.env.SECRET, // |
encryptedFields: ["password"], //_|
});
const User = mongoose.model("User", userSchema);
error :
Error: Authentication code missing
at Object.schema.methods.authenticateSync (C:\Users\Amir\Desktop\security\node_modules\mongoose-encryption\lib\plugins\mongoose-encryption.js:419:23)
at model.<anonymous> (C:\Users\Amir\Desktop\security\node_modules\mongoose-encryption\lib\plugins\mongoose-encryption.js:239:47)
at Kareem.execPreSync (C:\Users\Amir\Desktop\security\node_modules\kareem\index.js:115:16)
at model.syncWrapper [as $__init] (C:\Users\Amir\Desktop\security\node_modules\kareem\index.js:232:12)
at model.Document.init (C:\Users\Amir\Desktop\security\node_modules\mongoose\lib\document.js:513:8)
at completeOne (C:\Users\Amir\Desktop\security\node_modules\mongoose\lib\query.js:2853:12)
at model.Query.Query._completeOne (C:\Users\Amir\Desktop\security\node_modules\mongoose\lib\query.js:2094:7)
at Immediate.<anonymous> (C:\Users\Amir\Desktop\security\node_modules\mongoose\lib\query.js:2138:10)
at Immediate.<anonymous> (C:\Users\Amir\Desktop\security\node_modules\mquery\lib\utils.js:116:16)
at processImmediate (internal/timers.js:456:21)

I had the same problem and this worked for me:
Navigate to your database using your terminal using (as much I can see you use mongo) ex:
show dbs, use databaseName, show collections, db.databaseName.find() and then
Empty your database db.databaseName.drop() (If it is important stuff, then keep it somewhere safe so you can reuse it again, should be easy if you use Postman)
And recreate your database

You should delete the existing documents in your database and run the code again with an empty document.

Actually, the thing is that you might be using your new encryption on data which was stored before the addition of encryption , whereas if you check the same with the new data it will work fine , thus you should create a new database first so that you add new items in it , and it will hopefully work for you . :)

Well, I was facing with the same issue, but it occurs only to the data which you have stored in the database previously using mongoose-encryption without dotenv.
However, it works fine
when you create a new data by registering as new user.
Drop the database and create a new one. (Make sure you save the data before doing it).
:)

The reason is you might changed the "encryption key". If you can find out the one you made it at start, then you can still check and use this database in your (.js) file. However, "Error: Authentication code missing (Mongoose-encryption)" does not mean you destroy it. You still can use. Have a try!

Yes,
You should try to Drop your Database once and Start the server agein.
It may be possible that you have changed your encryption "secret" code a bit while transferring it to the .env file.
Don't forget to take backup before dropping it.

To fix this error, drop the collection you are trying to encrypt (with db.<collection-name>.drop() and create it again.
You are seeing this error because some of the data in your database is not encrypted while the rest of it is encrypted.

In my case, the error was triggered by the usage of findOneAndReplace.
I wanted to replace the record if it already existed in this way:
const newCredentials = { userId, securedCredentials};
await Credentials.findOneAndReplace({ userId }, newCredentials, {upsert:true});
I noticed that the code works if we try to add the object in the standard way:
await new Credentials(newCredentials).save();
Thus the problem is that we are trying to upsert a non-encrypted object. Ok, let's encrypt it then! I tried by calling the encrypt method, but that doesn't work
// The following line doesn't work. `encrypted` is undefined
const encrypted = await new Credentials(newCredentials).encrypt();
// This does work though...
const credentials = new Credentials(newCredentials);
credentials.encrypt((err) => {console.log(credentials)});
As I couldn't figure out how to do this in an atomic operation, I just went the long way:
await Credentials.deleteOne({userId});
await new Credentials(newCredentials).save();
If someone has an idea about how to atomize the operation, it would be great!

You don't have the MongoDB server port 27017 active on your system.
To do that, simply write "mongod" command in another tab of your hyper terminal.

Related

Giveaway commands does not save (Heroku) discord.js

I am making a giveaway command, but whenever I restart all dynos in heroku it seems the giveaway just froze(Never ends the giveaway) and when I do !gdelete {messageid} It says there is no giveaway for {messageid} any idea why and how to fix it. I have tried using quick.db but still the same and I am quite new to heroku and coding discord bot. Im using node.js
const { GiveawaysManager } = require("discord-giveaways");
const manager = new GiveawaysManager(bot, {
storage: "./giveaways.json",
updateCountdownEvery: 10000,
default: {
botsCanWin: false,
embedColor: "#FF0000",
reaction: "🎉"
}
})
bot.giveawaysManager = manager;
Heres the code
And heres the gstart command: https://pastebin.com/9tBjpVEY
The issue is caused by Heroku, which doesn't store local files when you're not running the app. Every time you restart a dyno Heroku deletes everything and rebuilds it: that means that if you save your files locally when it restarts they'll get deleted.
To solve this issue you need either to switch to another service or to create some form of backup for your file.
You could also use a remote database, but I don't know how that could be implemented with the discord-giveaways package.
I had the same issue and I think that it can be solved by doing this:
Instead of using quick.db, you can use quickmongo which just the same as quick.db and discord-giveaways also has an example of it. Although there is one change that you need to make. The example of quickmongo also shows a local way to store the files but instead of typing the localhost string, replace it with the MongoDB Compass connection string of your MongoDB cluster and give the new collection the same name which is giveaways.
In order to get the connection string, log in to your MongoDB account and create a cluster. After creating the cluster, click the connect button on the cluster and then select Connect using MongoDB Compass. From there you will see a connection string. Copy and paste that string in the place where there was the localhost string. Then replace <password> with your account's password which is your password with your username. Also, replace the test at the end with giveaways and you are good to go. After running the code, you would also see a collection named giveaways in the Collections Tab inside your cluster.
Example:
const db = new Database('connectionLink/giveaways');
db.once('ready', async () => {
if ((await db.get('giveaways')) === null) await db.set('giveaways', []);
console.log('Giveaway Database Loaded');
});

Mongodb does not save a document

I am trying to store some data from an HTML formulary. I send the data using the HTTP POST method and I received them using Express framework in Node.js. The data arrives and it seems to work, but when I try to store them into MongoDB using Mongoose, the database is created but no data is stored when I execute DB.sis_dictionary.find()
I've tried to build different types of schemas and models, but none seems to work. And I get no error from Node.js, it seems to be working, but the MongoDB database does not store anything.
const Mongoose = require('mongoose');
Mongoose.connect('mongodb://localhost:27017/sis_dictionary', {useNewUrlParser: true});
const Schema = Mongoose.Schema;
const wordSchema = new Schema({
word: String
})
const Word = Mongoose.model('Word', wordSchema);
app.post('/saveWord', (req, res) => {
var word = new Word({word: String(req.body)});
word.save(function(err){
if(err) {
return console.error(err);
} else {
console.log("STATUS: WORKING");
}
})
console.log(req.body);
})
server.listen(3000);
console.log("SERVER STARTUP SUCCESS");
In the console, I get the message: "STATUS: WORKING".
sis_ditionary is your DB name and Words should be your collection name. As mongoose automatically creates a plural name for collection from a model if model name not specified when creating from a schema
db.collection.find() is a command to find a collection data when using mongo-shell. Run below command to get data:
use sis_dictionary
db.Words.find()
To beautify result use pretty method
db.Words.find().pretty()
First command will select DB and second command list collection data.
So when you execute db.sis_dictionary.find() it won't work because sis_dictinary is your DB name.
Nodejs way with 'mongoose'
//Model.find({});
Word.find({});
Also, check this line var word = new Word({word: String(req.body)});
What does req.body have? If req.body is {word:"example word"} then you directly pass req.body to modal constructor ie new Word(req.body);
According to your database URL, mongodb://localhost:27017/sis_dictionary, sis_dictionary is the database name.
And according to your mongoose model, Word is your collection name.
When you save a document, it saves under a collection. So you have to make a query under the collections.
So when you try to get data using DB.sis_dictionary.find(), definitely it won't work.
Your query should be like db.collection.find()
Use the following query,
use sis_dictionary
db.words.find()
// for better view
db.words.find().pretty()
For more please check the documentation.
Thank you everybody. You were all right, it was a problem related to my collections names. db.words.find().pretty() worked perfectly!The problem is solved.

Is it safe to use a single Mongoose database from two files/processes?

I've been working on a server and a push notification daemon that will both run simultaneously and interact with the same database. The idea behind this is that if one goes down, the other will still function.
I normally use Swift but for this project I'm writing it in Node, using Mongoose as my database. I've created a helper class that I import in both my server.js file and my notifier.js file.
const Mongoose = require('mongoose');
const Device = require('./device'); // This is a Schema
var uri = 'mongodb://localhost/devices';
function Database() {
Mongoose.connect(uri, { useMongoClient: true }, function(err) {
console.log('connected: ' + err);
});
}
Database.prototype.findDevice = function(params, callback) {
Device.findOne(params, function(err, device) {
// etc...
});
};
module.exports = Database;
Then separately from both server.js and notifier.js I create objects and query the database:
const Database = require('./db');
const db = new Database();
db.findDevice(params, function(err, device) {
// Simplified, but I edit and save things back to the database via db
device.token = 'blah';
device.save();
});
Is this safe to do? When working with Swift (and Objective-C) I'm always concerned about making things thread safe. Is this a concern? Should I be worried about race conditions and modifying the same files at the same time?
Also, bonus question: How does Mongoose share a connection between files (or processes?). For example Mongoose.connection.readyState returns the same thing from different files.
The short answer is "safe enough."
The long answer has to do with understanding what sort of consistency guarantees your system needs, how you've configured MongoDB, and whether there's any sharding or replication going on.
For the latter, you'll want to read about atomicity and consistency and perhaps also peek at write concern.
A good way to answer these questions, even when you think you've figured it out, is to test scenarios: Hammer a duplicate of your system with fake data and events and see if what happen is OK or not.

Node JS sending data via URL

Recently i started programming with Node JS and found it an amazing replacement for php . In php i used to send get requests with Data in the url .
Something like : http://sample.com/public.php?x=helloworld
How to perform something like this in Node JS or is there a better way to send data to node unlike using the url in the above case .
Also , I have noticed that in some cases like stackoverflow , queries are different and dont include the file name
like /public?= instead of /public.php?=
How is this achieved , i always thought this was something related to REST . Also , if you have the answer you might as well guide me if it could be done with Node and a few sources to learn could be of help too .
the most regular way to use REST api
req.query
// GET /search?q=foo+bar
req.query.q
// => "foo bar"
// GET /phone?order=desc&phone[color]=black&shoe[type]=apple
req.query.order
// => "desc"
req.query.phone.color
// => "black"
req.params
// GET /user/william
req.params.name
// => "william"
req.body(for form data)
// POST /login
req.body.username
// => "william"
req.body.password
// => "xxxxxx"
You'll probably be much better off using a pre-existing module as your web server. You can set one up manually, but you have to know about a lot of potential edge cases and really understand web servers. Most people in node use express. In node, as in any server-side language, you can pass data around in a few ways. The query string is one. You can also put some parameters directly in the url (like "/users/12" where 12 is a user id). Depending on the type of request, you can put data in the body of the request. You can also pass cookies. These are not node-specific. Explaining how express works in a post like this would be crazy, so I'll just give you a short example of a what a route handler matching your example route might look like:
var express = require('express');
var app = express();
app.get('/public', function(req, res, next) {
// Get the value from the query string. Express makes the query
// available as an object on the request parameter.
var x = req.query.x;
// Execute your main logic
doSomethingWithX(x);
// Send a response
res.status(200).json({ foo: 'bar' });
});

node + express + mongoose query authentification

Im building a simple web app app in express, and I'm a bit stuck in the authentification for my sessions, im going to validate everything in the client with backbone and regExp eventually when i start building the front end of the app. no basycally i have an issue with the query in mongoose returning a mongoose document object. I've looked up a couple of solutions, in the query you can use a .lean() to get an object, or grab the return from the query and apply a .toObject(), that all works fine and dandy, however when i try and authenticate the value of the key with a string it returns false. i'll post an example code, its not exactly what i've got, but its close enough to get the point across.
this would be an example of my models file
var User = new Schema({}, { strict: false });
User.method('authenticate', function(plainText) {
var object = this.toObject();
return plainText == object.password; });
mongoose.model('User', User);
mongoose.connect( definitions.dbConnect );
and in my app file i would have something like
app.get('/session', routes.showLogin);
app.post('/session/new', routes.login);
and in my routes file id have something like
exports.login = function(req, res){
var userQuery = new RegExp(req.body.username , 'i');
var passwordQuery = new RegExp(req.body.password, 'i');
var Query = User.find();
Query.findOne().where('username', userQuery).exec(function(err, user){
if(user && user.authenticate((req.body.password))){
req.session.userId = user._id;
}else{
res.redirect('/session');
}
});
},
Any ideas would be appreciated, its probably very silly... : /
Thanks in advanced!
YEah robert klep was right on the money, After i seearched the mongoose Documentation and the mongodb docs as well, it became clear that queries return a mongo document object, in terms should be converted to the same object or variable types for opperands to work.

Categories