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)

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