How to decode an X.509 subject (from client certificates) in NodeJS

Question: How do I decode the X.509 subject data from a certificate string in NodeJS?

Background

When using Nginx as a reverse proxy I can get Nginx to verify the client certificate using the following setup:

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    ssl on;
    ssl_certificate        /path/to/bundle.crt;
    ssl_certificate_key    /path/to/server.key;
    ssl_client_certificate /path/to/client_certificates.crt;
    ssl_verify_client      optional_no_ca;
    ssl_verify_depth       2;

    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_session_cache shared:SSL:20m;
    ssl_session_timeout 60m;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DHE+AES128:!ADH:!AECDH:!MD5';

    server_name some_server;
    root /path/to/www;

    location /api/ {
        proxy_pass         http://my_api_server:1234/;
        proxy_http_version 1.1;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
        proxy_set_header   X-SSL-CERT $ssl_client_escaped_cert;
    }
}

Now this populates the header so that I can retrieve the certificate in the header:

let cert = req.headers['x-ssl-cert'];
cert = decodeURI(cert);
const interestingStuff = x509.getSubject(cert);

Now unfortunately the x509-package doesn't seem to allow cert to be a string or I'm making some kind of mistake. The error produced is: Error: Context creation failed: File doesn't exist.: 233123-123123-123123.

Hints

This issue hints that it needs to have proper newline characters but when running JSON.stringify it looks fine: "-----BEGIN CERTIFICATE-----\nASDWQESAD..\n..ASDASD\n-----END CERTIFICATE-----\n"

Other stuff

Note: this is trivial in plain NodeJS when not using a proxy and directly configuring the ca in the https as the getPeerCertificate() returns an object with a subject element.

This question is in part related to: expressjs setting tls connect https nginx server for request

1 answer

  • answered 2019-04-15 18:07 Max Gordon

    The culprit seems to be the decodeURI. The most obvious hint was that each line in the certificate should have the same max length, 64 characters. Using decodeURIComponent solved this issue.

    Probably also good to encapsulate the decodeURIComponent in a try-catch statement.