I'm trying to build an API to control the user authentication processes in Node.js, just to exercise myself, but I'm not very familiar with the resources available at a Node.js environment.
The question being: what can I use to identify an user? Only thing I can think of now are cookies, but that don't seem very safe, imho. I thought maybe there's some variable in the http request I could use.
I do not want you to list JS libraries that handle authentications for me. I wanna try to build one myself.
You can implement your own code as an exercise, but the mechanism the code uses to establish authentication should exactly match existing common practice in the industry. Specifically you should use a session cookie, which needs to have many very specific properties in order to be secure. Cookies are secure enough in combination with a host of other best practices (https, server hardening, security patches, etc) for most web traffic. For enhanced security this is often combined with additional password prompts before important actions (amazon, yahoo), 2-factor authentication (google, github, etc), fraud detection heuristics (facebook, banking), etc. A cookie is precisely a "variable in the http request" as you say.
Related
I don't know if this is the right platform to ask this kind of question,
but I have an app that is separated between frontend (Angular) and backend/API (Nodejs). Now the API exposes public endpoints to be used by the frontend. Now how do I protect the API from being used or exploited by other parties and only keep it to my Angular app? I thought of using an HTTP only cookie but it seems its visible when someone opens the developer's tools on the request's headers.
I am completely out of ideas, thanks in advance.
There is no way to make your site 100% secure but you can slow attackers down, or convince them on to a less secure site if you cover the owasp top 10 and have some transport protection.
Transport protection
HTTPS: either use a solution with https already configured, like heroku or now.sh or use letsencrypt.org
Authentication - There are loads of solutions and you would need to figure out how important the data is you are trying to secure. JWT is a good starting point as it is the easiest and relatively secure.
OWASP attacks.
The OWASP top 10 is here:
https://www.owasp.org/images/7/72/OWASP_Top_10-2017_%28en%29.pdf.pdf
You can cover the majority of the list by using a library such as JOI, https://www.npmjs.com/package/joi and setting up the schemas so you only allow input that is absolutely necessary. Use whitelists of valid parameters rather than allow any string.
The only other precaution I would take is to use the npm library helmet, https://www.npmjs.com/package/helmet. This covers most of the XSS points
Those are probably the main points you need to cover, that will deter most opportunistic crackers
You can secure your API with a token using OAuth2, I don't know in angular to much but the best practice is to secure the nodejs with JWT Token.
Helpful link Creating an API authenticated with OAuth 2 in Node.js
Beer Locker: Building a RESTful API With Node - OAuth2 Server
--
I'm using the MEAN stack and want to make sure certain routes have an authenticated user. I've been reading up on JSON web tokens. This seems reasonable.
Before I invest anymore time into it, I want to ask if anyone else uses this and if there are any major flaws they've noticed thus far. And are there any other popular alternatives excluding passport?
JSON web tokens have several flaws which, when dealt with properly, can make the approach quite useful for performing authorization:
A client still needs to transmit user credentials to a authentication server, which means using secure transmissions is paramount
If sensitive information is placed into the token, this information should be encrypted by the client and sent across a secure transmission
Depending on how your constructing the token and who your sharing it with, tokens should have a limited lifetime, preventing others from destructuring the token since it's generation and potentially sending falsified data to servers
There are definitely other approaches to cookie-based authentication other than passport, but I'm not aware of any that are as well integrated and popularized, though I'm sure you might find something more efficient. There are other examples of cookie-based schemes that exists, which you could implement, for instance the auto-login scheme from SO.
If you want to invest the time to learn how to implement JWT, it would definitely be worth the effort. If your trying to asses whether you need to use JWT, a good rule of thumb is asking yourself whether you will have multiple authentication servers, will you need to authorize clients accross several different domains and whether you need the clients to have stateless/ephemeral authorization tokens.
Getting into web development and would like to become good at making secure websites. Any general typs/answers to any of the below would be greatly appreciated.
So got some questions on the authentication side of things:
How should the password typed on the client be encoded and sent to the server - assuming https is already in use? i have heard of some suggesting that only the hash is sent for security for example. Should it be encrypted client side - how?
Similar but on server side. How should the passwords be saved. Actual, hash, etc? Should they be encrypted - how?
Also, is there a kind of architecture that can protect the passwords in such a way that if one password is compromised, not everyone else's is? For example, if all passwords are stored in one file then access to only this one file would compromise every user on the system.
if only hashes must be stored - how to handle collisions?
Once authenticated should you just rely on session IDs to maintain authenticated status throughout? I have read on tips to reduce session highjacking and was therefore wondering whether it is a good idea/the only idea in the first place for keeping users authenticated.
Is there a safe way to provide an autoLogIn feature so that the browser remembers the password - similar to social network/web-email clients?
-------------
Extra - preventing attacks
Are there any tools or even just some common practises out there that must be applied to the username/password entries provided to prevent injection or any other kind of attacks?
If I use a Java development environment (using PlayFrameWork btw) how likely is it in general that attackers could include harmful code snippets of any kind in any form entries?
PS
As mentioned I will probably be using the Java PlayFrameWork to encode the website - can you suggest anything I should take into account for this?
Any tips on design patterns that must be followed for security purposes would be helpful.
Many Thanks
PPS
You could suggest passing the job on to an expert but if possible I would like to have some experience coding it myself. I hope that this is a viable option?
Will probably like to set up an e-commerce system FYI.
How should the password typed on the client be encoded and sent to the server - assuming https is already in use? i have heard of some suggesting that only the hash is sent for security for example. Should it be encrypted client side - how?
It should not be sent to the server in a way that can be recovered. The problem with SSL/TLS and PKI is the {username, password} (or {username, hash(password)}) is presented to nearly any server that answers with a certificate. That server could be good or bad.
The problem here is channel setup is disjoint from user authentication, and web developers and server administrators then do dumb things like put a plain text password on the wire in a basic_auth scheme.
Its better to integrate SSL/TLS channel setup with authentication. That's called channel binding. Its provides mutual authentication and does not do dumb things like put a {username, password} on the wire so it can be easily recovered.
SSL/TLS offers nearly 80 cipher suites that don't do the dumb {username, password} on the wire. They are Preshared Key (PSK) and Secure Remote Password (SRP). Even if a bad guy answers (i.e., controls the server), the attacker cannot learn the password because its not put on the wire for recovery. Instead, he will have to break AES (for PSK) or solve the Discrete Log problem (for SRP).
All of this is covered in great detail in Peter Gutmann's Engineering Security book.
Similar but on server side. How should the passwords be saved. Actual, hash, etc? Should they be encrypted - how?
See the Secure Password Storage Cheat Sheet and Secure Password Storage paper John Steven wrote for OWASP. It takes you through the entire threat model, and explains why things are done in particular ways.
Once authenticated should you just rely on session IDs to maintain authenticated status throughout?
Yes, but authorization is different than authentication.
Authentication is a "coarse grained" entitlement. It asks the question, "can a user use this application?". Authorization is a "fine grained" entitlement. It answers the question, "can a user access this resource?".
Is there a safe way to provide an autoLogIn feature so that the browser remembers the password - similar to social network/web-email clients
It depends on what you consider safe and what's in the threat model. If your threat model does not include an attacker who has physical access to a user's computer or device, then its probably "safe" by most standards.
If the attacker has access to a computer or device, and the user does not protect it with a password or pin, then its probably not considered "safe".
Are there any tools or even just some common practises out there that must be applied to the username/password entries provided to prevent injection or any other kind of attacks?
Yes, user login suffers injections. So you can perform some filtering on the way in, but you must perform HTML encoding on the output.
Its not just username/password and logins. Nearly everything should have some input filtering; and it must have output encoding in case its malicious.
You should definitely spend so time on the OWASP web site. If you have a local chapter, you might even consider attending meetings. You will learn a lot, and meet a lot of awesome people.
If I use a Java development environment (using PlayFrameWork btw) how likely is it in general that attackers could include harmful code snippets of any kind in any form entries?
Java is a hacker's delight. Quality and security has really dropped since Oracle bought it from Sun. The more paranoid (security conscious?) folks recommend not signing any Java code because the sandbox is so broken. That keeps a legitimate application properly sandboxed. From http://threatpost.com/javas-losing-security-legacy:
...
“The sandbox is a huge problem for Oracle,” Jongerius told Threatpost.
“Everyone is breaking in. Their solution is to code-sign and get out
of the sandbox. But then, you have full permission to the machine. It
doesn’t make sense.”
Its too bad the bad guys didn't get the memo. They sign their code the malware and break out of the sandbox.
Any tips on design patterns that must be followed for security purposes would be helpful.
You also have web server configurations, like HTTPS Only and Secure cookies, HTTP Strict Transport Security (HSTS), and Content Security Policies (CSP), Suhosin (hardened PHP), SSL/TLS algorithms, and the like.
There's a lot to it, and you will need to find the appropriate hardening guide.
We are planning to go for a security testing certificate. For that reason we are using Paros tool to test our system.
The system is written in GWT on front end and database connectivity is happening through Hibernate.
When we use this tool to test our application following behaviour is happening which needs to be restricted.
The tool is able to see the data which is passed to server. This is fine but when we make any changes in the data through tool it gets updated in the system on database end. This is a big security issue.
Can someone guide me in this?
If you're still looking for a solution to this problem, you could use request signing. The reason I didn't mention it earlier was because the only time I had seen request signing, there were certificates involved, and it was mostly using the Web Services Security Standard. The other time I recommended implementation of request signing was for a mobile application - its relatively easier to do there also, since you can use certificates that are on the device to perform the signing, and the server can verify this signature (essentially, a public key encryption mechanism).
As you mention in the comments, there are multiple aspects to it - one is to prevent XSRF, which is essentially including a nonce to ensure that an attacker cannot replay requests, or craft requests that might harm an authenticated user. This nonce will have to come from the server, since anything that you create using Javascript, the attacker can create also. This nonce will make sure that your request is time specific, and that it cannot be replayed at a later point of time.
However, a nonce isn't going to stop attacks where a user is in a hostile network, and an attacker is performing a MitM attack on all traffic. The attacker can still modify a request, and since the server has never seen that nonce before, it will accept the request as valid. To prevent this, you need to countermeasures in place - one, all traffic should go via SSL, and two, all requests must be signed so as to prevent tampering. The signature part is particularly hard, especially if you have to ensure that an attacker cannot perform the same signing. The examples I have seen of it involve certificate level authentication for the webapp, and using these certificates to then perform the signing - which might be too stringent a requirement for the application that you seem to be developing. Other methodologies involve using something that the user has/knows - maybe a token, password, secret answer, etc. - that cannot be replicated by an attacker, and using that information to sign requests.
Here's an example on how you can do this via PHP. I don't know if this mechanism can be adapted to do it for your purposes, though. OAuth might be another possible method, but since I've never seen an application do it that way, I am not very sure.
Sorry I don't have a specific methodology or examples of code for you to look at, but most implementations I've seen are only from a design standpoint, versus an actual code standpoint.
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).