Passing x509 certificates into node express server, NOT over https - javascript

I have searched and searched but everything I seem to find on this topic is regarding setting up a node express server to use HTTPS, and this is NOT what I am trying to achieve.
I would like to know, regardless of using HTTPS or not, is it safe (and more importantly good practice) to pass in client x.509 certificates into a post request, and then parse and use the client certificate.
If I could provide an example that may help.
I have a simple medical application where users authenticate to a node express route using username and password, also, I already have HTTPS configured and working.
However, later in the stages of using the client application, I need the user to be able to pass in their x.509 certificate, and allow data to be verified with their public key.
Now, I understand that authentication is carried out at the initial connection for https, but this is different, so I was thinking I could pass the users certificate as a json object and create/use the certificate in the express route.
At first thought this should be fine as the certificate is public, and we have already established a secure endpoint, however, I am very surprised that I am not able to find any examples or tutorials on this, so perhaps for some reason I am not aware, this is not best practice?
Any advice or guidance would be great.
Thanks in advance.
Regards
Steve

If you do not do mTLS (via HTTPS) you will need to develop a protocol to authenticate the user who presents the certificate is in-fact the private key holder. This is not trivial to get right, not doing this means you will be exposed to trivial spoofing attacks.

Related

What is the relationship between authentication/authorization in my frontend and my api backend?

Frontend is Vue and my backend is an express rest api that pulls data from mysql. I want to secure both the frontend (login form) and backend api, but without limiting use of the api to just my frontend. I may want to use this api for other projects in the future.
What I'm strugging with is understanding how to have a user log in on the frontend but also give them access to the api without preventing future access to the api from other projects. I know I could set a JWT, but recently there seems to be a lot of "DON'T USE JWT!" articles out there, and I can understand why they might think this. Using cookies and sessions doesn't seem practical either without needing to create a session/cookie for each frontend and backend. Then I thought maybe using cookie/sessions for frontend, and having the frontend be authenticated with an API key to the backend API. This might allow other web applications to access the api while protecting it from unauthorized access.
Apologies for the lack of knowledge and seemingly rambling. I've been stuck on this aspect of my project for a while now. I know it's due to my poverty of knowledge on the subject. Any resources and points in the right direction will be greatly appreciated.
There is nothing wrong with JWTs, though it can depend on the implementation. The simplest way of doing it is just signing the JSON string with a private key. A little more complicated is base64 encoding it, encrypting it and signing only after that with a different key. And ofc. you need to send it through SSL. You need to add expiration time to it. Probably bind it to IP, browser, language, location, etc. too. If you want to revoke it, then you need to maintain a very small global revoked JWT database and remove it after it expired. You can add a JWT verification cache too, which spares you checking the signature for every request and which can be local too. If you want to avoid accessing it from Javascript code and probably leak it with XHR, then add it to a httpOnly cookie, though if you do so, then you need a CSRF token too. So I think all of the security issues are solveable with JWT too.
We need stateless communication between the REST client and the REST service, so if your frontend has a server side REST client, which uses for example JWT or any other method with Auhorization header, then it is perfectly fine from statelessness constraint perspective to do server side sessions with your frontend. As of the constraint itself, statelessness is needed for massive services with countless users global scale where handling server side sessions is an issue on its own, so better to move the stuff to the clients. These are typically social media services, search engines, global webshops, etc. If you have a limited user number, then you probably don't need this feature. Though using server side sessions between REST client and service would violate the statelessness constraint, which means you would not have a REST service. I don't think this is an issue. I mean it would be still a service, just not a REST service, it would work, would not scale as well as a REST service, but if this is what you need and it is simpler for you to implement it securely, then go on.
You can use API keys if you have some sort of revoke mechanism for those too. And keep in mind that API keys are server side stuff, so for mobile clients and in-browser application they are not good for identification, because they can be easily stolen by the users, so don't access your service directly from those with API keys just through a server. Another way is checking IP and using SSL to identify the clients, which is similar to using API keys, just more standard and the secret does not go through the communication channel. It really depends on your needs. If you have 3rd party clients, then you'll need OAuth too and let the users decide if they trust them.
Not sure if this helps.
By far the best thing you can do is adopt OAuth2. It has all the necessary components solve your problem and has ton of implementations.
The issue with JWT is that lots of people get it wrong. inf3rno does a good job accidentally pointing out many of the issues.

Connecting the frontend (HTML,CSS,JS) to the backend (Express)

So there's a few things I'm confused about with connecting a frontend to a backend part of a website, and I can't seem to find anything online about it.
Say you have a backend API, which if you had a endpoint which deletes a user, for if they want their account deleted, then what's stopping an attacker from just pinging the end point with a user ID and then it'll delete the user? I've heard that you can use like a password or something similar to stop fake attacks, but what's stopping somebody from just looking through the source code to find the code that is sent along with the request? Do you just use a user ID that would be hard to guess? But if so, why couldn't they just brute force user ID's?
Should the backend be run on the same domain as the frontend? Should you just have to use https://example.com:3000, or should you have to use the ip of the server and send data to https://000.000.000.00:3000?
Any help would be appreciated. I don't know that much about full stack development since I'm just now starting to learn, however what people say seems to be a really insecure way of doing it.
1 - You can safe your backend with a JWT signed by User/Password to ensure that only signed users are calling to your API BACKEND, in your server you can use a service of DDOS and a Firewall to avoid this kind of attack.
2 - a Backend/Frontend of a website can be anywhere in web separated or not, in a home computer or in a cloud service, you must ensure that your Frontend can reach your backend wherever it is. Ofcourse you can do it in a single webserver, and its better for many reasons, such as process of deploy, performance of the website and safety.
and you can always learn more in documentations.
https://laravel.com/docs/9.x/csrf
There are a csrf token stops unauthorized requests from passing .
a good example in Laravel Documentation
I hope it was useful !

How to avoid showing form data in http headers

I am submitting a form by using "POST" method. But, even I submit the form using "POST" method, I can see the submitted form data in http headers. Am using live http headers plugin to check the headers. I am trying to save secure info. If the browser has "live http headers" plugin, easily any one can trap the data. So, if I want to hide the submitted data in http headers also, what do I need to do?
If it is not possible to hide the submitted form data in http headers, which mechanism I could follow to encrypt the data at client side(so that even if data is visible in http headers, it would be in encrypted format. So, no one can understand) and decrypt and process the data at server side. I am totally blocked here.
Please help me out from this.
appreciate any help.
Thanks in advance.
There appears to be a bit of confusion regarding how an Http POST works. I'm assuming you are viewing the headers in either the client browser's debugger or on the server. In that case, the data being sent should be readable. The client side debugger actually displays the headers before they are encrypted and sent across the wire.
On the server, the post data should also be available in unencrypted format.
What is sent over the internet would be encrypted, provided that you are using https:// in your form action instead of http://
You can't really do that, I mean you could but anything on the front end can be easily reverse engineered. Your best bet for securing form data is to implement CSRF of which Jeff Atwood did a good post on here and the comments are quite good as well.
Aside from that; like one of the comments above says, you can use SSL to secure the data going to and from the server.
Comments weren't long enough for this
The steps towards getting secure, without knowing your technology stack would be to get an SSL certificate for the origin and destination of your post request, if you don't have control of the destination your journey ends here but head over to one of the hundreds of SSL certificate providers available, I usually use Start SSL because it's free and pretty good.
You'll need to give us some more info on your technology stack to go any further but assuming you're using PHP and Apache you'll need to do a few things on your server to get the certificate.
Firstly generate your Private Key using this command:
openssl genrsa -des3 -out www.yourdomainname.com.key 2048
It will ask you for a few details, fill them all out as best you can and write them down somewhere, specifically the password.
Once you have this, you need to generate a certificate signing request or a CSR for short, this is achieved by running the below command
openssl req -new -key www.yourdomainname.com.key -out www.yourdomainname.com.csr
The password you entered to create the private key, when it asks; enter it here.
You'll also be asked for a load of details, from my memory this is what it will ask and it's generic format
Country Name: GB
State or Province Name (in full): London
Locality Name (city): London
Organization Name: Your company name
Organizational Unit Name: Probably IT or development
Common Name: Enter your domain name here in FULL, without http://
When it asks for
Email Address
password challenge
optional company name
don't enter anything...
validate your CSR using
openssl req -noout -text -in www.mydomain.com.csr
You can now use this CSR to sign your request with Start SSL Once you have your crt from Start SSL open your server config (with apache its usually http-vhosts.conf in /etc/apache2/extra/ and create this block inside of it
<VirtualHost *:443>
DocumentRoot /var/www/www.yourdomainname.com
ServerName www.yourdomainname.com
SSLEngine on
SSLCertificateFile /path/to/your/www.yourdomainname.com.crt
SSLCertificateKeyFile /path/to/your/www.yourdomainname.com.key
SSLCertificateChainFile /path/to/StartSSL.crt
</VirtualHost>
Restart apache and you should be able to access your website using https
Hopefully I've got that all correct, I'll edit for any issues.
Well, there is no easy way but from other posts that I have found:
Take a look at this post. This does not hide the values in POST but using jquery serializes them. You can use your own conventions to make it look like a mess.
Take a look at this article. CLearly explains everything you should know about cross site request forgery.
Have a look at this link. They provide a toolkit to use encrypted forms, called Open Data Kit.
Are you using OpenSSL?
The simplest solution is to enable HTTPS support on your server, and serve the pages only via HTTPS, by turning off the standard HTTP connector.
You won't have to any special development, just switching to HTTPS will ensure that the data cannot be read in transit, and gives the assurance to the viewers of your pages that it's really your server that they are talking with, and not someone doing a man-in-the-middle attack.
The HTTPS technology transparently handles all the concerns that you are trying to handle manually. The browser will exchange with the server a temporary encryption key that is used to encrypt all data sent data back and forth.
The server contains a certificate signed by a certificate authority that is used to sign the data, to prove to browsers that it's really your server.
All of this is handled in a completely transparent and automated way, without any extra development. You just need to contact a certificate authority and get them to create you a certificate, see this tutorial.
You also need to enable HTTPS on the server, this is done via configuration and all servers support it.
A "header" is just another encapsulation. There is no difference between that and the abstract idea of "body". One is not inherently more or less safe for carrying data over wire, so your focus should not be on solving this issue. Also, post data technically is in the body.
If security is your objective here, then you will focus on preventing what someone could do if they had privilege in your client/server exchange. Then you would use SSL, http-only cookies (or well thought-out local storage) good session timeouts, and your usual smart coding practices. Generally we should assume most data is viewable in transit, and prioritize against making that privilege even worthwhile for an attacker
If you were really that truly concerned about MITM attacks against your form post data, I suppose you could throw together a little JS to encrypt and maybe even post over web-sockets, but that's akin to not really doing anything at all IMHO.

Using SSL from a CA for server + allowing ssl client authorization that is self-signed with Node.js

First time working with SSL client authentication. The way it works with node.js while mixing with a certificate issued by a third-party CA (in this case it is StartSSL) is confusing me.
On production servers I'm using nginx as load balancer to different node.js instances. Since this is how I had done it before, nginx is handling all the HTTPS work and then passing a plain http request to a node instance. Since it has been deciding to always enforce SSL (for all kind of requests, using HSTS and using simple redirects), I'm considering the possibility to moving into having nginx doing only the balancing and letting the nodejs instances take care of the rest.
So, what I ignore is how to handle this with Node.js?
I found this blog post http://www.gettingcirrius.com/2012/06/securing-nodejs-and-express-with-ssl.html and this other http://blog.nategood.com/nodejs-ssl-client-cert-auth-api-rest
What I don't understand is how to handle both SSL authentications simultaneously. I hope I'm making some sense.
The idea is to generate a certificate for each user which has a CN that I match to a user, then ask for a password that, after bcrypted, should match what is on the database. While, at the same time, using the verification level 3 certificate that works with the CA to improve our users' safety.

Securing my Node.js app's REST API?

I could do with some help on my REST API. I'm writing a Node.js app which is using Express, MongoDB and has Backbone.js on the client side. I've spent the last two days trying to work out all of this and not having much luck. I've already checked out:
Securing a REST API
Securing my REST API with OAuth while still allowing authentication via third party OAuth providers (using DotNetOpenAuth)
http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/
http://tesoriere.com/2011/10/10/node.js-getting-oauth-up-and-working-using-express.js-and-railway.js/
I want to keep my backend and frontend as separate as possible so I thought about using a carefully designed REST API would be good. My thinking is that if I ever get round to developing an iPhone app (or something else like that), it could use the API to access data.
BUT, I want this to be secure. A user has logged into my web app and I want to ensure my API is secure. I read about OAuth, OAuth 2.0, OpenID, Hmac, hashes etc... I want to avoid using external logging in (Facebook/Twitter/etc) I want the registering and logging in to be on my app/server.
...but I'm still confused here. Maybe it's late at night or my brain is just fried, but I could really do with some steps on what to do here. What are the steps for me to create a secure API?
Any help, any information, any examples, steps or anything would be great. Please help!
In order of increasing security / complexity:
Basic HTTP Auth
Many API libraries will let you build this in (Piston in Django for example) or you can let your webserver handle it. Both Nginx and Apache can use server directives to secure a site with a simple b64encoded password. It's not the most secure thing in the world but it is at least a username and password!
If you're using Nginx you can add a section to your host config like so:
auth_basic "Restricted";
auth_basic_user_file /path/to/htpasswd;
(Put it in your location / block)
Docs: http://wiki.nginx.org/HttpAuthBasicModule
You'll need to get the python script to generate that password and put the output into a file: http://trac.edgewall.org/browser/trunk/contrib/htpasswd.py?format=txt
The location of the file doesn't matter too much as long as Nginx has access to it.
HTTPS
Secure the connection from your server to the app, this is the most basic and will prevent man in the middle attacks.
You can do this with Nginx, the docs for it are very comprehensive: http://wiki.nginx.org/HttpSslModule
A self-signed certificate for this would be fine (and free!).
API Keys
These could be in any format you like but they give you the benefit of revoking access should you need to. Possibly not the perfect solution for you if you're developing both ends of the connection. They tend to be used when you have third parties using the API, eg Github.
OAuth
OAuth 2.0 is the one to go with here. While I don't know the underlying workings of the spec it's the defacto standard for most authentication now (Twitter, Facebook, Google, etc.) and there are a ton of libraries and docs to help you get those implemented. That being said, it's usually used to authenticate a user by asking a third party service for the authentication.
Given that you doing the development both ends it would probably be enough to put your API behind Basic HTTP Auth and serve it over HTTPS, especially if you don't want to waste time messing around with OAuth.
Here's a different way of thinking about it:
Let's suppose for a moment that you're not using an API. Your user logs into the app, providing some credentials, and you give a cookie or similar token of some sort to the user, which you use to identify that user has logged in. The user then requests a page containing restricted information (or creating/modifying/deleting it), so you check that this token to ensure that the user is allowed to view that information.
Now, it sounds to me that the only thing you're changing here is the way that information is delivered. Instead of delivering the information as rendered HTML, you're returning the information as JSON and rendering it on the client side. Your AJAX requests to the server will carry that same logged-in token as before, so I suggest just checking that token, and restricting the information down to 'just what the user is allowed to know' in the same way.
Your API is now as secure as your login is - if anyone was to know the token necessary for accessing the api, they would also be logged into the site and have access to all the information anyway. Best bit is, if you've already implemented login, you've not really had to do any more work.
The point of systems such as OAuth is to provide this 'logging in' method, usually from a third party application and as a developer. This would potentially be a good solution for an iPhone app or similar, but that's in the future. Nothing wrong with the API accepting more than one authentication method!
The answers so far do a great job of explaining, but don't give any actual steps. I came across this blog post that goes into great detail about how to create and manage tokens securely with Node + Passport.
http://aleksandrov.ws/2013/09/12/restful-api-with-nodejs-plus-mongodb/
Tips valid for securing any web application
If you want to secure your application, then you should definitely start by using HTTPS instead of HTTP, this ensures a creating secure channel between you & the users that will prevent sniffing the data sent back & forth to the users & will help keep the data exchanged confidential.
You can use JWTs (JSON Web Tokens) to secure RESTful APIs, this has many benefits when compared to the server-side sessions, the benefits are mainly:
1- More scalable, as your API servers will not have to maintain sessions for each user (which can be a big burden when you have many sessions)
2- JWTs are self contained & have the claims which define the user role for example & what he can access & issued at date & expiry date (after which JWT won't be valid)
3- Easier to handle across load-balancers & if you have multiple API servers as you won't have to share session data nor configure server to route the session to same server, whenever a request with a JWT hit any server it can be authenticated & authorized
4- Less pressure on your DB as well as you won't have to constantly store & retrieve session id & data for each request
5- The JWTs can't be tampered with if you use a strong key to sign the JWT, so you can trust the claims in the JWT that is sent with the request without having to check the user session & whether he is authorized or not, you can just check the JWT & then you are all set to know who & what this user can do.
Node.js specific libraries to implement JWTs:
Many libraries provide easy ways to create & validate JWTs, for example: in node.js one of the most popular is jsonwebtoken, also for validating the JWTs you can use the same library or use express-jwt or koa-jwt (if you are using express/koa)
Since REST APIs generally aims to keep the server stateless, so JWTs are more compatible with that concept as each request is sent with Authorization token that is self contained (JWT) without the server having to keep track of user session compared to sessions which make the server stateful so that it remembers the user & his role, however, sessions are also widely used & have their pros, which you can search for if you want.
One important thing to note is that you have to securely deliver the JWT to the client using HTTPS & save it in a secure place (for example in local storage).
You can learn more about JWTs from this link

Categories

Resources