yum upgrades for production use, this is the repository for you.
Active subscription is required.
If you are migrating from Apache to NGINX and your organization uses Shibboleth for single sign-on, you have a problem. Apache has built-in Shibboleth support through mod_shib, but NGINX has no native way to talk to Shibboleth’s authentication framework. Without a dedicated NGINX Shibboleth module, your SAML-based SSO breaks the moment you switch web servers.
The nginx-http-shibboleth module solves this. It connects NGINX to Shibboleth’s FastCGI authorizer, restoring full SSO functionality. The module processes incoming requests through an authorization subrequest and either grants access (passing user attributes to your backend) or redirects unauthenticated users to the identity provider’s login page. Universities, research institutions, and government agencies across federated identity networks rely on this NGINX Shibboleth module to run Shibboleth on NGINX.
How the NGINX Shibboleth Module Works
The NGINX Shibboleth module operates at the access phase of request processing. When a client requests a protected resource, the module performs this sequence:
- Subrequest: NGINX sends an internal subrequest to the Shibboleth FastCGI authorizer
- Authorization check: The authorizer inspects the request cookies and headers to determine authentication status
- Decision routing:
- 200 OK from the authorizer means access is granted and user attributes are extracted
- 302 redirect sends the client to the identity provider login page (WAYF)
- 401 or 403 denies access, forwarding the authorizer’s headers to the client
This follows the FastCGI Authorizer specification. One caveat: NGINX cannot buffer subrequest response bodies. For Shibboleth this does not matter, because authentication relies entirely on HTTP headers and cookies.
Because the module works at the access phase, it integrates with other NGINX access modules via the satisfy directive. You can therefore combine Shibboleth with IP-based access control or HTTP basic authentication.
Why Not Use the Native auth_request Module?
You might think NGINX’s built-in auth_request module could handle Shibboleth. It cannot. The problem is that Shibboleth’s authentication flow relies on HTTP redirects — when a user is not authenticated, the authorizer returns a 302 to the identity provider. The native auth_request module treats any non-2xx/401/403 response as an error, so it breaks the redirect chain entirely.
The NGINX Shibboleth module fixes this by forwarding all authorizer status codes and headers to the client:
| Feature | auth_request |
nginx-http-shibboleth |
|---|---|---|
| Status handling | Only checks for 2xx, 401, 403 | Returns all authorizer status codes and headers |
| Redirect support | Does not pass redirect headers | Passes redirect headers (critical for IdP redirects) |
| Header copying | Not supported | shib_request_use_headers copies Variable-* headers |
| FastCGI spec compliance | Generic subrequest auth | Follows FastCGI Authorizer specification |
Installation
RHEL, CentOS, AlmaLinux, Rocky Linux
Install the module from the GetPageSpeed RPM repository:
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
sudo dnf install nginx-module-shibboleth
Load the module by adding the following to the top of /etc/nginx/nginx.conf:
load_module modules/ngx_http_shibboleth_module.so;
You can also include all installed modules automatically:
include /usr/share/nginx/modules/*.conf;
You will almost certainly need the Headers More module as well. It clears input headers to prevent spoofing:
sudo dnf install nginx-module-headers-more
Debian and Ubuntu
First, set up the GetPageSpeed APT repository, then install:
sudo apt-get update
sudo apt-get install nginx-module-shibboleth nginx-module-headers-more
On Debian/Ubuntu, the package handles module loading automatically. No
load_moduledirective is needed.
View more details on the APT module page.
Prerequisites
Beyond the NGINX module itself, you need:
- Shibboleth SP with FastCGI support — On Debian,
shibboleth-sp-utilstypically includes it. On RHEL-based systems, you may need to rebuild the SP with FastCGI support. - Running FastCGI applications — The
shibauthorizerandshibrespondermust be running before NGINX can use them. Usesystemdorsupervisordto manage them.
Configuration Reference
The NGINX Shibboleth module provides three directives. All are valid in http, server, and location contexts.
shib_request
Syntax: shib_request <uri> | off;
Default: off
Context: http, server, location
Enables the Shibboleth auth request module. The URI should point to an internal location block that proxies to the Shibboleth FastCGI authorizer socket. Use off to disable authentication for a location that inherits it from a parent context.
shib_request_set
Syntax: shib_request_set $variable $value;
Default: none
Context: http, server, location
Sets a variable after the authorization subrequest completes. The value can reference $upstream_http_variable_* variables that contain Shibboleth attributes. This is the recommended method for passing attributes because it is not vulnerable to header spoofing.
shib_request_use_headers
Syntax: shib_request_use_headers on | off;
Default: off
Context: http, server, location
Copies authorizer response headers starting with Variable- into the main request (stripping the prefix). For example, Variable-Remote-User: jsmith becomes Remote-User: jsmith. This is required for proxy_pass backends that read attributes from headers. However, it introduces spoofing risks and requires clearing input headers.
Complete Configuration Example
Here is a production-ready NGINX configuration for the Shibboleth module:
server {
listen 443 ssl;
server_name example.org;
ssl_certificate /etc/pki/tls/certs/example.org.crt;
ssl_certificate_key /etc/pki/tls/private/example.org.key;
# Shibboleth FastCGI authorizer (internal only)
location = /shibauthorizer {
internal;
include fastcgi_params;
fastcgi_pass unix:/run/shibboleth/shibauthorizer.sock;
}
# Shibboleth FastCGI responder (handles login/logout/metadata)
location /Shibboleth.sso {
include fastcgi_params;
fastcgi_pass unix:/run/shibboleth/shibresponder.sock;
}
# Static resources for Shibboleth error pages
location /shibboleth-sp {
alias /usr/share/shibboleth/;
}
# Protected application
location /secure {
shib_request /shibauthorizer;
shib_request_use_headers on;
# CRITICAL: Clear spoofable headers
more_clear_input_headers Auth-Type Remote-User;
more_clear_input_headers 'Shib-*';
# Custom error page for access denied
error_page 403 /forbidden.html;
proxy_pass http://127.0.0.1:8080;
}
# Public area (no authentication)
location / {
shib_request off;
proxy_pass http://127.0.0.1:8080;
}
}
Important Notes
- The
/shibauthorizerlocation must beinternalto prevent direct client access - The
/Shibboleth.ssoresponder handles login redirects, logout, and SAML metadata exchange - The
include fastcgi_paramsdirective provides essential variables (REQUEST_URI,SERVER_PORT) that Shibboleth needs
Passing Attributes to Backend Applications
The NGINX Shibboleth module supports two methods for delivering user attributes to your backend. Choose based on your application architecture.
Method 1: Environment Variables (Recommended)
Use shib_request_set to extract attributes into NGINX variables. Then pass them as backend parameters. This method is immune to header spoofing.
location /secure {
shib_request /shibauthorizer;
# Extract attributes from the authorizer response
shib_request_set $shib_remote_user $upstream_http_variable_remote_user;
shib_request_set $shib_auth_type $upstream_http_variable_auth_type;
shib_request_set $shib_email $upstream_http_variable_email;
shib_request_set $shib_session_id $upstream_http_variable_shib_session_id;
shib_request_set $shib_identity_provider $upstream_http_variable_shib_identity_provider;
# Pass as FastCGI parameters
fastcgi_param REMOTE_USER $shib_remote_user;
fastcgi_param AUTH_TYPE $shib_auth_type;
fastcgi_param EMAIL $shib_email;
fastcgi_param SHIB_SESSION_ID $shib_session_id;
fastcgi_param SHIB_IDENTITY_PROVIDER $shib_identity_provider;
fastcgi_pass unix:/run/php-fpm/www.sock;
}
The $upstream_http_variable_* variables map to Variable-* headers from the authorizer. For example, $upstream_http_variable_remote_user reads the Variable-Remote-User header.
This works with fastcgi_param, uwsgi_param, and scgi_param. In PHP, these appear in $_SERVER.
Method 2: Request Headers (Use with Caution)
When your backend only reads from request headers (common with proxy_pass), enable shib_request_use_headers:
location /secure {
shib_request /shibauthorizer;
shib_request_use_headers on;
# MANDATORY: Clear all attribute headers to prevent spoofing
more_clear_input_headers Auth-Type Remote-User;
more_clear_input_headers 'Shib-*';
more_clear_input_headers EPPN Affiliation Entitlement;
more_clear_input_headers Persistent-Id Targeted-Id;
more_clear_input_headers DisplayName Email OrganizationName;
proxy_pass http://127.0.0.1:8080;
}
The authorizer’s Variable-* response headers are copied into the main request, with the prefix stripped. Your backend receives them as standard HTTP headers.
Preventing Header Spoofing
When using shib_request_use_headers on, you must prevent clients from injecting fake Shibboleth headers. Without safeguards, an attacker could send a Remote-User: admin header and gain unauthorized access.
The NGINX Headers More module handles this. Clear every attribute header your application reads:
# Clear default Shibboleth SP headers
more_clear_input_headers
Auth-Type
Remote-User
'Shib-*';
# Clear application-specific attribute headers
more_clear_input_headers
EPPN
Affiliation
Unscoped-Affiliation
Entitlement
Targeted-Id
Persistent-Id
Transient-Name
Commonname
DisplayName
Email
OrganizationName;
The module source repository includes default files for this purpose:
shib_clear_headers— Clears standard Shibboleth headersshib_fastcgi_params— Maps standard attributes to FastCGI parameters
Security Checklist
- Clear headers for every attribute your application reads, including capitalization variants
- Audit your application code to find all headers it reads — some apps fall back from environment variables to headers
- NGINX drops headers with underscores by default. Be aware of this when debugging attribute passing
- Prefer Method 1 (environment variables) whenever your backend supports it. It eliminates the spoofing vector entirely
Configuring Shibboleth’s shibboleth2.xml
Adding shib_request to NGINX is not sufficient on its own. You must also configure the Shibboleth SP to recognize your protected paths. Use the XML-based RequestMapper:
<RequestMapper type="XML">
<RequestMap>
<Host name="example.org"
authType="shibboleth"
requireSession="true"
redirectToSSL="443">
<Path name="/secure" />
</Host>
</RequestMap>
</RequestMapper>
Key Points
- Both
authTypeandrequireSessionmust be present. Without them, the authorizer returns 200 unconditionally (allowing everyone). - Use
type="XML"for theRequestMapper. NGINX has no.htaccess, so skipping native checks improves performance. Pathnames are case sensitive- After changing this file, restart
shibd,shibauthorizer, andshibresponder
Running the FastCGI Applications
NGINX does not manage FastCGI applications. You need a process manager. Here is a supervisord example:
[fcgi-program:shibauthorizer]
command=/usr/lib64/shibboleth/shibauthorizer
socket=unix:///run/shibboleth/shibauthorizer.sock
socket_owner=shibd:nginx
socket_mode=0660
user=shibd
[fcgi-program:shibresponder]
command=/usr/lib64/shibboleth/shibresponder
socket=unix:///run/shibboleth/shibresponder.sock
socket_owner=shibd:nginx
socket_mode=0660
user=shibd
The nginx user must be part of the shibd group so it can access the FastCGI sockets. Adjust paths and permissions for your distribution.
Performance Considerations
The NGINX Shibboleth module sends a subrequest to the FastCGI authorizer for every request to a protected location. This has clear performance implications:
- Each request requires a round-trip to the authorizer
- Static assets (CSS, JS, images) also trigger authorization
- The authorizer does not cache results
Reducing Overhead
Protect only the login endpoint. Let your application manage sessions after the initial authentication:
# Only the login path triggers Shibboleth authentication
location = /app/shibboleth-login {
shib_request /shibauthorizer;
shib_request_use_headers on;
more_clear_input_headers Auth-Type Remote-User 'Shib-*';
proxy_pass http://127.0.0.1:8080;
}
# The rest of the app uses its own session management
location /app {
proxy_pass http://127.0.0.1:8080;
}
This triggers Shibboleth only once per user session. Your app creates its own session cookie after capturing the attributes.
Serve static assets outside protected locations:
location /static {
shib_request off;
alias /var/www/app/static;
}
Troubleshooting
Authorization Always Succeeds (No Login Prompt)
Users access protected locations without being redirected to the identity provider:
- Verify
shibboleth2.xmlhas the correct<Path>withauthTypeandrequireSession - Confirm
shibd,shibauthorizer, andshibresponderare running - Check that
include fastcgi_paramsis present in the/shibauthorizerlocation
502 Bad Gateway Errors
The FastCGI authorizer socket is not accessible:
- Verify the socket exists:
ls -la /run/shibboleth/shibauthorizer.sock - Check permissions: the NGINX worker must be able to connect
- Ensure the Shibboleth FastCGI applications are running
500 Server Error from Responder
The message “FastCGI Shibboleth responder should only be used for Shibboleth protocol requests” means:
fastcgi_paramsis missing or incomplete. CheckREQUEST_URIandSERVER_PORT.<Sessions handlerURL="...">inshibboleth2.xmldoes not match your NGINX config
Attributes Not Reaching Backend
Authentication works but your application does not receive attributes:
- With
shib_request_set: verify$upstream_http_variable_*names match your SP’s attribute map - With
shib_request_use_headers: confirm you have not accidentally cleared needed headers - Check
attribute-map.xmlto ensure attributes are released - Enable debug logging to trace header copying:
error_log /var/log/nginx/error.log debug;
Look for shib request authorizer copied header lines in the output.
The return Directive Bypasses Authentication
NGINX’s return runs during the rewrite phase, before the access phase where the NGINX Shibboleth module operates. A return in a protected location executes without any authentication:
# WARNING: return bypasses shib_request entirely!
location /secure {
shib_request /shibauthorizer;
return 200 "This is served WITHOUT authentication";
}
Use try_files, proxy_pass, fastcgi_pass, or static file serving instead.
Conclusion
The NGINX Shibboleth module provides the bridge between NGINX and Shibboleth’s SAML-based authentication. By implementing the FastCGI authorizer pattern, it enables organizations to migrate from Apache to NGINX without losing their SSO infrastructure.
For secure deployments, prefer environment variables over header-based attribute passing. Always clear Shibboleth headers when using shib_request_use_headers. Protect only endpoints that truly need authentication to keep performance overhead low.
The module source code is on GitHub. For pre-built packages, visit the GetPageSpeed RPM module page or the APT module page.
