Nodejs Expressjs session ip and browser agent match - mysql

I am using connect-mysql-session to store sessions in db. Now my question is how do i add user data containing browser agent and ip-adress to check if the session is valid? How do i obtain that information? And how do i check if it matches?
users.login(credentials,function(err, results) {
//On errors
if (err) {
res.render(routes.index, {
title: 'Login'
});
//On success
} else if (results[0]) {
//Set session data and redirect to start page
req.session.userdata = results[0];
req.session.userdata.email = req.body.email_login;
req.session.is_logged_in = true;
res.redirect('/start');
//Wrong credentials
} else {
req.flash('warning','Wrong password or login');
res.render('index', {
title: 'Login'
});
}
});
Update:
I now got this added to the session:
req.session.ip = req.connection.remoteAddress;
req.session.useragent = req.headers['user-agent'];
and check for it in my auth middleware:
if(req.session.userdata && req.session.is_logged_in === true && req.session.ip === req.connection.remoteAddress && req.session.useragent === req.headers['user-agent']) {
next();
} else {
res.redirect('/');
}
Is this secure or do you see any risks with this? Should i go about it another way?

Your implementation looks good, and will give you some - very - basic protection against session hijacking.
However, I'm not sure I understand your middleware. What prevents an user from requesting /start directly? And, more importantly, as the middleware intercepts all requests, even those for /start, doesn't this look like some infinite redirect loop?
My suggestion would simply be to consider a user logged out at all time when ip or user agent mismatches.

Related

Angular/Http "put" method only returning undefined?

I've been trying to make a very basic app pulling user information from a .json file and "logging them in", and have a json storing whether a user is logged into the app and their user ID. I'm stuck on a method which would take the given email and password, match them to an entry in the users json, then update the login json with the new information (login true, and user ID.) This is what I have so far in the method:
setUserLogIn(email, password):any{
if (this.users){
this.users.forEach(foundUser => {
if (foundUser.email === email && foundUser.password === password){
this.currentUser=foundUser;
let login:Login = {"id": 1, "loginStatus":true, "userId":foundUser.id}
return this.httpService.put<Observable<any>>('http://localhost:7800/loginCheck/1', login)
.pipe(map((log:Observable<Login>) =>{
console.log(log) //this isn't reached, never prints in console
if (log !== undefined){
return true;
}
return false;
}))
}
if (this.currentUser != null){
FetchUserService.isLoggedIn = true;
} else{
FetchUserService.isLoggedIn = false;
}
})
}
}
From my previous tests I know everything else in the method works correctly, just the put only returns undefined. I am subscribing to the method in the controller:
this.fetchUserService.setUserLogIn(this.userEmail, this.userPassword).subscribe(data => {
console.log(data);
})
This method of subscription returns an error. I also tried subscribing in the service itself, like:
return this.httpService.put<Observable<any>>('http://localhost:7800/loginCheck/1', login)
.pipe(map((log:Observable<Login>) =>{
console.log(log)
if (log !== undefined){
log.subscribe(data => {
return data
})
Taking this into the component and logging the result also just returns undefined.
Any suggestions? I have no idea what I'm doing wrong, after searching put methods for the past few hours I can't see any differences in what I have there. Any help is greatly appreciated!
There are multiple issues here.
Parallel subscriptions. Avoid them if possible. Here you could use forkJoin to combine all observables and trigger them in parallel.
Why would an HTTP request emit an Observable as it's response? Most probably it wouldn't.
Currently you aren't returning anything from the function.
Try the following
setUserLogIn (email, password): Observable<any> { // <-- return `Observable` here
if (!this.users) return NEVER;
return forkJoin(
this.users.map(foundUser => {
if (foundUser.email === email && foundUser.password === password) {
this.currentUser = foundUser;
FetchUserService.isLoggedIn = true;
let login: Login = {
"id": 1,
"loginStatus": true,
"userId": foundUser.id
};
return this.httpService.put('http://localhost:7800/loginCheck/1', login).pipe(
map((log: Login) => { // why would an HTTP request emit an observable?
console.log(log);
return (!!log);
})
);
}
FetchUserService.isLoggedIn = false;
return EMPTY; // `forkJoin` emits only when all observables complete
})
);
}

Get list of blocked requests in Puppeteer

I am trying to get a list of requests that are blocked by the browser (HTTP on HTTPS sites). I tried
page.on('requestfailed', request => {
console.log(request.url());
console.log('failed');
});
but it did not provide the requests. The only requests I saw were those of URLs that do not exist anymore. The blocked (HTTP) request do also not trigger the request event.
page.on('request', request => {
console.log(request.url());
}
Is there another event I can listen to?
EDIT:
I can see that something failed when I use
page._client.on('Network.loadingFailed', async event => {
const request = await page._networkManager._requestIdToRequest.get(event.requestId);
console.log(event);
console.log(request);
});
but the request var is undefined. So I don't know which request failed.
Found out how to solve this
page._client.on('Network.loadingFailed', async event => {
if (requestToBySend[event.requestId] !== undefined) {
let reason = '';
if (event.blockedReason !== undefined) {
reason = event.blockedReason;
} else {
reason = event.errorText;
}
console.log('blocked: ' + requestToBySend[event.requestId] + '; reason: ' + reason);
}
});
page._client.on('Network.requestWillBeSent', async event => {
requestToBySend[event.requestId] = event.request.url;
});
The requestId is known on requestWillbeSent event. I just store those ids to look them up when I need them.
The Chrome events I use can be found here: https://chromedevtools.github.io/devtools-protocol/tot/Network#event-loadingFailed

sails.js: how to update model

Forgive my noob question. I'm using angularjs to send a user model (json) with varying fields. It works well with sails.js default PUT. I overrode the PUT, the problem is that I wish to update the model with the received JSON and do some processing on the modified model. Now I can't update the model with
User.update({
id: req.body.id
},{
req.body
}, function(err, users) {
// Error handling
if (err) {
return console.log(err);
// Updated users successfully!
} else {
console.log("Users updated:", users);
}
});
Please help
EDIT:
After knocking my head on the wall for days, problem solved! I know, my code formatting here is not the best..
changed this:
{
req.body
}
to just:
req.body
(without the braces)
full snippet becomes:
User.update({
id: req.body.id
},
req.body
, function(err, users) {
// Error handling
if (err) {
return console.log(err);
// Updated users successfully!
} else {
console.log("Users updated:", users);
}
});
Thanks.
So you figured out your problem, sort of. req.body is already an object. But you really should sanitize it before you put it into your update and then save the object. There's a lot of reasons for this but with Mongo when you get only a partial object you'll replace the object in the collection which, in your example with a user, could be bad. When I send users to the frontend I cull off things I don't want transmitted all over like passwords. The other reason is the golden rule of web application development - never trust the client! I'd start with something like:
var user = User.findOne(req.body.id).done(function(error, user) {
if(error) {
// do something with the error.
}
if(req.body.email) {
// validate whether the email address is valid?
// Then save it to the object.
user.email = req.body.email;
}
// Repeat for each eligible attribute, etc.
user.save(function(error) {
if(error) {
// do something with the error.
} else {
// value saved!
req.send(user);
}
});
});

peerConnection.addIceCandidate giving error: invalid string

I am trying to implement a Voice-only WebRTC app. I am running it on Chrome Version 29.0.1547.0 dev. My app uses Socket.IO for the signaling mechanism.
peerConnection.addIceCandidate() is giving me this error: Uncaught SyntaxError: An invalid or illegal string was specified.
and separately, peerConnection.setRemoteDescription(); is giving me this error: Uncaught TypeMismatchError: The type of an object was incompatible with the expected type of the parameter associated to the object.
Here's my code:
SERVER (in CoffeeScript)
app = require("express")()
server = require("http").createServer(app).listen(3000)
io = require("socket.io").listen(server)
app.get "/", (req, res) -> res.sendfile("index.html")
app.get "/client.js", (req, res) -> res.sendfile("client.js")
io.sockets.on "connection", (socket) ->
socket.on "message", (data) ->
socket.broadcast.emit "message", data
CLIENT (in JavaScript)
var socket = io.connect("http://localhost:3000");
var pc = new webkitRTCPeerConnection({
"iceServers": [{"url": "stun:stun.l.google.com:19302"}]
});
navigator.getUserMedia = navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
navigator.getUserMedia({audio: true}, function (stream) {
pc.addStream(stream);
}, function (error) { console.log(error); });
pc.onicecandidate = function (event) {
if (!event || !event.candidate) return;
socket.emit("message", {
type: "iceCandidate",
"candidate": event.candidate
});
};
pc.onaddstream = function(event) {
var audioElem = document.createElement("audio");
audioElem.src = webkitURL.createObjectURL(event.stream);
audioElem.autoplay = true;
document.appendChild(audioElem);
console.log("Got Remote Stream");
};
socket.on("message", function(data) {
if (data.type === "iceCandidate") {
console.log(data.candidate);
candidate = new RTCIceCandidate(data.candidate);
console.log(candidate);
pc.addIceCandidate(candidate);
} else if (data.type === "offer") {
pc.setRemoteDescription(data.description);
pc.createAnswer(function(description) {
pc.setLocalDescription(description);
socket.emit("message", {type: "answer", description: description});
});
} else if (data.type === "answer") {
pc.setRemoteDescription(data.description);
}
});
function offer() {
pc.createOffer( function (description) {
pc.setLocalDescription(description);
socket.emit("message", {type: "offer", "description": description});
});
};
The HTML just contains a button that calls offer().
I can confirm the ICECandidates and SessionDescriptions are transferring successfully from one client to the other.
What am I doing wrong? And how should I fix these and any other errors so that I can transfer audio from one client to the other?
PS: If you know about a good source documenting the WebRTC API (except the W3C documentation), please tell me about it!
Thanks!
For that error the point is, ICE Candidates must be added only after successfully setting remote description.
Note that just after creating Offer (by Offerer), ice candidates are produced immediately. So, if somehow the answerer receives those candidates, before setting remote description (which in theory would arrive before candidates), you get error.
The same is true for offerer. It must set remote description before adding any ice candidate.
I see that in your javascript code you are not guaranteeing that remote description is set before adding ice candidates.
First of all you can check just before pc.addIceCandidate(candidate); if pc's remoteDescription is set. If you see that it is null (or undefined), you can locally store received ice candidates to add them after setting remoteDescription (or wait in offerer to send them in proper time.)

Users have no access to application

I'm building an application in Google Apps Script. I'm authenticating the domain users by checking if their logonid is permitted to use the application.
I developed it and when I entered the testing phase, I was the only user that could actually use the application.
Although I had set the "Who has Access" combobox on the web-app publish wizard to "anyone".
When a user executes the application he will get an exception saying he has no access when executing the first function after doGet(). Did I overlook some settings or did I do something wrong?
I use the following classes:
UserManager
Session
Jdbc
Utilities
Logger
This is the function that is called after the doGet() function:
function authenticateUser() {
try {
var user = UserManager.getUser(Session.getActiveUser());
Logger.log('User: ' + user.getEmail());
if (user == undefined || user == null) {
return {authenticated: false};
} else {
var auth = _getAuth();
if (!auth.isAuthorized(user.getEmail())) {
Logger.log('Not authorized in database.');
return {authenticated: false};
} else {
var profile = auth.getProfile(user.getEmail());
authenticated = true;
auth.setLogin(user.getEmail());
if(!profile.firstLogin) {
activeProfile = profile;
}
activeUser = user;
return {profile: profile, authenticated: true};
}
}
} catch(ex) {
Logger.log(ex);
return {authenticated: false};
}
}
Access to UserManager is the issue here. As the documentation states, UserManager is only accessible to administrators.
If the app is running as a normal user, it cannot access UserManager. You may need to rethnk the deployment/code to run it as yourselves (or admin).