Fediz authentication in Tomcat
This document describes configuring Fediz in Tomcat 8.5/9.0. By default Semarchy xDM has Tomcat's FormAuthenticator enabled. This document walks through the details of using an alternative authentication mechanism: the Semarchy FederationAuthenticator which is based on Fediz. This allows you to use SAML or WS-Federation external identity providers (IDP) like Active Directory Federation Services (ADFS) and Okta where xDM tomcat server will be the service provider (SP). You can find more details on Fediz here, http://cxf.apache.org/fediz-tomcat.html.
WS-Federation and SAML are time sensitive protocols, and multiple time-based assertions are performed to check validity of tokens. It is very important to synchronize IDP and SP through NTP (Network Time Protocol) to avoid time drift related issues that can be hard to troubleshoot
Step-by-step guide
- Most IDP requires https, so you may have to configure Tomcat to use https (SSL/TLS).
Ensure that Semarchy's Tomcat tools are available (9.0.3 or more). This is to permit mapping of external groups (such as Active Directory groups or OKTA groups) to Semarchy roles (referred to as "role mapping"). Semarchy's Tomcat tools file ships with Semarchy xDM (com.semarchy.tool.jee.tomcat-9.0.x.jar).
Check Tomcat tool availability# Is com.semarchy.tool.jee.tomcat-* present? ls -l /usr/share/tomcat9/lib/
If the jar file is not present, then get it from the standard Semarchy Installation files.
Get Tomcat tools from standard Semarchy installation# Get Semarchy Install # Browser version of these steps: # 1. Download from "Server Installation" from here: https://www.semarchy.com/all-downloads/ # 2. Unzip the xDM Server Installation zip file # Command line version. (correct for 5.2.3): curl https://www.semarchy.com/downloads/products/5.2/semarchy-xdm-install-5.2.3.ga-20200807-0643.zip -O # Extract Semarchy Tomcat Tools from the .zip file unzip -j semarchy-xdm-install-5.2.3.ga-20200807-0643.zip mdm-server/additional-libraries/com.semarchy.tool.jee.tomcat-8.5.10-ga-20200807-0643.jar # Copy the jar into place sudo cp com.semarchy.tool.jee.tomcat-8.5.10-ga-20200807-0643.jar /usr/share/tomcat8/lib/
Download latest Fediz 1.6 connector for tomcat (with dependencies) here :
https://repo1.maven.org/maven2/org/apache/cxf/fediz/fediz-tomcat/1.6.1/fediz-tomcat-1.6.1-zip-with-dependencies.zipExample of getting the Fediz connectorcurl https://repo1.maven.org/maven2/org/apache/cxf/fediz/fediz-tomcat/1.6.1/fediz-tomcat-1.6.1-zip-with-dependencies.zip -O unzip fediz-tomcat-1.6.1-zip-with-dependencies.zip
Create sub-directory called Fediz to hold the fediz jar files in ${catalina.home}/lib
Example of creating Fediz directorysudo mkdir /usr/share/tomcat9/lib/fediz
Update catalina.properties in ${catalina.home}/conf to add the previously created directory to the common loader:
Updating catalina.properties# original common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar # modified common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,"${catalina.home}/lib/fediz/*.jar"
Deploy the libraries to the directory created in step 4.
Deploying librariessudo cp /tmp/*.jar /usr/share/tomcat9/lib/fediz/
Configure Fediz Valve in semarchy.xml
Remove (comment out) the existing FormAuthenticator and replace it with FederationAuthenticator.Configure Fediz valve in semarchy.xml with Role Mapping<!-- This is the default authenticator valve <Valve className="org.apache.catalina.authenticator.FormAuthenticator" landingPage="/" /> --> <!-- This Semarchy class is based on the Fediz class. It allows us to do role mapping and to do fallback for REST API authentication. --> <!-- https://www.semarchy.com/doc/semarchy-xdm/semng.html#using-the-tomcat-role-mapper --> <Valve className="com.semarchy.tool.jee.tomcat.FederationAuthenticator" rolesMappingPathName="/some/custom/path/my-roles-mapping.properties" configFile="conf/fediz_config.xml" keepMappedRoles="false" keepUnmappedRoles="false" /> <!-- Example: store credentials to be used for REST calls in tomcat-users.xml. This works because we do preemptive basic authentication. (Won't work for form login.) --> <!-- <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> -->
Configure Fediz valve in semarchy.xml without Role Mapping<!-- This is the default authenticator valve <Valve className="org.apache.catalina.authenticator.FormAuthenticator" landingPage="/" /> --> <Valve className="org.apache.cxf.fediz.tomcat.FederationAuthenticator" configFile="conf/fediz_config.xml" /> <!-- This Semarchy class is based on the Fediz class. It allows us to do role mapping and to do fallback for REST API authentication. --> <!-- https://www.semarchy.com/doc/semarchy-xdm/semng.html#using-the-tomcat-role-mapper --> <!-- <Valve className="com.semarchy.tool.jee.tomcat.FederationAuthenticator" configFile="conf/fediz_config.xml" /> <!-- Example: store credentials to be used for REST calls in tomcat-users.xml. This works because we do preemptive basic authentication. (Won't work for form login.) <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> -->
You need to provide the relevant cert to Tomcat so that your authentication provider (for example OKTA) will trust Tomcat.
Create a keystore (or use your existing keystore) and import your Identity Provider certificate for your Semarchy xDM application (Note that if your Identity Provider certificate is a PEM file you can skip keystore import and point configuration directly to it).
For example, in OKTA when using SAML download the X.509 Certificate for your Semarchy xDM instance as "okta.cert" (you'll have different certs for each application: dev, prod, etc.)# Sample import into a keystore keytool -import -trustcacerts -alias customer_saml_cert -file okta.cert -keystore keystore.jks
- Configure your Identity Provider.
For example, configure Okta as described here: https://developer.okta.com/standards/SAML/setting_up_a_saml_application_in_okta.
Specifically it's best to set the 'Audience URI (SP Entity ID)' to the server URL including context. For example, http://example.com/semarchy/ or https://example.com/semarchy/. This is what Semarchy will expect, by default, in the response token from Okta. This should match the 'audienceItem' section of the fediz_config.xml file as described in step 10.
If the 'Audience URI (SP Entity ID)' setting in Okta needs to be something other than the server URL, you must configure the 'audienceItem' AND add a realm in the protocol section of fediz_config.xml as described in step 10. This is due to the fact that Fediz can also be used as an IDP itself or used for relaying authentication and not just a SP. Configure Fediz by creating fediz_config.xml here: ${catalina.home}/conf/fediz_config.xml
References:
http://cxf.apache.org/fediz-configuration.html
https://github.com/apache/cxf-fediz/blob/master/plugins/core/src/main/resources/schemas/FedizConfig.xsd
Additional samples in "Sample Configurations" belowCreate fediz_config.xmlsudo vim /etc/tomcat9/fediz_config.xml
Configure fediz_config.xml<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <FedizConfig> <contextConfig name="/semarchy"> <audienceUris> <audienceItem>https://mydomain:8443/semarchy/</audienceItem> <!-- This value must match the Okta 'Audience URI (SP Entity ID)' setting. If the 'Audience URI (SP Entity ID)' setting is not the server URL including context, you must also set the optional realm below in the protocol section. See step 9.--> </audienceUris> <certificateStores> <trustManager> <keyStore file="conf/keystore.jks" password="keystore_password" type="JKS" /> </trustManager> </certificateStores> <!-- maximumClockSkew sets the tolerance time between IDP and SP. It is still highly recommended to synchronize servers through NTP --> <!-- <maximumClockSkew>10</maximumClockSkew> --> <trustedIssuers> <issuer certificateValidation="PeerTrust" /> </trustedIssuers> <!-- Only one protocol may be defined. Here are two examples. --> <!-- WS-Federation protocol: --> <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="federationProtocolType" version="1.2"> <issuer><!-- Your Identity Provider Issuer. For example: https://login.customer.com/adfs/ls/ --></issuer> <roleURI><!-- Your URI to get roles. For example for ADFS: http://schemas.microsoft.com/ws/2008/06/identity/claims/role --></roleURI> </protocol> <!-- SAML protocol: --> <!-- Comments on frequently used values: doNotEnforceKnownIssuer is used when: - Fediz is expecting issuer as specified above (SSO IDP URL), Okta is sending something else disableDeflateEncoding is used when: - Fediz is expecting SAML response to be gziped, Okta is not compressing response --> <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="samlProtocolType" version="2.0"> <doNotEnforceKnownIssuer>true</doNotEnforceKnownIssuer> <disableDeflateEncoding>true</disableDeflateEncoding> <issuer> <!-- Your Identity Provider Single Sign on URL. This should link to a login screen. Examples: https://mydomain.okta.com/app/mydomaine_semarchydev_1/hsosjgkwlsjCUREU7T2p6/sso/saml https://YOUR.PINGFEDERATE.SERVER/idp/SSO.saml2 https://www.mysite.com/adfs/ls --> </issuer> <!-- Your roleURI configuration could be different, but "groups" is often the roleURI. --> <roleURI>groups</roleURI> <!-- The realm tag is not generally required. It is needed, for example, if the Okta 'Audience URI (SP Entity ID)' setting is not set to the server URL including context. See step 9 for more details. --> <!-- <realm type="String">http://10.10.10.10/semarchy/welcome</realm> --> </protocol> <!-- Uncomment logoutURL below to enable SSO logout --> <!--<logoutURL>/sem_check2</logoutURL>--> <!-- Or uncomment below to enable local logout with redirect to you have been logged out page --> <!--<logoutRedirectToConstraint>.*</logoutRedirectToConstraint>--> </contextConfig> </FedizConfig>
Logout
By default in xDM logout is not performing a SSO logout. SSO logout is configured by adding following to configuration
<logoutURL>/sem_check2</logoutURL>
If for some reasons you need to perform a local logout (logout from xDM only, but keep SSO sign-in), standard Fediz is not working well with xDM logout action, so you need to use semarchy version (com.semarchy.tool.jee.tomcat.FederationAuthenticator)
The local logout is redirecting by default to a big black screen image. In order to redirect to our page "you have been logged out" you need to add following configuration:
<logoutRedirectToConstraint>.*</logoutRedirectToConstraint>
Note that currently the url redirected after logout is not configurable, if a customer requires this feature, fill a Jira story
Enable Logging for Fediz
Activate this logger
Activate this loggersudo vim /etc/tomcat8/logging.properties # These are included but commented out by default. # Enable them now, so we get the detailed logging we need. # From Semarchy # enable realm logging org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/semarchy].level = ALL org.apache.catalina.realm.level = ALL org.apache.catalina.realm.useParentHandlers = true org.apache.catalina.authenticator.level = ALL org.apache.catalina.authenticator.useParentHandlers = true # Turn on Fediz logging - add these lines at the end com.semarchy.tool.jee.tomcat.level = FINE org.apache.cxf.fediz.level = ALL org.apache.wss4j.level = ALL # Remember that Log4j uses ERROR, WARN, INFO, DEBUG, TRACE, etc # but JULI uses these: SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, or ALL # By default Tomcat 8 uses JULI logging.
- SAML-tracer. In addition to logging in Tomcat, it's also useful to see the SAML token in the browser to understand what's going on. The Firefox add-on "SAML-tracer" is very helpful:
https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/ or Chrome version https://chrome.google.com/webstore/detail/saml-tracer/mpdajninpobndbfcldcmbpnnbhibjmch?hl=en
You cannot browse the contents of the token if it is encrypted. Obviously. So do not encrypt. (Or enable encryption after everything is working without encryption.)
There is more general information about configuring Fediz logging in this article if your Tomcat configuration is different.
AuthnRequest Request Builder configuration
Some IDPs may not support default SAML Sign-in Request generated by fediz. We provide a way to customize some parts of this Request:
- com.semarchy.tool.jee.tomcat.fediz.PingFederateSamlRequestBuilder: pre-configured builder for PingFederate server
- com.semarchy.tool.jee.tomcat.fediz.ADFSSamlRequestBuilder: pre-configured builder for ADFS server
- com.semarchy.tool.jee.tomcat.fediz.ConfigurableSAMLPRequestBuilder: configurable builder
The custom builder can be configured in protocol part of fediz_config.xml
<protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="samlProtocolType" version="2.0"> <authnRequestBuilder>com.semarchy.tool.jee.tomcat.fediz.ConfigurableSAMLPRequestBuilder</authnRequestBuilder> .... </protocol>
com.semarchy.tool.jee.tomcat.fediz.ConfigurableSAMLPRequestBuilder requires an additional configuration file in conf of tomcat named fediz-samlp-request.properties
Sample file below shows supported properties with default values. For example to customize nameID, you need to uncomment nameid.format and put the value you expect.
#nameid.format = urn:oasis:names:tc:SAML:2.0:nameid-format:persistent #authn.ctx.classref = urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport #nameid.qualifier = true #authn.force = false #passive = false #protocol.binding = urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST
Sign SAML Request token
You need a certificate to sign tokens. If you do not have a certificate you can generate one (steps are similar than for generating an https certificate).
The following configuration is required to sign Request tokens:
<FedizConfig> <contextConfig name="/semarchy"> .... <signingKey keyAlias="mytomrpkey" keyPassword="tompass"> <keyStore file="/path/to/mykeystore.jks" password="tompass" type="JKS" /> </signingKey> ..... <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="samlProtocolType" version="2.0"> <signRequest>true</signRequest> </protocol> ......... </contextConfig> </FedizConfig>
Default Digest algorithm for signature is RSA_SHA1 or DSA_SHA1 when using DSA certificates.
Some IDPs may only support RSA_SHA256 signatures, in this case you need to be sure the certificate used to sign tokens is a RSA certificate, then fediz can be configured like this:
<signRequest algorithm="RSA_SHA256">true</signRequest>
Support for Encrypted tokens
The configuration needs to define the certificate used to decrypt tokens
<FedizConfig> <contextConfig name="/semarchy"> ....... <tokenDecryptionKey keyAlias="mytomrpkey" keyPassword="tompass"> <keyStore file="/path/to/mykeystore.jks" password="tompass" type="JKS" /> </tokenDecryptionKey> ......... </contextConfig> </FedizConfig>
Fediz normally requires tokens to be signed, but when tokens are encrypted, signature validation can be disabled (to support encrypted tokens that are not signed)
<FedizConfig> <contextConfig name="/semarchy"> ...... <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="samlProtocolType" version="2.0"> ...... <doNotEnforceEncryptedAssertionsSigned>true</doNotEnforceEncryptedAssertionsSigned> ...... </protocol> ...... </contextConfig> </FedizConfig>
SP Metadata
Fediz automatically build XML metadatas of the xDM application acting as the SAML Service Provider, from its configuration.
The Metadata Document is available from SAML/Metadata.xml URL, for example https://myhost/semarchy/SAML/Metadata.xml
Known Issues
- Fediz 1.5.0 release does not support SAML signed tokens without keyinfo in it. a NPE is thrown during SAML token validation.
Sample Configurations
Valid sample fediz_config.xml for ADFS with WS-Federation
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <FedizConfig> <contextConfig name="/semarchy"> <audienceUris> <audienceItem>https://dev-mdm.mydomain.com/semarchy/</audienceItem> </audienceUris> <certificateStores> <trustManager> <keyStore file="/opt/tomcat/.keystore" password="changeit" type="JKS" /> </trustManager> </certificateStores> <trustedIssuers> <issuer certificateValidation="PeerTrust" /> </trustedIssuers> <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="federationProtocolType" version="1.2"> <issuer>https://login.mydomain.com/adfs/ls/</issuer> <roleURI>http://schemas.microsoft.com/ws/2008/06/identity/claims/role</roleURI> </protocol> </contextConfig> </FedizConfig>
Valid sample fediz_config.xml for samling (Samling is a serverless SAML IDP simulator, probably the easiest way to test a fediz SAML setup as it does not need a SAML server setup)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <FedizConfig> <contextConfig name="/semarchy"> <audienceUris> <audienceItem>http://localhost:8088/semarchy/</audienceItem> </audienceUris> <certificateStores> <trustManager> <!-- not that certificate is in file directly, not imported in keystore, as this is also supported by fediz --> <keyStore file="/opt/tomcat/conf/samling.cert" type="PEM" /> </trustManager> </certificateStores> <trustedIssuers> <issuer certificateValidation="PeerTrust" /> </trustedIssuers> <protocol xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="samlProtocolType" version="2.0"> <disableDeflateEncoding>true</disableDeflateEncoding> <doNotEnforceKnownIssuer>true</doNotEnforceKnownIssuer> <issuer>https://fujifish.github.io/samling/samling.html</issuer> <roleURI>groups</roleURI> <roleDelimiter>,</roleDelimiter> </protocol> <logoutURL>/sem_check2</logoutURL> </contextConfig> </FedizConfig>
Sample SAML configuration with Pingfederate (Sanofi) Fediz 1.4.6 and com.semarchy.tool.jee.tomcat-8.5.4 at least are required for this configuration:
REST API
Once customers configure authentication in Semarchy, many also are interested in configuring authentication REST API. The REST API has two methods of authentication:
- Basic
- API tokens
Troubleshooting
If you see this error in the log:
org.apache.cxf.fediz.core.saml.SAMLTokenValidator.validateAndProcessToken Issuer 'null' not validated in keystore 'conf/ststrust.jks' org.apache.cxf.fediz.core.saml.SAMLTokenValidator.validateAndProcessToken Issuer 'https://sts.windows.net/62a9c2c8-8b09-43be-a7fb-9a87875714a9/' not trusted org.apache.cxf.fediz.core.handler.SigninHandler.handleRequest Federation processing failed: Security token issuer not trusted
Logging from org.apache.wss4j logger is necessary to understand the real issue behind this.
Sample error encountered by one Semarchy customer:
org.apache.wss4j.common.saml.SamlAssertionWrapper.checkIssueInstant SAML Token IssueInstant not met
The preceding error is normally a time drift related issue.
Solution: Synchronize servers through NTP (recommended) so that the clocks match.
Workaround: Use maximumClockSkew parameter as a workaround to allow a sufficient tolerance.
Otherwise possible reason for that is the certificate has either not been imported into the keystore or is not an up to date copy, then a SAML token not trusted error is shown.
Import the certificate with a command such as this:
sudo keytool -import -alias customer_saml_cert -file /data/installs/adfs.cer -keystore /opt/tomcat/conf/ststrust.jks
Or if you see this
Related articles
Filter by label
There are no items with the selected labels at this time.