GOAL
Typical usage is a web application who normally needs an Apache authentication BUT placed behind a reverse proxy who handles itself authentication/authorization
If you need to define REMOTE_USER system variable on a proxied virtual host (backend) :
1° You need first to use an authentication + authorization process on the front-end virtual host (the one which forwards the requests to the backend).
2° On this frond-end virtual host, after the authentication/authorization, process you need to define a dedicated header that will be transmitted and recognized by the backend
2° You need then to configure the backend virtual host to create the REMOTE_USER system variable from this dedicated header .
User –>
Front-End : Forward + add custom header –>
Backend : use custom header to create system variable REMOTE_USER
Note this system variable REMOTE_USER can never be modified. It works in this case because it was not defined before on the backend
FRONT END VIRTUAL HOST
<VirtualHost *:443>
ServerName frontend.onemrva.priv
<Location />
AuthName "Application Access"
AuthType XXXXX (Basic, Digest, Kerberos, ...)
...
Require valid-user
# ------------------------------
# Pass headers to backend
# X-APP-USER = username as you want to be passed to backend (created from APP_USER variable ; APP_USER should be defined before)
# X-REAL-USER = original username as authentified in frontend for audit/log
# ------------------------------
RequestHeader set X-APP-USER "%{APP_USER}e"
RequestHeader set X-REAL-USER "%{REMOTE_USER}s"
</Location>
# --------------------------------
# Reverse Proxy to webapp backend
# --------------------------------
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN Off
SSLProxyCheckPeerName Off
ProxyPreserveHost On
ProxyPass / https://127.0.0.1:8443/
ProxyPassReverse / https://127.0.0.1:8443/
The key instruction is
RequestHeader set X-APP-USER "%{APP_USER}e"
It defines X-APP-USER (which will become REMOTE_USER on backend) from APP_USER variable.
This APP_USER variable should of course be defined somewhere before in the authentication/authorization phase.
Note in this example, the backend server is defined on https://127.0.0.1:8443/ It’s necessary to make it listen on an alternate TCP port (8443 here) if both backend and frontend runs on the same machine
BACKEND VIRTUAL HOST
#Listen only on localhost to restrict access
Listen 127.0.0.1:8443
<VirtualHost 127.0.0.1:8443>
ServerName webapp.onemrva.priv
# Define custom log format including X-APP-USERS-USER and X-REAL-USER
LogFormat "%h %l %u %t \"%r\" %>s %b X-APP-USER:%{X-APP-USER}i X-REAL-USER:%{X-REAL-USER}i REMOTE_USER:%{REMOTE_USER}e" webapp_custom
# Logs
ErrorLog logs/webapp-8443-error.log
CustomLog logs/webapp-8443-access.log webapp_custom
# Enable SSL
SSLEngine On
SSLCertificateFile /etc/pki/tls/certs/webapp.onemrva.priv.crt
SSLCertificateKeyFile /etc/pki/tls/private/webapp.onemrva.priv.key
# -----------------------------------------------
# Set REMOTE_USER from frontend header X-APP-USER
# -----------------------------------------------
SetEnvIf X-APP-USER (.+) REMOTE_USER=$1
DocumentRoot "/var/www/html/webapp"
<Directory "/var/www/html/webapp">
Options None
AllowOverride All
Require ip 127.0.0.1
</Directory>
</VirtualHost>
the key instruction here is
SetEnvIf X-APP-USER (.+) REMOTE_USER=$1
If the header X-APP-USER exists, assigns its content to the system variable REMOTE_USER
Additional info on this config
- Localhost on port 8443 (127.0.0.1:8443) is defined for this Vhost on TCP 8443 : listening on another port is necessary when both frontend and backend runs on the same machine
- LogFormat : Custom log format to displays both “used application username” and “real username as received by the frontend”. In this example it’s called webapp_custom
- This webapp_custom format is used while defining log file location
- Require ip 127.0.0.1 in <Directory> definition is a second security check to be sure it can only be served through the frontend
