Best practice to secure request payload between client / server during post request transmission node/express js - node.js

Narrowing down from a broad topic, i have a specific question (maybe a little bit 'tin-foil hat').
This question is regarding the best practices of securing data transmitted in a post request between the client and server. The background is a web app I'm developing to learn more about node and express js.
Although the example i'm using is for login credentials it really could be about any information being transmitted in a post request from a form submit to an express server.
example:
client submits form data through a button click event on the client. I'm using vue for the front end, but this is a generic question. On the client page i'm also using (inside an async function):
const resp = await axios.post("http://someurl.com/login", {client:email, pw:pw});
in chrome developer tools on the network tab i can see the request payload. In the example it looks like:
{client:"some email address", pw:"some password"}
Would it be better to transmit the payload already encrypted / encoded? Then have it decrypted / de-encoded on the server?
For transmitting sensitive information, is it better to use a signed cookie?
The plan, should i ever get through all of this is to use let'sEncrypt for HTTPS.
Is it reasonable to only rely on HTTPS for protecting this type of payload?
For reference, on the express server, password gets hashed and compared with a hashed version from a database. I've read about Helmet, and csurf and intend to use them in the final product as well. There's a lot of great information in this answer. Which is incredibly awesome and talks about the importance of HTTPS over HTTP.
Any additional references / thoughts / practical considerations are appreciated.

Using HTTPS will encrypt your payload between your client and the server.
Any javascript handling on the front end can be circumvented by users with enough knowledge so all frontend is mainly there for is to facilitate a better user experience. Password confirmation checking, correct fields filled out etc.
Your main source of security will be your eventual LetsEncrypt HTTPS certificate and your hashing and salting applied at the server end. As you correctly surmised HTTP send passwords in clear text which is bad. As a warning though even HTTPS can be defeated if somebody wants it bad enough with a number of techniques to high jack Certificate Authorities (I believe Root CAs should be offline anyway) or modify trusted certificates on a users PC.
Although it does depend on the amount of effort required by the hacker vs potential return hence the more you are trying to protect the greater the security required before it becomes not worth the effort for any potential hacker to attempt to circumvent the security of a particular site. (Reputation hacks aside of course)
Hope this helps.

Related

How to encrypt URL parameter - React.js - Js - Node.js

I am building an app that sends password/email in URL request:
For Example http://localhost:3000/getUserId/email?email=myEmail#gmail.com or the same with the password
I don't want this sensitive information to be visible on the network and would like to protect it from potential hacking or sniffing furthermore.
The front is using React.js and back Node.js - How can I encrypt that sensitive information?
I guess using btoa and atob is not enough since anyone could use them for decryption right?
You have at least two issues.
If you send confidential information like e-mail addresses and passwords over a network, you have to not only encrypt it but also make sure that potential network-based attackers don't have the ability to alter the traffic. This is done by employing HTTP over TLS or better known under HTTPS.
The other thing is that passwords should never be set in the URL. Most web servers provide logging capabilities and happily log the password in that case. But since passwords should be hashed repeatedly that would defeat that purpose.

Is using JWT Tokens actually a secure way to work around user sessions?

I am trying to build a registration/login system using the PERN stack (Postgres, Express, React & Node) for a client website.
I was doing some researching and came across HTTP Cookie and JWT token authorizations (many more but apparently those two are the dominant).
I noticed alot apps and tutorials that uses Node JS seems to use JWT alot, and store these in localstorage. But I'm doubtful about the security because I feel like a developer can basically go into localstorage and get the JWT token which o
Is there a better way to secure user authentications with this stack or is using localstorage the rule of thumb? If so, why is that?
Thank you for your time.
One limiting medium to the security of both session IDs and JWTs is network transmission. In this case, both are only as secure as the network itself. But most likely, your application would be using something like HTTPS or SSL, in which case any data being sent across the network would be reasonably secure.
Regarding your other edge case of someone trying to sniff at a JWT in local storage, there are a few options you may consider:
First, the nature of the JWT is that it is generally tamper-proof. A JWT contains inside of it a checksum, which is a unique hash based on the actual contents of the JWT. Let's says that some malicious user sniffed local storage, and then tried to change e.g. the claims section of the JWT. In doing so, this would also change the checksum (which that user would not be able to figure out, lacking the server key). Then, the next time the compromised JWT is sent to the server, the server would reject it, because the computed checksum would not match with the value contained in the JWT.
Second, in the event the above be deemed not secure enough, it is possible to pass around encrypted JWT. If you go with this option, both the server and client would encrypt/decrypt before sending a JWT, which adds an extra layer of protection.
Security of network transmission is just one case of whole solution in web applications.
Im currently in the research of the same topic and as you said a lot of tutorials, blogs, youtube and other sources gives an excellent examples of using JWT tokens for handling user data. Unfortunately hardly anyone go deepest in handling and processing user sessions from administration point of view - where the real problems starts.
Logging the user in and sends JTW token in response to the client is not a problem at all. The problem begin when you as administrator want to invalidate a user.
Refer to this sources:
http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
Logout/invalidate a JWT
The session cookie with session data stored in server-side is currently the best option for web application.

API authentication without SSL

I'm writing an API that will be hosted without SSL support and I need a way to authenticate the requests. Each client would have a different ID, but if requests were authorised with that, anyone with a packet sniffer could forge requests. Is it possible to make a secure system WITHOUT relying on SSL?
(Some thoughts I had included OAuth, could that be implemented?)
Many thanks
Have each client cryptographically sign its requests with a client-specific key. Verify the signature on the server.
Using cryptography pretty simple. The main challenge is setting up the clients' keys. It'll be hard to do that securely without using SSL. There's no information in the question about how you set up client IDs, so I don't know if it's secure enough to set up keys at that point as well.
It's also going to be a problem if you serve the client code without SSL.
But hey, it's just an API you're building. Maybe the code that interacts with it is served over HTTPS. Or maybe the code is stored locally on the client.
I feel like a lot of people are going to complain about this answer though.

Securing parts of an HTTP request?

How does one go about securing parts of an HTTP request, say their Session ID? I know you can use HTTPS, but then your servers must decrypt all of the request. Wouldn't it be ideal to only encrypt the required parts of a request?
Are there any frameworks or resources out that that allow you or inform you how to do this?
HTTPS is the correct tool to use. The computational load of decrypting the packets is very low. Google changed to HTTPS by default for the whole of GMail earlier this year, and they report that the CPU load on their servers for SSL encryption/decryption is around 1%.
If you only encrypt part of the stream then you still have the problem of man-in-the-middle and replay attacks. SSL is the only way to prevent these. It doesn't really matter if the session ID is encrypted. If a man-in-the-middle can capture it, he can reuse it in it's encrypted form, and the server wouldn't know the difference.
Here's a blog post about Google's experience since the GMail switch to 100% SSL.
HTTPS is all or nothing. If not all elements on a page are secured with HTTPS then users will get usually get a "broken lock" in the upper left corner. This is because an attacker could use this to inject an attack similar to xss and obtain the document.cookie value.
Further more if 1 request is sent with a session id then an attacker can obtain the value and authenticate as you.

Security advice: SSL and API access

My API (a desktop application) communicates with my web app using basic HTTP authentication over SSL (Basically I'm just using https instead of http in the requests). My API has implemented logic that makes sure that users don't send incorrect information, but the problem I have is that someone could bypass the API and use curl to potentially post incorrect data (obtaining credentials is trivial since signing up on my web app is free).
I have thought about the following options:
Duplicate the API's logic in the web app so that even if users try to cheat the system using curl or some other tool they are presented with the same conditions.
Implement a further authentication check to make sure only my API can communicate with my web app. (Perhaps SSL client certificates?).
Encrypt the data (Base 64?)
I know I'm being a little paranoid about users spoofing my web app with curl-like tools but I'd rather be safe than sorry. Duplicating the logic is really painful and I would rather not do that. I don't know much about SSL client certificates, can I use them in conjunction with basic HTTP authentication? Will they make my requests take longer to process? What other options do I have?
Thanks in advance.
SSL protects you from the man-in-the-middle attacks, but not from attacks originated on the client side of the SSL. A client certificate built into your client API would allow you to identify that data was crafted by the client side API, but will not help you figuring out if client side manually modified the data just before it got encrypted. Technically ssavy user on the client end can always find a way to modify data by debugging through your client side API. The best you can do is to put roadblocks to your client side API, to make it harder to decipher it. Validation on the server side is indeed the way to go.
Consider refactoring your validation code so that it can be used on both sides.
You must validate the data on the server side. You can throw nasty errors back across the connection if the server-side validation fails — that's OK, they're not supposed to be tripped — but if you don't, you are totally vulnerable. (Think about it this way: it's the server's logic that you totally control, therefore it is the server's logic that has to make the definitive decisions about the validity of communications.)
Using client certificates won't really protect you much additionally from users who have permission to use the API in the first place; if nothing else, they can take apart the code to extract the client certificate (and it has to be readable to your client code to be usable at all). Nor will adding extra encryption; it makes things much more difficult for you (more things to go wrong) without adding much safety over that already provided by that SSL connection. (The scenario where adding encryption helps is when the messages sent over HTTPS have to go via untrusted proxies.)
Base-64 is not encryption. It's just a way of encoding bytes as easier-to-handle characters.
I would agree in general with sinelaw's comment that such validations are usually better on the server side to avoid exactly the kind of issue you're running into (supporting multiple client types). That said, you may just not be in a position to move the logic, in which case you need to do something.
To me, your options are:
Client-side certificates, as you suggest -- you're basically authenticating that the client is who (or what, in your case) you expect it to be. I have worked with these before and mutual authentication configuration can be confusing. I would not worry about the performance, as I think the first step is getting the behavior your want (correctness first). Anyway, in general, while this option is feasible, it can be exasperating to set up, depending on your web container.
Custom HTTP header in your desktop app, checking for its existence/value on the server side, or just leveraging of the existing User-Agent header. Since you're encrypting the traffic, one should not be able to easily see the HTTP header you're sending, so you can set its name and value to whatever you want. Checking for that on the server side is akin to assuring you that the client sending the request is almost certainly using your desktop app.
I would personally go the custom header route. It may not be 100% perfect, but if you're interested in doing the simplest possible thing to mitigate the most risk, it strikes me as the best route. It's not a great option if you don't use HTTPS (because then anyone can see the header if they flip on a sniffer), but given that you do use HTTPS, it should work fine.
BTW, I think you may be confusing a few things -- HTTPS is going to give you encryption, but it doesn't necessarily involve (client) authentication. Those are two different things, although they are often bundled together. I'm assuming you're using HTTPS with authentication of the actual user (basic auth or whatever).

Resources