[TIP] Apache module to authenticate a NativeSPApacheConfig to the backend app and sign attributes
Tom Noonan
tom at joinroot.com
Thu May 3 12:20:28 EDT 2018
I'd like to highlight an Apache2 module which makes a
NativeSPApacheConfig authenticating proxy configuration which proxies
to a backend service that is not launched by Apache more robust.
https://github.com/Root-App/mod_proxy_jwt_auth is a module that allows
the Apache instance to authenticate to the backend app via a json web
token (JWT), and will pass attribute environment variables set by
mod_shib as claims in the JWT resolving header spoofing concerns. In
an environment that runs a NativeSPApacheConfig as a authenticating
proxy, with mod_proxy_jwt_auth configured in Apache to pass shib
attributes and sign the header, and where the backend server is
running independently of Apache this module resolves the following
pain points:
- The backend app can be configured to verify the header added by
mod_proxy_jwt_auth is properly signed using off-the-shelf JWT
libraries and not serve content if the header isn't valid. This
resolves concerns about the backend server being misconfigured and
accepting requests that do not go through the NativeSPApacheConfig,
which is a concern when running in cloud environments like AWS. In
this configuration the backend server still requires authentication
(from Apache) to serve content, but the SAML heavy lifting is left to
Shibboleth.
- mod_proxy_jwt_auth will add Shibboleth environment variables to the
token and sign them. When signature verification is on then the
backend server can be confident the header variables are not spoofed.
This allows ShibUseEnvironment to be used as recommended in an
environment where the backend server process cannot access Apache
environment variables.
Here is an example config that passes name-id and Shib-Session-ID
through via the Authorization header:
<Location /example>
ProxyJwtAuthEnabled On
ProxyJwtAuthTokenAlgorithm RS256
ProxyJwtAuthTokenAlgorithmKeyPath /etc/httpd/ssl/jwt_key.pem
ProxyJwtAuthClaimMap name-id name-id
ProxyJwtAuthClaimMap Shib-Session-ID shib-session-id
AuthType shibboleth
ShibRequestSetting requireSession 1
require shib-session
ShibUseEnvironment On
ShibUseHeaders Off
</Location>
Then the backend app can decode the bearer JWT token in the
Authorization header and use the name-id and session-id it returns.
In Ruby the decode is one line of code using the JWT gem.
More details on JWTs are at jwt.io. Hope this helps someone.
--Tom Noonan II
More information about the users
mailing list