Overview
ADFS is Microsoft Active Directory Federated Services. It is a single sign-on solution, and this post explains how to tie in Apache 2.4 (CentOS 7) to ADFS. All of this works even with SELinux enforcing!
The test environment described by this document includes the following.
Root URL: https://sample.example.org (10.1.9.192)
Protected subdirectory: https://sample.example.org/auth1/
Warning! ADFS Configuration changes can take a few minutes to take effect.
Adding ADFS integration to Apache
This guide assumes you have a functional apache environment.
Configuring apache
Install mod_auth_mellon from the regular centos repository. Also include php.
yum -y install mod_auth_mellon php
Set up mellon with the sample hostname and url using the provided tool.
mkdir -p /etc/httpd/mellon cd /etc/httpd/mellon /usr/libexec/mod_auth_mellon/mellon_create_metadata.sh urn:samplesite:sample.example.org "https://sample.example.org/auth1/endpoint/"
This script outputs 3 files to the current directory.
urn_samplesite_sample.example.org.key urn_samplesite_sample.example.org.cert urn_samplesite_sample.example.org.xml
This certificate is a self-signed certificate, but other options can be used and should be considered for production environments. Be aware that the certificates are also dumped into the xml file that will be shared with the ADFS host, so be sure to share any new certificates there as well.
Collect the ADFS metadata and store it locally. Such metadata is usually available at a URL similar to the following.
https://adfs.example.org/federationmetadata/2007-06/FederationMetadata.xml
Here is a copy-pastable line for people like me.
wget https://adfs.example.org/federationmetadata/2007-06/FederationMetadata.xml -O /etc/httpd/mellon/FederationMetadata.xml
Build the apache Mellon config.
cat <<EOF >/etc/httpd/conf.d/auth_mellon.conf MellonCacheSize 100 MellonLockFile /var/run/mod_auth_mellon.lock MellonPostTTL 900 MellonPostSize 1073741824 MellonPostCount 100 MellonPostDirectory "/var/cache/mod_auth_mellon_postdata" EOF
My test environment uses a modular ssl directives include file:
cat <<EOFSSL >/etc/httpd/sites/all-ssl.cnf SSLEngine on SSLProtocol all -SSLv2 -SSLv3 SSLHonorCipherOrder on SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS" <Files ~ "\.(cgi|shtml|phtml|php3?)$"> SSLOptions +StdEnvVars </Files> <Directory "/var/www/cgi-bin"> SSLOptions +StdEnvVars </Directory> SSLCertificateFile /etc/pki/tls/certs/localhost.crt SSLCertificateKeyFile /etc/pki/tls/private/localhost.key SetEnvIf User-Agent ".*MSIE 4\.0b2.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0 LogLevel warn ErrorLog logs/ssl_error_log CustomLog logs/ssl_access_log combinedvhost <Directory "/var/www/html/notfound/"> AllowOverride None Order allow,deny Allow from all </Directory> # END OF FILE all-ssl.cnf EOFSSL
In the apache config, probably /etc/httpd/sites/sample.conf, modify the virtual host.
cat <<EOF >/etc/httpd/sites/sample.conf Listen 10.1.9.192:80 Listen 10.1.9.192:443 <VirtualHost 10.1.9.192:80> ServerName sample.example.org:80 ServerAlias sample # Redirect everything to the https site RewriteEngine On RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} </VirtualHost> <VirtualHost 10.1.9.192:443> ServerName sample.example.org:443 ServerAlias sample sample.example.org DocumentRoot /var/www/html/sample.example.org Include sites/all-ssl.cnf <Directory "/var/www/html/sample.example.org"> AllowOverride None Order allow,deny Allow from all Options Indexes FollowSymLinks </Directory> <Location /auth1/> # Mellon auth which goes to ADFS Include sites/adfs.cnf MellonCond "groups" "WebAppUsers_grp" [REG,SUB,NC] </Location> </VirtualHost> EOF
Make the post dump location, which is not necessary but might be useful in the future.
mkdir -p /var/cache/mod_auth_mellon_postdata chown apache:apache /var/cache/mod_auth_mellon_postdata chmod 0700 /var/cache/mod_auth_mellon_postdata
Building the include files
We already built the all-ssl.cnf include file, so we just need the adfs include file.
cat <<EOF >/etc/httpd/sites/adfs.cnf # File: /etc/httpd/sites/adfs.cnf MellonEnable "auth" Require valid-user AuthType "Mellon" MellonVariable "cookie" #MellonSamlResponseDump On MellonSPPrivateKeyFile /etc/httpd/mellon/urn_samplesite_sample.example.org.key MellonSPCertFile /etc/httpd/mellon/urn_samplesite_sample.example.org.cert MellonSPMetadataFile /etc/httpd/mellon/urn_samplesite_sample.example.org.xml MellonIdPMetadataFile /etc/httpd/mellon/FederationMetadata.xml MellonMergeEnvVars On ":" MellonEndpointPath /auth1/endpoint EOF
Here, the MellonMergeEnvVars On “:” means that any multiple-value attribute (like Groups) will be added to one colon-delimited string instead of being assigned to “Mellon_Groups_1” “Mellon_Groups_2” and so on. It’s how the MellonCond works in the virtual host configuration.
Building example sites
Build the index file for the protected directory.
cat <<EOF >/var/www/html/sample.example.org/auth1/index.html <html> <head><title>Authorized zone</title></head> <body> <h1>Welcome to the authorized zone.</h1> You should only be able to see this if you are authenticated and authorized. </body> </html> EOF
Make a php troubleshooting file.
thisfile=/var/www/html/sample.example.org/auth1/info.php cat <<EOF >${thisfile} <?php phpinfo(INFO_VARIABLES); ?> EOF chown apache:apache ${thisfile} chmod 644 ${thisfile}
This little php file will show the apache environment variables that are available for use in the apache directives. The important ones here will be the ones prepended with “MELLON_.”
Configuring ADFS to share data
On the ADFS server, add a new relying party trust.
Run the AD FS management tool.
Navigate in the tree structure to AD FS –> Trust relationships –> Relying party trusts.
Select on the action menu “Add relying party trust…”
The easiest way to do this is to use the xml file generated by that script earlier.
Do not configure multi-factor authentication.
Permit all users to access this relying party.
Edit the properties of the relying party trust –> Advanced tab.
Set value “Secure hash algorithm” to SHA-1.
Adding claim rules
Right-click this relying party trust and select “Edit Claim Rules.”
Add a rule of type “Transform incoming claim.”
Incoming claim type: Windows account name
Outgoing claim type: Name ID
Outgoing name ID format: Transient Identifier
Radio button: Pass through all claim values
The rule text looks like:
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"] => issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient");
Reference: Specific example of mellon configuration
Add custom rule “Get all groups user belongs to.”
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"] => add(store = "Active Directory", types = ("http://schemas.xmlsoap.org/claims/Group"), query = ";tokenGroups;{0}", param = c.Value);
The add command instead of issue passes the information on to the next rule.
Reference: Custom rules sharing
Add custom rule “Filter your groups only.”
c:[Type == "http://schemas.xmlsoap.org/claims/Group", Value =~ ".*WebAppUsers_grp.*|.*IT.*"] => issue(Type = "groups", Value = c.Value, Issuer = c.Issuer);
The type name of “groups” means that mellon will provide an apache environment variable of “MELLON_groups” which we are performing the condition statement on in the virtual host.
The regex in the first part is looking for any group name that has “IT” in it at all or “WebAppUsers_grp” which is probably pretty specific to just that one group.
What this does is limit the groups being sent so instead of those 538 AD groups possible that that one user is in, it will pass back only the 28 IT department-related ones and the WebAppUsers_grp.
After the apachectl configtest, give apache graceful a shot!
https://sample.example.org/auth1/info.php
The above link (modified for you of course) should redirect to the AD FS login page and then send authenticated users back!
The benefits here include using apache as a reverse proxy to tomcat applications (local or otherwise) and providing a layer of authentication.
References
- Official mellon page https://github.com/UNINETT/mod_auth_mellon
- Specific example of mellon configuration https://answers.splunk.com/answers/177936/accessing-splunk-enterprise-using-adfs-authenticat.html
- https://httpd.apache.org/docs/2.4/mod/mod_authz_core.html
- ADFS saml rules https://support.zendesk.com/hc/en-us/articles/203663896-Mapping-attributes-from-Active-Directory-with-ADFS-and-SAML-Professional-and-Enterprise-
- Regex is allowed in claims https://social.technet.microsoft.com/wiki/contents/articles/8008.ad-fs-2-0-selectively-send-group-membership-s-as-a-claim.aspx
- http://serverfault.com/questions/700126/sending-ad-attributes-as-ad-fs-claims-to-shibboleth-sp-attributes
- Custom rules sharing http://molikop.com/2014/04/adfs-claim-rules-filtering-groups/
- http://stackoverflow.com/questions/6861534/is-it-possible-to-output-any-or-all-available-variables-in-a-htaccess-file
Detailed, clear, sourced. Thanks for that, you are making the internet a better place.
I’ve followed your instructions to a tea… Have you had any issues with ADFS giving the following error:
MSIS7075: SAML authentication request for the WebSSO profile must not specify any SubjectConfirmations.
I have not, unfortunately. Off the top of my head, it sounds like there’s a property being passed from your SP (Apache, if you’re following my guide) named “SubjectConfirmations” which ADFS does not want. Check out https://social.msdn.microsoft.com/Forums/en-US/d6a05795-cfd1-42c5-8088-f76abbe23b2b/ad-fs-saml-authentication-request-wsis7075-error?forum=Geneva. On my favorite Stackoverflow, http://serverfault.com/questions/795994/saml-authentication-fails-with-error-msis7075 shows a response to basically the same question.
This post saved my time 🙂 really helps!!
Can you share how to get the return value(authenticated users’ information) from IdP?
Thank you
I remember using a Firefox plugin that let me see the SAML information used in the transaction. It was SAML tracer at https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/
Hello bgstack15
Thanks for your reply 🙂 that’s useful.
Now i can login from IdP portal(STS), then been redirected to our website and get the user info.
But another scenario seems got some problem,
Open our web page> been redirected to STS login page> after login success > bring user back to our web page.
But while “login success” > “bring user back to our website” will get 401 error.
The apache error log:
… Error processing authn response. Lasso error: [-432] Status code is not success…
So I checked the SAML tracer and found that my StatusCode is Responder.
According to the official document(https://msdn.microsoft.com/en-us/library/hh269642.aspx) maybe this issue caused by the IdP setting??
Or any suggestion?
Thank you again.
I have no idea how to help you with that problem. I’m sorry. If you could suppress the “StatusCode: Responder” from being sent, maybe that would help.
I have seen implementations where the published link for the application is the the IdP page and then the user is sent to a generic page with “Click here to access [application]” because the redirection directly to the application did not work. If you can’t solve this problem, maybe you can at least try my idea.
Or maybe you need to turn on the Mellon dump info (that goes into /var/cache/mod_auth_mellon_postdata) and troubleshoot from that?
Hello bgstack15
Thank you 🙂
Yes, i think that lead users to IdP page is another workaround and that works now.
But since IdP been managed by another department, if we can control by our end(SP) will be better.
Now we built a dummy IdP for testing and found that the issue should caused by >>>Set value “Secure hash algorithm” to SHA-1.>>now is SHA2
Do you think SHA-256 will be available?
According to https://bugzilla.redhat.com/show_bug.cgi?id=1295472 the lasso already fixed the bug about SHA2, so now it should work?!
hello….
1) could you provide more detail steps on generating the certificate and signed by official CA? In this mellon_create_metadata.sh script, it will generate self-signed certificate. I could not do this in production environment. kindly provide detail.
2) as to SHA256, I modify mellon_create_metadata.sh script and generate SHA256 self-signed certificate. However, it still fails at assertion signing party. It still looks for SHA1… What else I should do to ensure it is SHA256? my lasso version is 2.5.0 and mod_auth_mellon is 11.
Thanks
Hi,
Thank you for this valuable post that gives a very clear procedure to follow step by step.
I have followed it and it when well but when testing I got an endless loop between apache and ADFS server. Apache seems not to accept the connection after authentication. I have seen with Chrome developer tools that the SAML answer I get from ADFS seems to include the information I needed.
Have you ever experienced such a behavior or any idea where it can come form? Certificates, bad configuration of Mellon?
Kind regards,
Thibault
The fact that you get an answer from ADFS suggests to me that the certificates are fine in your case. If you are getting a saml response, with the attributes you need, but apache is still misbehaving, then it is likely that apache/mellon is not configured correctly. You should double-check the Mellon directives in apache.
This is very useful post, Here I have some question (sorry for my less understanding if questions are stypid ;P)
we have Root URL: https://sample.example.org and Protected subdirectory: https://sample.example.org/auth1/
but while generating metadata xml, we are specifying URL (2nd parameter) as “https://sample.example.org/auth1/endpoint/” why “/endpoint/” is there?
and if it is required do in need to create directory named as “/endpoint” under my “/auth1” directory.
In my case I am trying to protect “auth1/test/” directory.
Thank you in advance.
Have you ever had a problem with mellon parsing the FederationMetadata.xml file?
I’ve been getting “Error adding metadata “/etc/httpd/mellon/FederationMetadata.xml” to lasso server objects.” today, and I’ve removed some non-spec data from the XML but still haven’t had any luck (See for the bits I removed on a whim https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/ff849212(v=ws.10) ).
[…] Adding ADFS integration to Apache […]