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

Node.js + express : rewrite url path

I'd like to know if it's possible to rewrite an url with express.
I actually have this code :
var http, express, app;
http = require("http");
express = require("express");
app = express();
app.use(express.json())
app.use(express.urlencoded())
.post("/ajax_login", function (req, res) {
"use strict";
http.get({ host: "localhost", port: 8080, path: "/users/" + req.body.email + "/email" }, function (resp) {
resp.setEncoding("utf8");
resp.on("data", function (data) {
json = JSON.parse(data);
if (json.password.password === sha1(req.body.password)) {
res.render("home.ejs");
} else {
res.render("login.ejs", { email : req.body.email, error : "password is not good" });
}
});
});
})
.get("/login", function (req, res) {
"use strict";
res.render("login.ejs");
})
.listen(3030);
I call /ajax_login from a form :
<form method="post" action="/ajax_login">
<div class="form-group">
<label for="email">Email address</label>
<input type="email" class="form-control" id="email" name="email" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" name="password" />
</div>
<button type="submit" class="btn btn-primary">Connection</button>
</form>
The problem is : when I call /ajax_login, after res.render my HTML code on my browser is changed, but the url still /ajax_login.
How I can change this URL ?
I know the javascript solution :
window.history.pushState("", document.title, "/login");
But, I'd like to know if a solution exist from the server.
Thanks
I would add an error to the request locals, redirect to login, and then check if an error exists when rendering the login page.
.post("/ajax_login", function (req, res) {
"use strict";
...
if (password && email IS OK) {
res.locals.errorMSG = "password is not good";
res.redirect("/login"); //redirect vs render
} else {
res.render("home.ejs");
}
})
.get("/login", function (req, res) {
"use strict";
res.render("login.ejs", {error: res.locals.errorMSG || null});
})
res.locals
res.redirect

How to submit a HTML contact form using Node?

I am having an issue trying to setup a contact form to be submitted using my node express app. I already have Nodemailer installed but I haven't used it before. Here is what I have so far..................
app.js
var express = require('express');
var fs = require('fs');
var bodyParser = require('body-parser');
var nodemailer = require('nodemailer');
var app = express();
app.use(express.static(process.cwd() + '/public'));
app.use(bodyParser.urlencoded({extended: true}));
app.get('/', function(req, res){
res.send(fs.readFileSync('./views/index.html', 'utf8'));
});
app.post('/', function(req, res) {
if(req.body.mail == "" || req.body.subject == "") {
res.send("Error: Email & Subject should not be Blank");
return false;
}
var smtpTransport = nodemailer.createTransport("SMTP", {
host: "smtp.gmail.com",
secureConnection: true,
port: 465,
auth: {
user: '',
pass: ''
}
});
var mailOptions = {
from: "Node Emailer - <email#gmail.com>",
to: req.body.email,
subject: req.body.subject + " -",
html: "<b>"+req.body.description+"<b>"
}
smtpTransport.sendMail(mailOptions, function(error, response) {
if (error) {
res.send("Email could not be sent due to error:" +error);
}else {
res.send("Email has been sent successfully");
}
});
});
app.listen(process.env.PORT || 3000, function() {
console.log("LISTENING!");
});
Contact Form
<form action='/' method='post' class='contact-form commentsblock'>
<div>
<label for='g52-name' class='grunion-field-label name'>Name<span>
(required)</span></label>
<input type='text' name='g52-name' id='g52-name' value=''
class='name'
required aria-required='true'/>
</div>
<div>
<label for='g52-email' class='grunion-field-label email'>Email<span>
(required)</span></label>
<input type='email' name='g52-email' id='g52-email' value=''
class='email' required aria-required='true'/>
</div>
<div>
<label for='g52-website' class='grunion-field-label
url'>Website</label>
<input type='text' name='g52-website' id='g52-website' value=''
class='url' />
</div>
<div>
<label for='contact-form-comment-g52-comment' class='grunion-field-label textarea'>Comment<span>(required)</span></label>
<textarea name='g52-comment' id='contact-form-comment-g52-comment' rows='20' class='textarea' required aria-required='true'></textarea>
</div>
<p class='contact-submit'>
<input type='submit' value='Submit' class='pushbutton-wide'/>
</form>
I haven't had much experience sending mail using Node. I have a one page site and all I want to do is to be able to send emails. How do I connect my form with Node?
All fields you check through req.body need to match the name="" attributes of your <input> and <textarea> HTML elements. It seems you don't fetch any of those values in your script, and sometimes arbitrarily look at either req.body.email or req.body.mail. If you console.log(req.body) on submit, you'll rather see something like:
{
"g52-name": "...",
"g52-email": "...",
"g52-website": "...",
"g52-comment": "..."
}
This is where your form content is.
app.post('/', function(req, res) {
var subject = req.body["g52-name"];
var mail = req.body["g52-email"];
var website = req.body["g52-website"];
var description = req.body["g52-comment"];
if (!subject || !mail) {
res.send("Error: Email & Subject should not be Blank");
return false;
}
// rest of email-sending code here
// ...
}

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.');
});
}

AWS S3 & NodeJS - xhr error

I am trying follow along this tutorial on uploading files to Amazon S3 with NodeJS and have gotten hung up on an error that occurs on the client side of the code, but I'm pretty sure is part of my route. The 404 error that appears is on the xhr.send() request to the server in the sign_request function. The information from my file that is logged at the GET is correct file:138 GET http://localhost:3000/sign?file_name=gtm-value.png&file_type=image/png 404 (Not Found), which makes me think that it has something to do with my route setup.
view:
<!DOCTYPE html>
<head>
{{> app/app-head}}
</head>
<body>
{{> app/app-navigation}}
<div class="container">
<div class="col-md-12">
<form action="/create" method="post">
<input type="file" name="fileAttachment" id="image">
<img id="preview">
<button type="submit" id="button">Create Image</button>
</form>
</div>
<script type="text/javascript">
function upload(file, signed_request, url, done) {
var xhr = new XMLHttpRequest();
xhr.open("PUT", signed_request);
xhr.setRequestHeader('x-amz-acl', 'public-read');
xhr.onload = function() {
if (xhr.status === 200) {
done()
};
};
xhr.send(file);
}
function sign_request(file, done) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/sign?file_name=" + file.name + "&file_type=" + file.type);
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
done(response);
}
};
xhr.send();
};
document.getElementById("image").onchange = function() {
var file = document.getElementById("image").files[0]
if (!file) return
sign_request(file, function(response) {
upload(file, response.signed_request, response.url, function() {
document.getElementById("preview").src = response.url
});
});
};
</script>
route:
var aws = require('aws-sdk');
appRoutes.get('/sign', function(req, res){
aws.config.update({accessKeyId: config.awsAccessKeyId, secretAccessKey: config.awsSecretAccessKey});
var s3 = new aws.S3();
var options = {
Bucket: config.awsBucket,
Key: req.query.file_name,
Expires: 60,
ContentType: req.query.file_type,
ACL: 'public-read'
}
s3.getSignedUrl('putObject', options, function(err, data){
if(err) return res.send('Error with S3')
res.json({
signed_request: data,
url: 'https://s3.amazonaws.com/' + config.awsBucket + '/' + req.query.file_name
});
});
});
The issue was unrelated to the code and an issue with the permissions provided to the user with the auth key. After giving the user an AdministrativeAccess policy the issue was resolved.

Not getting response when sending post request to node server

I am using Express with node js. If I run my HTML template on different host or server (other than the one which my application is running) then I am not getting any response.
If I make post request to the node server from a file hosted on same server then it gives a JSON response successfully.
I want to create a REST API application, so everyone can just post a request and use response data.
My code of the HTML file (running on locally on the node server):
<script type="javascript">
function submitit() {
var name = $('#name').val();
var id = $('#pw').val();
var obj = {
name: name,
id: id
};
//posting on node server
$.post('http://localhost:3001/user', {
data1: obj
}, function (data, status) {
alert(data);
//window.location.href = "http://google.com";
}, 'json')
}
</script>
<body>
<h1 class="hone">Log in to site.</h1>
<form method = "post" id="yourform">
user id :<input type="text" id='name' name="userid" /><br />
password :<input type="text" id='pw' name="password" /><br />
</form>
<input id="formsubmit" type="button" onclick='submitit();' value="login" /><br />
<div id="flash"></div>
</body>
app.js on the node server:
app.post("/user", function (req, res) {
console.log("ok");
//var h=req.params.name;
var user = {
"name": "sdf",
"add": "f"
};
//var r = req.body.name;
console.log(user);
console.log(req.body.data1);
res.json(user);
});
This is working fine if I request from the same host, but if send a request from a file a different machine it's not working.
Got solution, have to just add middle ware for cross domain communication
add bellow middle ware to yout app.js or script code.
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.use(allowCrossDomain);

Resources