node.jssslhttpsapache2swagger-node-express

Apache2 Node Express unable to verify the first certificate


What I am trying to do is to make an api endpoints using Node Express and Swagger. The server that I am going to deploy the project is Ubuntu.

After I set up the node project on the server, installing Apache2 and set HTTPS with SSL certificates and key, accessing to the site worked well.

However, whenever I try to send API request from local to the server, it returns an error with "unable to verify the first certificate" message.

The certificates and key files that I have are:

  1. CA_GLOBALSIGN_ROOT_CA.crt
  2. File_Wildcard.servername.com.crt
  3. ChainFile_ChainBundle.crt
  4. KeyFile_Wildcard.servername.com_crt.key
  5. complete_chain.crt (this is the one that I made through combining (1). (2), and (3) files).

.conf file:

<VirtualHost *:80>
    ServerName servername.com
    Redirect permanent / https://servername.com/
</VirtualHost>
<VirtualHost *:443>
    ServerName servername.com

    SSLEngine on
    SSLProxyEngine on
    SSLProxyVerify none
    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off
    SSLProxyCheckPeerExpire off
    SSLCertificateKeyFile /etc/apache2/ssl/KeyFile_Wildcard.servername.com_crt.key
    SSLProxyCACertificateFile /etc/apache2/ssl/CA_GLOBALSIGN_ROOT_CA.crt
    SSLCertificateFile /etc/apache2/ssl/complete_chain.crt

    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / https://servername.com:3005/
    ProxyPassReverse / https://servername.com:3005/
</VirtualHost>

app.js file in node project:

const express = require('express');
const orderRoutes = require('./routes/orderRoutes');
const swaggerUi = require('swagger-ui-express');
const swaggerJSDoc = require('swagger-jsdoc');
const swaggerDef = require('./utils/swaggerDef');
const https = require('https');
const fs = require('fs');

const app = express();

app.use(express.json());

const options = {
  swaggerDefinition: swaggerDef,
  apis: ['./routes/*.js', './controllers/*.js'],
};

const swaggerSpec = swaggerJSDoc(options);

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
app.use('/api', orderRoutes);

const PORT = process.env.PORT || 3005;

const privateKey = fs.readFileSync('/etc/apache2/ssl/KeyFile_Wildcard.servername_crt.key');
const certificate = fs.readFileSync('/etc/apache2/ssl/complete_chain.crt');

const credentials = {
        key: privateKey,
        cert: certificate
}

const httpsServer = https.createServer(credentials, app);

httpsServer.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

module.exports = app;

I did test openssl s_client -connect servername.com:443, but it also returns unable to verify the first certificate.

I also tried using nginx, but it resulted the same.

Could someone please help me solving out this problem?

Thanks in advance!


Solution

  • What is contained in the chain? To setup the server (without client authentication) you'd only need the chain & the key file.

    The first certificate expected by the client is the one of the server, followed by any intermediate certificates and then optionally followed by the root certificate. The client should already have the root certificate in their trust store after all.