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
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).
# 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 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.zip
curl 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
sudo mkdir /usr/share/tomcat9/lib/fediz |
Update catalina.properties in ${catalina.home}/conf to add the previously created directory to the common loader:
# 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.
sudo 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.
<!-- 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"/> --> |
<!-- 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 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" below
sudo vim /etc/tomcat9/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> |
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
Activate this logger
sudo 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. |
Some IDPs may not support default SAML Sign-in Request generated by fediz. We provide a way to customize some parts of this Request:
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 |
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> |
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> |
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
<?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> |
<?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> |
Once customers configure authentication in Semarchy, many also are interested in configuring authentication REST API. The REST API has two methods of authentication:
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 appear here based on the labels you select. Click to edit the macro and add or change labels.
|