Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js client certificate authentication on some paths only

I have a node.js based web app that requires secure (https) connections from client. What I want is that on some paths client certificate authentication is required and on other paths not.

So for example. If user goes to https://www.example.com/main the server doesn't require client certificate authentication (and thus the browser won't ask anything). But if the user navigates to https://www.example.com/secure, then the client certificate authentication would be required (and thus the browser will pop up a dialog for selecting which certificate to use).

How can I make this happen. I am able to force client certificate authentication if I pass requestCert:true and rejectUnauthorized:true to https.createServer options. The problem with this approach is that client certificate is required for every path.

like image 801
Jukka Avatar asked Jan 23 '13 08:01

Jukka


2 Answers

I landed here because I am working on the same issue and will share the approach I'm taking. For endpoints that require the user to have authenticated using a valid cert I use a custom path appended to endpoints requiring the cert and verify that the user has authenticated using a cert if they are accessing any endpoint that follows that path (express app assumed). i.e.:

app.use('/api/cert', function(req, res, next){
    //validate that any token passed in the request was generated for a valid
    //cert login, otherwise reject request

    //pseudo-code
    if(isValidCertToken(req.authentication.token)) {
        next(); //this will pass it on to the correct endpoint in the /api/cert/[whatever] chain
    } else {
        req.status(401).send({error: 'invalid login, cert required'});
    }
});

This will require you to allow the user the ability to authenticate using certs by setting the requestCert flag to true, but will also allow other authentication methods if the user does not desire to use the "cert required" endpoints as long as the rejectUnauthorized is set to false when setting up the https connecton.

like image 154
weagle08 Avatar answered Nov 12 '22 23:11

weagle08


I think that this problem can be solved by setting up a reverse proxy/API gateway using Node.js package http-proxy-middleware which is compatible with express (the web server package we are using).

As shown in an example on homepage of the Node.js package, it could be done this way: 1. Define the redirections for the UNAUTH and AUTH API as per convention used by http-proxy-middleware and use in next step.

  1. Start an express HTTPS webserver on required port (say 3000) with http-proxy-middleware configured to act as reverse-proxy/API gateway. No need to set requestCert and rejectUnauthorized in https.createServer options.

  2. Start an express HTTPS webserver on another port (say 3001) to serve UNAUTH API requests. No need to set requestCert and rejectUnauthorized in https.createServer options.

  3. Start an express HTTPS webserver on another port (say 3002) to serve AUTH API requests. Set requestCert:true and rejectUnauthorized:true as https.createServer options.

The UNAUTH requests will be routed back/forth from 3000 to 3001 and AUTH requests will be routed back/forth from 3000 to 3002.

like image 27
shashi Avatar answered Nov 12 '22 23:11

shashi