10. React deployment on Nginx (5). Passing client certificate DN to react client

 0. Nginx installation

#------------------------------------------------------
# INSTALLATION
# @see Mohammad Faisal
#------------------------------------------------------

#1. Install nginx
sudo apt-get update
sudo apt-get install nginx

#2. verify installation
sudo nginx -v



#------------------------------------------------------
# STARTUP SETTINGS
#------------------------------------------------------
#start Nginx when server restarts
sudo systemctl enable nginx

#only for checking if nginx is running
systemctl status nginx

Now, change the local port (for instance to 8081) if you have another server (apache) in port 80

sudo nano /etc/nginx/sites-available/default (OLD VERSIONS of NGINX !!!)
In newer versions of nginx use this file instead
sudo nano /etc/nginx/conf.d/default.conf
and edit the port from 80 to 8081 and also change the root from /var/www/html  to another folder like /home/ximo/my-react-app , but to avoid router problems, try_files has been changed from $uri $uri/ =404 to  $uri $uri/ /index.html index.html =404    
server {
	#listen 80 default_server;
        listen 8081 default_server;
	#listen [::]:80 default_server;
        listen [::]:8081 default_server;
#root /var/www/html; root /home/ximo/my-react-app # Add index.php to the list if you are using PHP #index index.html index.htm index.nginx-debian.html; index index.html; server_name _; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. #try_files $uri $uri/ =404; try_files $uri $uri/ /index.html index.html =404; }
and now restart the Nginx service
sudo systemctl restart nginx.service
verify the system is running
sudo netstat -tlpn| grep nginx
tcp        0      0 0.0.0.0:8081  0.0.0.0:*   LISTEN      12749/nginx: master 
tcp6       0      0 :::8081       :::*        LISTEN      12749/nginx: master 

1. Deploying react program to Nginx

Once you have tested your app, after executing  npm run build , copy the contents of the build folder to the folder /home/ximo/my-react-app as shown in the file  /etc/nginx/sites-available/default as shown in the previous section

The folder my-react-app is as follows

/home/ximo
    └─my-react-app
                └─ index.html
                └─ static

and now restart Nginx service
sudo systemctl restart nginx.service

to verify that the app works. In the browser navigate to http://localhost:8081 and it should work!

2. Enabling HTTPS 

1. Nginx needs a certificate and a key (both in pem format) If you have other formats, you can see how to convert it in a previous post.

2. The SSL certificate chain or CA certificate chains are usefull for discovering which CA can provide accepted user certificates. Mozilla helps us with a collection of CA chains. (The Mozilla file is named cacert.pem)

The file /etc/nginx/sites-available/default (in old versions of nginx!!!)

or  /etc/nginx/conf.d/default.conf (in new versions of nginx) is

#==================================================================
# HTTPS SERVER
#==================================================================

server {
	# SSL configuration
	#
	# listen 443 ssl default_server;
        listen 9999 ssl default_server;
# listen [::]:443 ssl default_server; listen [::]:9999 ssl default_server; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5; ssl_certificate /home/ximo/my-react-app/keystores/mycrt.pem; ## ssl_certificate_key /home/ximo/my-react-app/keystores/mykey.pem; ## ssl_client_certificate /home/ximo/my-react-app/keystores/cacert.pem; ## CA Bundle ssl_verify_client on; #root /var/www/html; root /home/ximo/my-react-app; # Add index.php to the list if you are using PHP #index index.html index.htm index.nginx-debian.html; #index index.nginx-debian.html; index index.html; server_name _; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. #try_files $uri $uri/ =404; try_files $uri $uri/ /index.html index.html =404; } } #================================================================== # HTTP SERVER #================================================================== server { #listen 80 default_server; listen 8081 default_server; #listen [::]:80 default_server; listen [::]:8081 default_server; #root /var/www/html; root /home/ximo/my-react-app; # Add index.php to the list if you are using PHP #index index.html index.htm index.nginx-debian.html; #index index.nginx-debian.html; index index.html; server_name _; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. #try_files $uri $uri/ =404; try_files $uri $uri/ /index.html index.html =404; } }

Note the absolute routes to the certificates!

and now restart the Nginx service

sudo systemctl restart nginx.service

In the browser, point to https://localhost:9999/ and the application works


Happy coding!

3. Adding client certificate as a query parameter to the URL 

I have posted a question in ServerFault about how to add a parameter to the URL.

Using HTTPS in Nginx,  enable us to detect if the client has a recognized certificate and the information about it.

Here is a list of useful Nginx variables:

$ssl_client_verify
returns the result of client certificate verification: “SUCCESS”, “FAILED:reason”, and “NONE” if a certificate was not present;
$ssl_client_s_dn
returns the “subject DN” string of the client certificate


Here is the configuration file for Nginx

#==================================================================
# HTTPS SERVER
#==================================================================

server {
	# SSL configuration
	# listen 443 ssl default_server;
        listen 9999 ssl default_server;
	
	# listen [::]:443 ssl default_server;
	listen [::]:9999 ssl default_server;

	ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        #ssl_ciphers         AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
        
	ssl_certificate        /home/ximo/my-react-app/keystores/mycert.crt.pem;         ## 
        ssl_certificate_key    /home/ximo/my-react-app/keystores/mycert.key.pem;         ## 
	ssl_client_certificate /home/ximo/my-react-app/keystores/.npm.certs.pem;               ## CA Bundle
        ssl_verify_client on;

	#root /var/www/html;	
	root /home/ximo/my-react-app;

	# Add index.php to the list if you are using PHP
	#index index.html index.htm index.nginx-debian.html;
        #index index.nginx-debian.html;
        index index.html;

	server_name _;
        #error_log /home/ximo/log/nginx_log debug; #only for debug purposes

       	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		#try_files $uri $uri/ =404;
                try_files $uri $uri/  /index.html =404;
	}

        location = /login {
            if ($arg_verify = "") {
                #@see https://serverfault.com/q/1112066/986686
                #flags: redirect and permanent change externally the URL but produces loops
                #flags: last, break and no flag change only internally, and the browser is not affected
                #       so use redirect or permanent trying to avoid loops with an if statement
                rewrite ^ /login?DN=$ssl_client_s_dn&verify=$ssl_client_verify&server=$remote_addr redirect;
            }
            try_files /index.html =404;
        }
}


#==================================================================
# HTTP SERVER
#==================================================================
server {
	#listen 80 default_server;
	listen 8081 default_server;
	
	#listen [::]:80 default_server;
	listen [::]:8081 default_server;

	#root /var/www/html;	
	root /home/edu/my-react-app;

	# Add index.php to the list if you are using PHP
	#index index.html index.htm index.nginx-debian.html;
        index index.html;

	server_name _;

	location / {
	    # First attempt to serve request as a file, then
	    # as directory, then fall back to displaying a 404.
	    #try_files $uri $uri/ =404;
            try_files $uri $uri/  /index.html index.html =404;
	}
}


4. Reading query parameters from the URL 


And in the react component, some code like this should be used to get the query parameters

import { createSearchParams, useNavigate, useSearchParams } from "react-router-dom"  
import React, { ChangeEvent, FormEvent, useEffect, useState } from "react"

export const Login = () => {
  //==================================================================
  let [searchParams, setSearchParams] = useSearchParams();
  for (const entry of searchParams.entries()) {
    const [param, value] = entry;
    console.log(param, value);
  }
  //==================================================================

  return(
    <h1>{searchParams.get('DN')}</h1>     
  )



Comentarios

Entradas populares de este blog

14. Next.js Tutorial (1)

15. Next.js Tutorial (2). Fetching data. Async functions getStaticProps, getServerSideProps, getStaticPaths

16. Next.js Tutorial (3). Dynamic Routes. Async functions getStaticPaths and getStaticProps