expressjs ldap authentication showing basic auth pop up form - node.js

I'm a newbie to expressjs and ldap.
Need your help with getting my way through the code flow.
I need to authenticate user credentials against ldap server.
I'm using this ldap library https://github.com/vesse/node-ldapauth-fork for making it work.
I get the pop-up form on my broswer that asks for my basic auth credentials after I have submitted the login credentials with the login form(loginCtrl.js).
When i enter the credentials into the popup, the backends sees them as "undefined"
My question is why is the basic auth form popping up, if I'm already sending teh credentials via loginCtrl.js
This is my front end code that calls the REST api
login.html
app.controller("loginCtrl", ["$scope", "$http", "$location","$document", "$uibModal", "$filter", "$q", function($scope, $http, $location, $document, $uibModal, $filter, $q) {
$scope.keepLoggedIn = false;
$scope.login = function() {
var body = {};
body["username"] = $scope.username;
body["password"] = $scope.password;
var auth = window.btoa($scope.username+":"+$scope.password);
console.log(auth);
/* $http.post('/login', JSON.stringify(credentials)).then(function(success){
console.log("success");
}, function(error){
console.error("error");
});*/
var results = [];
$http({
method: 'POST',
headers: {'Authorization': "Basic " + auth},
url: '/login',
data: JSON.stringify(body)
})
.then(function (success) {
console.log(success);
results.push(success);
}, function (error) {
results.push(error.data);
});
}
}]);
<div id="container">
<form ng-submit="login()">
<label for="username">Username:</label>
<input type="text" ng-model="username" id="username" name="username">
<label for="password">Password:</label>
<input type="password" ng-model="password" id="password" name="password">
<div id="lower">
<input type="checkbox" ng-model="keepLoggedIn"><label for="checkbox">Keep me logged in</label>
<input type="submit" value="Login">
</div><!--/ lower-->
</form>
</div>
This is the expressjs server code that uses ldapauth to authenticate against ldap
var express = require('express');
var basicAuth = require('basic-auth');
var LdapAuth = require('ldapauth-fork');
var app = express();
var ldap = new LdapAuth({
url: 'ldap://ldapserver.net:389',
bindDN: 'uid=root,ou=sample,dc=dept,dc=net',
bindCredentials: 'secret',
searchBase: 'ou=sample,dc=dept,dc=net',
searchFilter: '(uid={{username}})',
reconnect: true
});
ldap.on('error', function (err) {
console.error('LdapAuth: ', err);
});
var rejectBasicAuth = function(res) {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="Example"');
res.end('Access denied');
}
var basicAuthMiddleware = function(req, res, next) {
ldap.authenticate(req.body.username, req.body.password, function(err, user) {
console.log("callback:"+user);
if (err) {
console.log(err);
return rejectBasicAuth(res);
}
console.log("success");
req.user = user;
next();
});
};
app.post('/login',basicAuthMiddleware, function(req,res){
res.send({"status":"ok"});
});
app.listen(2500, function(){
console.log('Express started on http://localhost:' + 2500 + '; press Ctrl-C to terminate.');
});

Related

Connect nodemailer to form

I have a mail.js file that when run independently sends me a mail. And I have a form. I want to send mail to the email id that fils the form. How can I do that? I am not able to connect these two.
Where and how do I add mail.send();? And how to add variable email if both of these codes are in different files?
Also my html is in index.html
Thank you!!
index.html
<form action="/sign_up" method="POST" id="myForm">
<div>
<p class="cuboid-text">Subscribe</p>
</div>
<div>
<label for="submit" class="submit-icon">
<i class="fa fa-chevron-right"></i>
</label>
<input type="text" id="email" class="cuboid-text" placeholder="Your Email" autocomplete="off" name="email"/>
<input type="submit" id="submit" name="submit" class="submit" formaction="/sign_up" formmethod="POST"/>
</div>
<div>
<p class="cuboid-text loader">Just a moment ...
<i class="fa fa-spinner fa-pulse"></i>
</p>
</div>
<div>
<span class="reset-icon"><i class="fa fa-refresh"></i></span>
<p class="cuboid-text">Thankyou, we'll be in touch</p>
</div>
</form>
<script>
$("#email").focus(function () {
$("#cuboid form").addClass("ready");
})
//remove '.ready' when user blus away but only if there is no content
$("#email").blur(function () {
if ($(this).val() == "")
$("#cuboid form").removeClass("ready");
})
//If the user is typing something make the arrow green/.active
$("#email").keyup(function () {
//this adds .active class only if the input has some text
$(".submit-icon").toggleClass("active", $(this).val().length > 0);
})
$("#cuboid #myForm").submit(function () {
const re = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")#(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
const email=document.getElementById("email").value;
const re1='abcd';
console.log(email);
//prevent default form submisson
if(re.test(String(email).toLowerCase())){
console.log("true");
document.getElementById("demo1").style.visibility="hidden";
$(this).removeClass("ready").addClass("loading");
setTimeout(complete, 3000);
return true;}
else{
document.getElementById("demo1").style.visibility="visible";
// setTimeout(complete, 1000);
return false;
}
})
function complete() {
$("#cuboid form").removeClass("loading").addClass("complete");
}
//reset/refresh functionality
$(".reset-icon").click(function () {
$("#cuboid form").removeClass("complete");
})
</script>
index.js
var express = require("express")
var bodyParser = require("body-parser")
var mongoose = require("mongoose")
const app = express()
app.use(bodyParser.json())
app.use(express.static('public'))
app.use(bodyParser.urlencoded({
extended: true
}))
mongoose.connect('mongodb://localhost:27017/mydb123', {
useNewUrlParser: true,
useUnifiedTopology: true
});
var db = mongoose.connection;
db.on('error', () => console.log("Error in Connecting to Database"));
db.once('open', () => console.log("Connected to Database"));
app.post("/sign_up", (req, res) => {
// var name = req.body.name;
var email = req.body.email;
// var phno = req.body.phno;
// var password = req.body.password;
// var initrefnum = req.body.demo;
// var newrefnum = req.body.newdemo;
console.log("step1");
var data = {
// "name": name,
"email": email
// "initrefnum": initrefnum,
// "newrefnum": newrefnum
}
db.collection('users').insertOne(data, (err, collection) => {
if (err) {
throw err;
}
console.log("Record Inserted Successfully");
});
// return res.redirect('index.html')
})
app.get("/", (req, res) => {
res.set({
"Allow-access-Allow-Origin": '*'
})
return res.redirect('index1.html');
}).listen(3000);
console.log("Listening on PORT 3000");
mail.js
const nodemailer=require('nodemailer')
let mailTransporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'mail#gmail.com',
pass: '*********'
}
});
let mailDetails = {
from: 'xyz#gmail.com',
to: 'abc#gmail.com',
subject: 'Test mail',
text: 'Node.js testing mail for GeeksforGeeks'
};
mailTransporter.sendMail(mailDetails, function(err, data) {
if(err) {
console.log('Error Occurs');
} else {
console.log('Email sent successfully');
}
});
Just this <input type="submit" id="submit" />
or
<button type="submit">Submit</button> is fine
app.use(express.static('public')) // this is enough in case if you think what more to do to wire up.
Mail.js
const nodemailer = require('nodemailer');
let mailTransporter = nodemailer.createTransport({
service: 'gmail',
host: 'smtp.gmail.com',
auth: {
user: 'dee#gmail.com', //this should be same as 'from' address
pass: 'workingpassword'
}
});
module.exports = mailTransporter;
App.js
const mailTransporter = require('./mail);
for your form action, in your /sign_up post method do below
app.post('/sign_up', (req, res)=>{
mailTransporter.sendMail({
from: 'dee#gmail.com', //this should be same as above auth.user
to: `${req.body.email}`,
subject: 'Test',
text: 'hello',
html: `Hello ${req.body.name} thank you for contacting. We will get in touch`
}).then(res=>{
console.log("success........", res)
resp.send(`email sent to ${req.body.name}` successfully);
}).catch(e=>{
console.log("failed........", e)
});
});
Things to do to avoid issues,
go to https://myaccount.google.com/lesssecureapps and enable for less secure apps.
go to https://accounts.google.com/DisplayUnlockCaptcha and enable.

how to redirect to url with node js

I'm trying to do a node js project where a pseudo-login page communicate with mongooseDB and redirect in different pages based on username. The problem is: when I click on login button, this don't redirect me to any page (in inspect page-> network, I can see the corect response but nothing happen)
login.html
...
<form action="/dashboard" method="post" name="loginform" id="loginform">
<span>Inserisci i seguenti dati per accedere:</span><br><br>
<span>Username: </span>
<span id="username"></span>
<input name="nome" id="usernameuser"/><br><br>
<span> Password: </span>
<span id="userpassword"></span>
<input name="password" id="passworduser" type="password"/><br><br>
<input type="submit" value="Login"/>
</form>
<script>
const form = document.getElementById('loginform');
form.addEventListener('submit',loginUser);
async function loginUser(event){
event.preventDefault();
const username = document.getElementById('usernameuser').value;
const password = document.getElementById('passworduser').value;
if(username=='admin' && password==='admin'){
window.location.href='/libri/list';
}else{
const result = await fetch('/login',{
method: 'POST',
headers:{
'Content-Type':'application/json'
},
body: JSON.stringify({
username,
password
})
}).then((res)=>res.json())
}
}
</script>
...
login.js
...
router.post('/', async (req,res)=>{
const username= req.body.username;
const password= req.body.password;
const utente = await User.findOne({ username }).lean()
if (!utente) {
res.redirect('/dashboard');
}
if (password==utente.password) {
// the username, password combination is successful
const token = jwt.sign(
{
id: utente._id,
username: utente.username
},
JWT_SECRET
)
res.redirect('/dashboard');
}
});
...
Can you explain me the problem and an idea of solution?
Try using your fetch this way:
fetch(url, {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
.
.
.
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer'// no-referrer, *client
});
Set the redirect attribute in your options.
Let me know if it helps :)

Login System in NodeJS & Excel

So, I am creating a basic system which runs a login system in nodejs and express using an Excel file as a base. The excel CSV file will have a list of username and passwords and I am reading it using fast-csv. But when it is authenticating with the listing, it is matching only the first record. Not the other records in the excel. Any clue why? Code is as below:
index.js file
var express = require('express');
var path = require('path');
var app = express();
var bodyParser = require('body-parser');
var csv = require('fast-csv')
var fs = require('fs')
app.listen(80, function(){
console.log("Server is running")
})
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded({extended : true}));
app.post("/", function (req,res) {
fs.createReadStream(path.resolve(__dirname, 'master_data.csv'))
.pipe(csv.parse({ headers: true}))
.on('error', error => console.error(error))
.on('data', row => {
if(req.body.username == row.username && req.body.password === row.password && row.loggedIn == 'FALSE'){
res.send("Login Successful. <br> Your link is available below:" + row.link)
}else{
res.send("Login Failed")
}
})
// Log file created below
var userSchema = {
Username: req.body.username,
loginDateTime: new Date().toString(),
ipAddress: req.ip,
};
fs.appendFile('logfile.txt', JSON.stringify(userSchema) + ",", function(err, file){
if(err) throw (err);
})
});
index.html file
<html>
<head>
<title>School Login Page</title>
<link rel="stylesheet" type="text/css" href="./css/mainCSS.css">
</head>
<body>
<h2>School Login Page</h2><br>
<p>Please enter all details exactly as per details provided to you.</p>
<form action="/" method="POST">
<label for="username">Username</label>
<input type="text" id="username" name="username" value="" required><br><br>
<label for="password">Password</label>
<input type="password" id="password" name="password" required><br><br>
<input type="submit" value="submit" id="submitButton">
</form>
</body>
</html>
I also want to create an alert for a failed login but I know that you cannot create alerts server side in nodejs. How can I do this is in the front-end? Thanks
The data event is fired for each row of the CSV. What you want is to check the username and password against all present records.
To achieve this, change the following:
fs.createReadStream(path.resolve(__dirname, 'master_data.csv'))
.pipe(csv.parse({ headers: true}))
.on('error', error => console.error(error))
.on('data', row => {
if(req.body.username == row.username && req.body.password === row.password && row.loggedIn == 'FALSE'){
res.send("Login Successful. <br> Your link is available below:" + row.link)
}else{
res.send("Login Failed")
}
})
to:
let isValid = false, rowLink;
fs.createReadStream(path.resolve(__dirname, 'master_data.csv'))
.pipe(csv.parse({ headers: true}))
.on('error', error => console.error(error))
.on('data', row => {
if(req.body.username == row.username && req.body.password === row.password && row.loggedIn == 'FALSE'){
isValid = true;
rowLink = row.link
}
})
.on('end', () => {
if (isValid) {
res.send("Login Successful. <br> Your link is available below:" + rowLink)
} else {
res.send("Login Failed")
}
})

NodeJS - AJAX POST 404 (Not Found)

I am trying to send values from one file to another on click of items displayed.
While doing so, I am getting the error:
POST http://localhost:4000/todo/addToCart 404 (Not Found) jquery-3.3.1.js:9600
My app.js file:
//More codes above to set-up express and all
app.use(express.static('./public'));
todoController(app); //give todocontroller the reference to express
app.listen(4000); //listen on a port
console.log('server is running');
Controller:
module.exports = function(app) {
app.get('/todo', function(req, resp) {
Todo.find({}, function(err, data) {
if (err) throw err;
console.log('get method');
resp.render('todo', {
todos: data
});
});
});
//Few More Code
app.post('/todo', urlencodedParser, function(req, resp) {
console.log('post method');
resp.render('addToCart', {
data: req.body
});
});
};
Model for data interaction:
$('li').on('click', function() { //when user clicks on an item in the list
var item = $(this).text().replace(/ /g, "-"); //traps the item user clicked on
alert(item);
$.ajax({
type: 'POST',
url: '/todo/addToCart', //+item append that item to the url
success: function(item) {
location.reload(); //refresh the page
}
});
});
Parent ejs:
<div id="todo-table">
<form id="todoForm" method="post" action="/todo">
<input type="text" name="item" placeholder="Add new Item..." required />
<button type="submit">Add Item</button>
<ul>
<% for (var i=0;i<todos.length; i++){ %>
<li>
<%=todos[i].item%>
</li>
<% } %>
</ul>
</form>
</div>
Child ejs(to which I need to re-direct):
<div id="itemSelect">Selected Item:
<form id="addToCart" method="post" action="/addToCart">
<button type="submit" id="btnCheckOut">Check out</button>
<%=data.item%>
</form>
</div>
Please help. I am new, kindly point out my mistake.
Many thanks.
The route you created on your nodejs server here:
app.post('/todo', urlencodedParser, function (req, resp) {
console.log('post method');
resp.render('addToCart', { data: req.body });
});
Matches all the POST requests made to the /todo endpoint, not the /todo/addToCart which doesnt exist. This is why you obtain a 404.
Your ajax request should be like so:
$('li').on('click', function () {
var item = $(this).text().replace(/ /g, "-");
alert(item);
$.ajax({
type: 'POST',
url: '/todo', // 'addToCart' has been removed from the path
success: function (item) {
location.reload();
}
});
});

EmberJS empty req body

I am new to EmberJS and I'm trying to save some data to Amazon DynamoDB using nodejs and expressjs as back-end but I'm getting a empty req body when submit my form through EmberJS.
If I try it using curl, as follows, I can save the data successfully, hence this shows that the back-end is working properly.
curl --header "Content-Type: application/json" --data '{"user":{"email":"teste#teste.com","firstName":"teste","lastName":"last name","password":"teste"}}' http://localhost:3000/api/users
I tried to set the Content-Type header in the application.js JSONAPIAdapter but got no luck. I also tried to use a REST adapter and got no luck also.
Following is my code:
Front-end
model - user.js
import DS from 'ember-data';
export default DS.Model.extend({
email: DS.attr('string'),
firstName: DS.attr('string'),
lastName: DS.attr('string'),
password: DS.attr('string'),
});
template - register.hbs
<div class="container" style="margin-top: 30px;">
<div class="row">
<form class="col s12" name="registerForm" id="registerForm">
<div class="row">
<div class="input-field col s6">
{{input name="firstName" name="firstName" type="text" value=model.firstName class="validate" required="required" aria-required="true"}}
<label for="firstName">First Name</label>
</div>
<div class="input-field col s6">
{{input name="lastName" name="lastName" type="text" value=model.lastName class="validate" required="required" aria-required="true"}}
<label for="lastName">Last Name</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
{{input type="email" value=model.email name="email" class="validated" }}
<label for="email">Email</label>
</div>
<div class="input-field col s6">
{{input name="password" name="password" type="password" value=model.password class="validate" required="required" aria-required="true"}}
<label for="password">Password</label>
</div>
</div>
</form>
</div>
<div class="row">
<div class="col s6 m6 l6">
<button class="waves-effect waves-light center-align btn col s6 m6 l6 teal darken-1" {{action 'register'}} >Register Me!</button>
</div>
<div class="col s6 m6 l6">
{{#link-to 'main'}}Cancel{{/link-to}}
</div>
</div>
</div>
route - register.js
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.createRecord('user');
},
actions: {
willTransition() {
// rollbackAttributes() removes the record from the store
// if the model 'isNew'
this.controller.get('model').rollbackAttributes();
},
register() {
let email = this.controller.get('model.email');
let firstName = this.controller.get('model.firstName');
let lastName = this.controller.get('model.lastName');
let password = this.controller.get('model.password');
let user = {
email: email,
firstName: firstName,
lastName: lastName,
password: password
};
console.log('USER === ' + JSON.stringify(user));
const newUser = this.store.createRecord('user', {
user
});
newUser.save().then((response) => {
alert('Registro efetuado com sucesso ! ID = ' + response.get('id'));
this.set('email', '');
this.set('firstName', '');
this.set('lastName','');
this.set('password','');
this.transitionTo('main');
});
},
}
});
Back-end - NodeJS + ExpressJS
app.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
console.log('ENV = ' + process.env.NODE_ENV);
var cors;
if (process.env.NODE_ENV == 'production') {
cors = 'https://www.myserserver.com';
}
else {
cors = 'http://localhost:4200';
}
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', cors);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
next();
});
var globSync = require('glob').sync;
var routes = globSync('./routes/*.js', { cwd: __dirname}).map(require);
var ddb = require('dynamodb').ddb(
{
accessKeyId: 'XXXXX',
secretAccessKey: 'ZZZZZZZ',
endpoint: 'dynamodb.eu-west-1.amazonaws.com'
});
routes.forEach( function(route) {
route(app, ddb);
});
module.exports = app;
route - users.js
var express = require('express');
var uuid = require('node-uuid');
var crypto = require('crypto');
module.exports = function(app, client) {
var router = express.Router();
var options = { attributesToGet: ['nome'],
consistentRead: true
};
router.get('/users',function(req, res, next){
client.scan('users', {}, function(err, data) {
if(err) {
return res.status(200).json({"erro": err});
}
else {
res.send({user:data.items});
}
});
});
router.post('/users',function(req, res, next) {
var payload = req.body.user;
console.log('\n REQ BODY = ' + JSON.stringify(req.body) + '\n\n');
var response = '';
var id = uuid.v1();
var salt = crypto.randomBytes(16).toString('hex');
var password = payload.password; //req.body.password;
var hash = crypto.pbkdf2Sync(password, salt, 1000, 64,'sha512').toString('hex');
var firstName = payload.firstName;
var lastName = payload.lastName;
var email = payload.email;
var user = {
id: id,
email: email,
firstName: firstName,
lastName: lastName,
hash: hash,
salt: salt
}
console.log(user);
client.putItem('users', user, {}, function(err, res, cap) {
if (err) {
this.response = ('erro = ' + err);
}
else {
//console.log('PutItem: ' + cap);
console.log(res);
//this.response = ('User registered!');
}
});
return res.status(200);
});
app.use('/api', router);
};
This is the console.log for req.body when I send the data using EmberJS:
REQ BODY = {"user":{"email":null,"firstName":null,"lastName":null,"password":null}}
What am I missing here?
Thanks very much for the help!
Got it running.
For those facing the same problem, I just replace my register action with this one:
register: function() {
var _this = this;
this.get('model').save()
.then(function(data) {
console.log('signup response:', data);
alert('signup saved ok! redirect to signin');
_this.transitionToRoute('main');
},
function(data) {
alert('signup saved fail!');
_this.set('error', data.responseJSON.error || 'sorry, signup failed.');
});
}

Resources