Introduction
This is the third post, in a series of posts about adding support for Authentication (AuthN) to HAPI FHIR with OAuth2 Proxy, Nginx and Keycloak:
- Add AuthN to HAPI FHIR with OAuth2 Proxy, Nginx and Keycloak - Part 1
- Add AuthN to HAPI FHIR with OAuth2 Proxy, Nginx and Keycloak - Part 2
- Add AuthN to HAPI FHIR with OAuth2 Proxy, Nginx and Keycloak - Part 3
Nginx
Nginx is a HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, and mail proxy server.
I followed the recommendations in the following guides:
- Nginx docs: NGINX SSL Termination
- Nginx docs: Authentication Based on Subrequest Result
- OAuth2 Proxy docs: Integration
- Australian Signals Directorate: Implementing Certificates, TLS, HTTPS and Opportunistic TLS
- Cloudflare docs: Cipher suites recommendations
We will route all traffic through Nginx and use the Nginx auth_request
directive to make subrequests to OAuth2 Proxy in order to authenticate requests to HAPI FHIR.
SSL Termination
To set up a HTTPS server, add the ssl
parameter to the listen
directive in the server block:
server {
server_name hapi-fhir.au.localhost;
listen 443 ssl default_server;
include /etc/nginx/conf/ssl.conf;
...
}
See: nginx-default.conf.template
And specify the locations of the server certificate and private key files:
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
ssl_stapling_verify on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'AEAD-AES128-GCM-SHA2561 AEAD-AES256-GCM-SHA3842 AEAD-CHACHA20-POLY1305-SHA2563 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-CHACHA20-POLY1305 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384';
access_log /var/log/nginx/access.log;
See: ssl.conf
The server certificate is a public entity. It is sent to every client that connects to Nginx. The private key is a secure entity and should be stored in a file with restricted access. However, Nginx must be able to read this file.
The auth_request
directive
To perform authentication, NGINX makes a HTTP subrequest to an external server where the subrequest is verified. If the subrequest returns a 2xx response code, access is allowed, if it returns 401 or 403, access is denied.
nginx-default.conf.template:
server {
...
location /private/ {
auth_request /oauth2/auth;
auth_request_set $auth_status $upstream_status;
}
location /oauth2/ {
proxy_pass http://oauth2-proxy:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Auth-Request-Redirect $request_uri;
}
location = /oauth2/auth {
internal;
# Proxy for AuthN server
proxy_pass http://oauth2-proxy:4180;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
...
}
See: nginx-default.conf.template
The Nginx auth_request
directive allows Nginx to authenticate requests via OAuth Proxy's /auth
endpoint.
Source Code
What's Next
In the next post, we'll take a look at how to configure OAuth2 Proxy.
References
System Hardening
- ASD: Implementing Certificates, TLS, HTTPS and Opportunistic TLS
- Cloudflare docs: Cipher suites recommendations
OAuth 2.0
- IETF: OAuth 2.0 for Browser-Based Applications
- Spring docs: Implementation Guidelines for Browser-Based Applications
- okta Developer blog: OAuth for Java Developers
- OAuth.com: OAuth 2.0 Playground
- okta Developer blog: Add Auth to Any App with OAuth2 Proxy
Keycloak
- Keycloak guides: Configuring Keycloak for production
- Keycloak guides: Configuring TLS
- Keycloak guides: Configuring trusted certificates
- Keycloak guides: Configuring the hostname
- Keycloak guides: Using a reverse proxy
- Keycloak guides: Running Keycloak in a container
Nginx
- Nginx docs: NGINX SSL Termination
- Nginx docs: Authentication Based on Subrequest Result
OAuth2 Proxy
- OAuth2 Proxy docs: Integration
- OAuth2 Proxy docs: TLS Configuration