Enabling client side SSL authentication with Nginx for Application

Atul Dewangan
2 min readJun 27, 2021
  1. Create a server Certificate Authority(CA) Key and Certificate, replace password paraphrase xxxx
SERVER_ID="app.server" 
openssl genrsa -aes256 -passout pass:xxxx -out ${SERVER_ID}.pass.key 4096
openssl rsa -passin pass:xxxx -in ${SERVER_ID}.pass.key -out ${SERVER_ID}.key rm ${SERVER_ID}.pass.key

2. Create a Certificate Authority(CA) Certificate, enter details and a Common Name asked

openssl req -new -x509 -days 365 -key app.server.key -out app.server.crt
#Country Name (2 letter code) [AU]:IN
#State or Province Name (full name) [Some-State]:Karnataka
#Locality Name (eg, city) []:
#Organization Name (eg, company) [Internet Widgits Pty Ltd]:app
#Organizational Unit Name (eg, section) []:
#Common Name (e.g. server FQDN or YOUR name) []:app-server

3. Create a Client Key , use the same terminal and change CLIENT_ID with appropriate name

CLIENT_ID="app.client"
CLIENT_SERIAL=01
openssl genrsa -aes256 -passout pass:xxxx -out ${CLIENT_ID}.pass.key 4096
openssl rsa -passin pass:xxxx -in ${CLIENT_ID}.pass.key -out ${CLIENT_ID}.key
rm ${CLIENT_ID}.pass.key

4. Create a Certificate Signing Request (CSR), enter details and Common Name asked

openssl req -new -key ${CLIENT_ID}.key -out ${CLIENT_ID}.csr

5. Signing the CSR.

sudo openssl x509 -req -days 365 -in ${CLIENT_ID}.csr -CA ${SERVER_ID}.crt -CAkey ${SERVER_ID}.key -set_serial ${CLIENT_SERIAL} -out ${CLIENT_ID}.crt
#Country Name (2 letter code) [AU]:IN
#State or Province Name (full name) [Some-State]:Karnataka
#Locality Name (eg, city) []:
#Organization Name (eg, company) [Internet Widgits Pty Ltd]:SomeCompany
#Organizational Unit Name (eg, section) []:
#Common Name (e.g. server FQDN or YOUR name) []:app-client

6. verify

openssl pkcs12 -export -out ${CLIENT_ID}.pfx -inkey ${CLIENT_ID}.key -in ${CLIENT_ID}.crt -certfile {SERVER_ID}.crt

7. Bundle client key into a PFX file

openssl pkcs12 -export -out ${CLIENT_ID}.pfx -inkey ${CLIENT_ID}.key -in ${CLIENT_ID}.crt -certfile {SERVER_ID}.crt

8. To load this in java keystore, use pkcs12 format

keytool -importkeystore -destkeystore ${CLIENT_ID}.jks -srckeystore ${CLIENT_ID}.pfx -srcstoretype pkcs12 -deststorepass xxxx

9. update nginx for application with by adding ssl_client_certificate with server certificate path created before and and set ssl_verify_client on

server {
listen 80;
server_name app.domain.in;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name app.domain.in;
server_tokens off;
ssl_certificate /home/rails/ssl_certs/production/domain.in/domain.in.crt;
ssl_certificate_key /home/rails/ssl_certs/production/domain.in/domain.in.key;
ssl_client_certificate /home/rails/ssl_app/app.server.crt;
ssl_verify_client on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
ssl_prefer_server_ciphers on;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://app.domain.in:4000/;
proxy_set_header X-Real-IP $remote_addr;
}
}

10. Try accessing any endpoint, it will be give following response.

References

--

--