Domino on Linux/Unix, Troubleshooting, Best Practices, Tips and more ...

alt

Daniel Nashed

NGINX Authentication Based on Subrequest Result

Daniel Nashed – 12 October 2024 21:07:46

NGINX comes in two different versions. The free open source version and the commerical NGINX Plus.


The free version basically supports:
  • Basic authentication
  • Client certificate authentication
  • Allow access by IP address

NGINX also has a very flexible programming model in C or LUA.


But there is an interesting additional option:

https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-subrequest-authentication/

You can authenticate against another HTTP server.
When the user is not authenticated NGINX uses a sub request to check for authentication.

If the requests re turns a HTTP 200 OK, the user authentication was successful.

The result can be cached by authorization token (also in combination with the IP).


In my case I am sending the request to a local UNIX Socket instead of a web server.
The socket request is processed by a C++ program.

Using this approach I can implement any type of authentication on NGINX.
In my case I am verifying a JWT via OpenSSL code.

But this opens the door for any type of authentication integration.

The following example shows how it works in general.


Example configuration
  • Basic authentication
  • IP based authentication
  • Sub request integration
  • Cache the authentication even in tmpfs
  • Use a UNIX socket for the sub request

...

http {


  proxy_cache_path /dev/shm/nginx keys_zone=auth_cache:1m;


 server {

      listen            443 ssl;

      listen       [::]:443 ssl;

      server_name  _;

      root         /usr/share/nginx/html;


      ssl_protocols TLSv1.2 TLSv1.3;

      ssl_prefer_server_ciphers on;


      # Prefer the SSL ciphers for ECDSA:

      ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256';


      # Use multiple curves.

      ssl_ecdh_curve secp521r1:secp384r1;


      ssl_certificate     /etc/nginx/conf.d/cert.pem;

      ssl_certificate_key /etc/nginx/conf.d/key.pem;


      add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;


      http2 on;


      location = /auth {

          internal;

          proxy_pass              
http://unix:/tmp/auth.sock;
          proxy_pass_request_body off;

          proxy_set_header        Content-Length "";

          proxy_set_header        X-Forwarded-Host $hostname;

          proxy_set_header        X-Forwarded-For  $remote_addr;

          proxy_set_header        X-Orig-URI       $request_uri;

          proxy_set_header        X-Orig-Protocol  $ssl_protocol;

          proxy_set_header        X-Orig-Cipher    $ssl_cipher;


          proxy_cache             auth_cache;

          proxy_cache_valid any   1m;

          # Use the authorization header and IP for cache lookup

          proxy_cache_key         "$http_authorization$remote_addr";

      }


      location / {

          satisfy any;

          allow 127.0.0.1;

          allow 1.2.3.4;

          deny all;


          auth_basic           "Software Download";

          auth_basic_user_file /etc/nginx/conf.d/htpasswd;


          auth_request     /auth;

          auth_request_set $auth_status $upstream_status;


          root   /usr/share/nginx/html;

          index  index.html;

      }

  }

...



Example request passed as a sub request


You can add all type of information to the sub request on top of the request itself.
IP address, hostname and TLS information can be helpful.

This opens the door for many different authentication options.


------

GET /auth HTTP/1.0

X-Forwarded-Host: volt.domino-lab.net

X-Forwarded-For: 91.14.169.18

X-Orig-URI: /software.txt

X-Orig-Protocol: TLSv1.3

X-Orig-Cipher: TLS_AES_256_GCM_SHA384

Host: localhost

Connection: close

user-agent: curl/7.81.0

accept: */*

authorization: Basic ZG9ja2VyOmV...




Links

    Archives


    • [HCL Domino]
    • [Domino on Linux]
    • [Nash!Com]
    • [Daniel Nashed]