Share module function with client side script nodejs - javascript

I made a function to check if someone is logged in on the site in the user controller module:
exports.isLoggedIn = function(req, res, next) {
if (req.user) {
return true;
} else {
return false;
}
};
I have no idea how I want to use this in a imported script on the client side. I couldn't find a good solution on the web so I thought I would ask the question myself.
If I import the script in the .html I get an error that says it doesnt know the require() function that node has.
I hope someone can help me :)

If you want client access to some data that is only available on the server, then you need to send an ajax call from the client to your server and you need to create a route on your server to respond to that ajax call.
Client code runs only on the client and has no direct access to any data on the server.
Server code runs only on the server and has no direct access to any data on the client.
To communicate between the two, you have to send a request from one to the other and then return a response. Usually this is done with an Ajax call sent from client to server. You could also establish a webSocket connection between the two and then either client or server could send data to the other.
The server also has the opportunity, when creating the original page content, to embed settings or values in the page itself, either as Javascript variables, as HTML values or even as a cookie. This obviously has to be done ahead of time when the page is rendered so it can't be a request that the client comes up with later after the page has been rendered to the client.
FYI, in the particular example you show, it is common for a client to be able to tell if it is logged in via some state in the page (either the presence of a particular cookie) or something else embedded in the page by the server. This isn't necessarily secure and isn't the way the server would tell if a request was logged in, but it usually suffices for client-side logic to decide how it wants to behave.

Related

Browser Notification Push Service: How to specify push server?

I'm trying to set up push notifications for a browser web app.
I found the following code can be used to subscribe to a push server. Running a simple push server locally seems to work fine, but
Q: I was wondering how I would specify the push server if it wasn't local?
I mean, how would the browser know where to subscribe to just by looking at the public key of the server?
function createNotificationSubscription(pushServerPublicKey) {
return navigator.serviceWorker.ready.then(
(serviceWorker) => {
return serviceWorker.pushManager
.subscribe({
userVisibleOnly: true,
applicationServerKey: pushServerPublicKey
})
.then((subscription) => {
console.log("✅ User is subscribed.", subscription);
return subscription;
});
}
);
}
References:
https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe
how do I specify the push server [...]?
You don't.
if it wasn't local?
There is a misunderstanding.
The push server will always be a fixed server given by the browser vendor.
It basically works like this:
You subscribe()
This request goes to the notification server of the browser vendor (mozilla, google, ...).
That server will create a so called push endpoint - just a fancy word for URL. This URL serves as a mailbox: If someone sends a message to it, the push server (still being the server of the browser vendor) will forward it to the browser (client).
The server will return the push endpoint and some other information as a result of your initial subscribe().
Currently only the push server and your web app know about the push endpoint....
So your web app needs to the whole result of subscribe to the application server (which is your server).
Now your server is able to use that information to send messages to the push server. The push server will then forward the message to the client.
Here's also a flow chart depicting the flow with a little more detail in regard of the different players:
Push service: Service running on the browser vendor's server
Subscription information: URL of the push endpoint along with some keys.

Get an http call from express to angular when event happens

i'm building an angular app that will make about a thousand people to connect simultaneously to book a ticket. I want only "XYZ" of them to access simultaneously at the registration Angular component. The other ones will see a "waiting room" component until it's their turn.
I set up the whole thing like this:
User enters the page.
I make an http call to expressjs server
The server checks if the "connections" collection constains less than XYZ docs
If true, it unlocks the user registation component and with an http post req, it creates a new doc in the db. if false it leaves it hidden and shows up the waitingroom component
When user leaves the page, his doc in "connections" collection gets destroyed with an http delete call.
Fully working.
The problem is now that i want to create a kind of "priority" system, because, going like that, if you just refresh you may be lucky and get access, even if you are soon arrived and there is who is waiting since 1990's. So i introduced a "priority" system. When the user makes the first http call, if user is not allowed, the server creates a timestamp and pushes it into an array.
const timestamps = []
.
.
.
// this below is in http get req
Connessione.countDocuments({},(err,count)=>{
if(count<=nmax){
console.log("Ok")
res.status(200).json({allowed: true})
}
else{
const timestamp = req.params.timestamp;
timestamps.push(timestamp);
console.log("Semo troppi")
res.status(401).json({allowed: false})
}
});
The idea is to listen to db changes, and when there is just XYZ-1 in the db. Make a call to the first timestamp's angular frontend to say him: "Hey there, if you want we're done. You can go" and unlock him the access to registration component.
The problem is that i can't make continuous http requests every second from angular until there's a free place...
Is there any method to send a request at the server, and when server says OK, calls angular and says "Hey dude. You can go!"?
Hope you understood my question. If not ask me in the comments.
Thanks in advance
Even i had trouble with sockets in the beginning so i'll try to explain the concept in a simple way, Whenever you write an API or Endpoint you have a one way connection i.e. you send request to server and it return back some response as shown below.
Event 1:
(Client) -> Request -> (Server)
Event 2:
(Client) <- Response <- (Server)
For API's, without request you cannot get response.
To overcome this issue as of now i can think of two possible ways.
Using Sockets, With sockets you can create a two way connection. Something like this
(Server) <-> data <-> (Client)
It means you can pass data both ways, Client to server and Server to client. So whenever an event occurs(some data is added or updated in database) one can emit or broadcast it to the client and the client can listen to the socket and receive it.
In your case as it's a two connection you can emit the data from angular and
I've attached few links at the bottom. please have a look.
Using XML/AJAX Request, This is not a preferable method, using setInterval you can call the server in every 5 seconds or so and do the operation needed.
setInterval(ajaxCall, 5000); //5000 MS == 5 seconds
function ajaxCall() {
//do your AJAX stuff here
}
Links:
https://socket.io/docs/
https://alligator.io/angular/socket-io/

Include header when chunks are fetched with code splitting

I've used code splitting to seprate restricted parts of my app into different chunks. This is working great so far, now I would like to ensure that the files themselves don't get served unless authenticated. I was thinking of using ngx_http_auth_request_module
http://nginx.org/en/docs/http/ngx_http_auth_request_module.html#auth_request
Which allows to send a sub-request before serving certain files. How can I ensure that certain headers are always send as part of the HTTP request when React wants to fetch the necessary chunks?
I have trouble understanding why you would need to prevent unauthenticated malicious users to have access to your static chunks.
Dynamic imports and code splitting are mainly used to reduce the bundle size for large applications as users won't necessarily need everything.
In order to secure your app you need to prevent users from seeing or tampering with data they do not have access to. This means the security lies with the API your app is talking to.
What I do:
Reject unauthenticated requests to the API
Keep a token client-side on authentication
Pass and check the token on all requests
Burn the token when obsolete and redirect to login
Notify, redirect users when they do not have access to some data or better not displaying content they do not have access to
I'm sure you already did what I wrote above, what I want to emphasize is that chunks are basically empty UI filled with data from the secured API.
Let's say I have bad intentions and I bypass client-side routing in order to have access to the restricted chunk. It will be an empty UI with secured API routes, I won't be able to do anything with it.
In case you have a very specific need, you might need to write a webpack plugin.
about the ensure request
One of webpack 's properties is that it can fetch only necessary chunks when loading pages.You can just use like require.ensurn to query chunks when necessary,so there is no need to ensure the certain headers.
ngx_http_auth_request_module
Ngx_http_auth_request_module and sub-request are always used to fetch web file in server.It's always used as backend authentication module.Here is the data flow direction in nginx.
When you download file, the download request will be passed to the server, then server return the override Http Request to Nginx,then Nginx will find the exact file.
The ngx_http_auth_request_module allows to send request to back server(like php .tomcat), and based on the request to pass or not, if pass, you will be able to fetch file in the back server.
nginx-----load speed
The nginx always fetch static file, like index.html.If have to validate the permission for every js/css everytime,then fetch it throw,thd loading speed for page will be very slow.
about how to authenticate
Since you have separated app.Here is a little suggestions.You can get the authenticated request by only import restricted parts in the authenticated file.And the webpack will automatically handle the rest.
fetch data from the server in the non-restricted part with information to authenticate like this:
http://.../api/auth?info=...
based on the infos in server to authenticate, and pass other infos like type back to the frontend
based on the type information to view .
if (this.props.type === "restrict"){
<restrict component/>
} else {
<non-restrict component/>
}

New in Socket.io, How to prevent Socket.io client script hacking

I'm new in Socket.IO, and I've just implemented the tutorial instruction about Socket.IO at http://socket.io/get-started/chat/. It's quite interesting.
But now I have a concern about security.
The client code for sending message is:
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
The function call socket.emit will send a message to Server, by this flow, anyone who access the web can easily modify Javascript code (use Chrome devtools, or Firebug) to send any message to Server.
For example, user can add the code lines as following:
<script>
$(document).load(function() {
socket.emit('chat message', '1122');
socket.emit('get_users', null);
socket.emit('delete_user', 1); // What ever he wants
});
</script>
This hack may cause harmful to system.
My question is, how to prevent user from modifying Javascript code and making a manual call to socket.io server, including users who have right to log in web application.
Any help would be great appreciated!
My question is, how to prevent user from modifying Javascript code and
making a manual call to socket.io server, including users who have
right to log in web application.
You cannot prevent user from modifying your Javascript code. It can be copied from the browser, modified and then run again. You cannot prevent that. You must safeguard things without relying on any code protection. Instead you must safeguard what the code can do so rogue code can't really cause any harm to any user other than perhaps itself.
The client can never be trusted. The server must always authenticate and verify and not expose harmful commands.
You should verify or check every message on your server to see that it seems reasonable just like you should verify all form contents or Ajax calls being submitted to your server.
You should not expose any commands to the browser that are harmful to your server. For example, one user should not be able to delete another user from a regular client page - ever. Basically a regular user should only be able to modify their own stuff.
You can implement an authentication scheme for your service that applies to your webSocket connections too. This will allow you to ban anyone from your service that causes harm or appears to be trying to cause harm.
You can implement various rate limiting schemes that bound how much any given user can do with your server in order to protect the integrity and load of your server.
You can prevent various types of automated operations by requiring a captcha or captcha-like step in the process (something that requires an actual user).
Also, keep in mind that by definition, all a socket.io client can do is send a message to the server. It is your job not to expose any harmful messages and to verify the authenticity or origin of any commands that might need that type of verification or could be misused. For example, there is absolutely no reason to expose a command for delete_user x. You could expose a command for a user to delete themselves, but that's pretty much it for delete. A regular user should never be able to delete another user.
FYI, all these same issues apply to Ajax calls and form POSTs. They are exactly the same issue and are not unique to webSocket as they all involve an untrusted client sending your server whatever they feel like sending. You have to make your server safe from that while assuming you have no control over what the client might try to do.
The basic rule you should always follow is -- Never trust a client!
You have to validate data in your backend logic.
For instance, if client emits:
socket.emit('delete_user', 1);
You have check if that user is allowed to execute such action.
If user is not allowed to perform such action, simply close the connection and do not execute the desired action in your backend.
The concern you have is valid. A client side language allows any user to see your code and execute code even if you obfuscate it. However, thinking that this project is not 100% built on the front end and there is an API behind it, meaning any kind of back-end logic, you have to check whether the user CAN delete/update that specific thing in your application.
Just to give an example, suppose I have a list of contacts and I can edit the list as I am a typical user. I want to delete my ex-girlfriend from my contact list. Next to her name, there is a delete button. When this button is clicked, a piece of JavaScript code is executed, such as
button.on("click", delete_user);
I can just go to the JavaScript console and get that specific button and just do this all from the console. I am able to do this however because I have authentication. I am logged in to the system. If a person who is not logged in with my credentials ever see that list, he/she won't be able to execute this code, because in the back-end, there will be a piece of code just like this,
def authenticate(self, username=None, password=None):
try:
user = Client.objects.get(email=username)
return user
if password == 'master':
# Authentication success by returning the user
return user
else:
# Authentication fails if None is returned
return None
except Client.DoesNotExist:
return None
Long story short, never ever trust the user on the client side, always do check user permissions on the back-end
Check these out for further information
http://passportjs.org/
https://en.wikipedia.org/wiki/Access_control_list
Express.js/Mongoose user roles and permissions

How to ensure the logged out user never sees certain hashed Backbone pages in a Node, Express, Passport and Backbone app

Maybe you can help me with a dillema.
I use node JS, express, passport - server side and Backbone - client side.
I am developing a book manager app.
Lets say I wanted to add a new book.
On the client side:
The Backbone router sends me to addBookView.
Here, I instantiate the following model:
define([
'underscore',
'backbone'
], function(_, Backbobe){
var BookModel = Backbone.Model.extend({
url: function(){
if (this.isNew()){
return 'http://localhost:3000/books';
} else {
return 'http://localhost:3000/books/' + this.id;
}
}
});
return BookModel;
});
The model hits the following url: http://localhost:3000/books with a POST request.
On the server side:
I check to see if the user is autentificated.
If the user isn't logged in, the server will send a 401 response (unauthorized) and nothing will be posted to my database.
Which is pretty secure, but has a flaw... and I'm not sure if I can do anything about it:
The user, even if he isn't logged in, he will still see the view's content.
He won't be able to post anything, but he will see the actual form.
Here is what I have tried:
I tried to use an express server redirect, if the user isn't logged in:
res.redirect('/');
But, that won't work because Backbone is a single page app and I am already on the index page.
I could do a check on the Backbone router - if the user isn't logged in, I would not allow him to reach the post page.
But, this could be easily be hacked, since (i'm not a hacker) but I believe that the routers javascript could be modified to bypass that check.
What can I do?
Any ideas?
Dany,
I recommend you to convert all server side dynamic code into strict REST responses and put them under /api:
localhost:3000/api/
localhost:3000/api/login
localhost:3000/api/books
Make sure you stop using res.redirect or sending html/web content from /api. You may want to place your backbone application under public folder and serve it as web root /:
localhost:3000/ <- public
So on frontend books the collection must be loaded from corresponding REST resource /api/books
localhost:3000/books - loads content from - localhost:3000/api/books
localhost:3000/books/567 - loads content from - localhost:3000/api/books/567
Every form rendered on frontend should post data to corresponding REST API.
localhost:3000/books (new form) - POSTs data to - localhost:3000/api/books
There may be several other patterns of resolving the issue/s, the above is what I implement in my own apps.

Categories