DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • MuleSoft OAuth 2.0 Provider: Password Grant Type
  • The Evolution of User Authentication With Generative AI
  • API and Security: From IT to Cyber
  • Optimizing GitHub Access Management for Enterprises: Enhancing Security, Scalability, and Continuity with Jenkins GitHub App Authentication and Load Balancing

Trending

  • Performance Optimization Techniques for Snowflake on AWS
  • Concourse CI/CD Pipeline: Webhook Triggers
  • Emerging Data Architectures: The Future of Data Management
  • Why High-Performance AI/ML Is Essential in Modern Cybersecurity
  1. DZone
  2. Coding
  3. Languages
  4. Single Sign-On Made Easy: SAML With Tomcat and PicketLink

Single Sign-On Made Easy: SAML With Tomcat and PicketLink

Learn all about SAML single sign-on with PicketLink and Tomcat, including an investigation of how SAML single sign-on works, and overviews of Fediz, Tomcat, and PicketLink.

By 
Brett Crawley user avatar
Brett Crawley
·
Feb. 03, 16 · Tutorial
Likes (11)
Comment
Save
Tweet
Share
47.5K Views

Join the DZone community and get the full member experience.

Join For Free

How Does SAML Single Sign-on Work?

In the sequence diagram below you can see the interactions taking place during authentication of a user via SAML SSO. In the sequence diagram below you can see the interactions taking place during authentication of a user via SAML SSO.


The user requests a protected resource from the web application, the application server requires that the user supplies a SAML token that asserts they are authenticated and that they have the necessary rights to the application. So it redirects them to the Identity Provider (IdP) who will give him that SAML token.

The identity provider requires that the user be authenticated too and this takes place perhaps via Kerberos or some other means. Once the Identity Provider is satisfied that the user is authenticated it request metadata about the user to satisfy the assertion requirements of the Service Provider (SP).

It then builds the token and sends it back to the browser. Who then again talks to the application server forwarding it his token. If the assertions stored in the token satisfy the web applications security requirements the user is then authorised to access the application.

Tomcat

The Tomcat project does not include an out of the box solution for Single Sign-On with SAML. I started looking at how to do this and found two possible solutions/libraries. Both seemed quite promising, they both stated “on the box” that they implemented SAML and that they worked with Tomcat. My initial reaction was to try and use the one developed by Apache since I was going to use it with another Apache tool i.e. Tomcat.

Fediz

The Apache library is a sub-project of CXF (an open-source services/integration framework) and the project is called Fediz (an open-source web security framework) and contains tomcat valve which enables this.

The valve is called FederationAuthenticator. However after many trials and tribulations including running Tomcat with a debugger attached, I found that SAML was not supported for SSO because unfortunately the code contains a bug. In the SAMLProcessorImpl there is a method called processRelayState that checks if the requestState parameter is null however a couple of calls up the stack in the SigninHandler processSigninRequest method instead of retrieving the FedizRequest object from the restored Request a new one is created that does not, unfortunately, set the requestState property of the FedizRequest.

Therefore SSO with SAML is currently not possible with Fediz, there were also other issues specific to using it with Active Directory Federation Services (ADFS) so in the end, I abandoned this library and decided to try using the PicketLink library and the ServiceProviderAuthenticator valve. Right now I haven’t had time to investigate all of the problems but at some point in the future I may go back and investigate further trying to fix the issues with the FederationAuthenticator and ask to become a committer to the fediz project but right now that is not possible.

PicketLink

This time, things went a little bit better, as in it worked. Picketlink is pretty much aimed at JBoss users so the documentation for use with Tomcat is quite limited. So what do you need to configure, to have a basic system up and running and working with Active Directory Federation Services using SAML?

  1. You need to add the PicketLink libraries and dependencies to the Tomcat lib folder.
  2. You need to add a valve to the application context, this can be done in the server.xml.
  3. You will need to modify the web.xml file in the WEB-INF folder of your web app.
  4. You will need to add a config file called picketlink.xml to the WEB-INF folder of your web app.

Step 1.

For the simple configuration, we are putting together here, you will only need 6 jar files. These jar files must be placed in the $CATALINA_HOME/lib folder because they are required by Tomcat itself to enable access to the web app. The required jars are:

  • picketlink-common-2.7.2.jar
  • picketlink-config-2.7.2.jar
  • picketlink-federation-2.7.2.jar
  • picketlink-tomcat7-2.7.2.jar
  • jboss-logging-3.0.0.GA.jar
  • jboss-security-spi-3.0.0.Final.jar

Step 2.

To add the valve to your web app you simply add the following line of XML:

<Valve className="org.picketlink.identity.federation.bindings.tomcat.sp.ServiceProviderAuthenticator" />

to your server config as in the example below within the /myapp context and beware that the tag names are case sensitive:

<?xml version='1.0' encoding='utf-8'?>
<Server port="14772" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    <Listener className="org.apache.catalina.core.JasperListener" />
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

    <Service name="Catalina">
        <Connector port="8080" protocol="HTTP/1.1"
            connectionTimeout="20000"
            redirectPort="8443" />
        <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
            maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
            clientAuth="false" sslProtocol="TLS"
            keystoreFile="conf/ssl-keystore.jks" keyAlias="appserver.mydomain.com" />
        <Engine name="Catalina" defaultHost="localhost">
            <Host name="localhost" appBase="webapps">
                <Context docBase="myapp.war" path="/myapp">
                    <Valve className="org.picketlink.identity.federation.bindings.tomcat.sp.ServiceProviderAuthenticator" />
                </Context>
            </Host>
        </Engine>
    </Service>
</Server>

Note there is no need for a Realm to be specified in the server.xml and there is also no need to configure JAAS

Step 3.

Things to note about the web.xml are:

  1. The security roles are the groups/roles the users have in your user database be that LDAP or some other structure.
  2. The security constraints contain an auth constraint that uses one of these roles.
  3. There is no login-config section.
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             version="2.5">
    
        <display-name>My Application</display-name>
        <description>My Web Application</description>
    
        <servlet>
            <servlet-name>WorkerServlet</servlet-name>
            <servlet-class>com.brett.WorkerServlet</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>WorkerServlet</servlet-name>
            <url-pattern>/internal/worker/*</url-pattern>
        </servlet-mapping>
    
        <security-constraint>
            <web-resource-collection>
                <web-resource-name>User Space</web-resource-name>
                <url-pattern>/internal/*</url-pattern>
                <http-method>GET</http-method>
                <http-method>POST</http-method>
                <http-method>PUT</http-method>
                <http-method>HEAD</http-method>
                <http-method>TRACE</http-method>
                <http-method>DELETE</http-method>
                <http-method>OPTIONS</http-method>
            </web-resource-collection>
            <auth-constraint>
                <role-name>BasicUser</role-name>
            </auth-constraint>
            <user-data-constraint>
                <transport-guarantee>NONE</transport-guarantee>
            </user-data-constraint>
        </security-constraint>
    
        <security-role>
            <description>App Users</description>
            <role-name>BasicUser</role-name>
        </security-role>
    
    </web-app>

Step 4.

Here is where all the magic is. In the PicketLinkSP section, the BindingType refers to the method used for communicating back and forth with the IdP. The IdentityURL is the address of the IdP to be used for requesting the SAML token and the ServiceURL is the address to which the browser should send this token before it will be allowed to receive the resource it required. The trust section contains a list of domains for which the there is a trust relationship.

The handlers section defines which handlers will be involved in interpreting the token during the authentication / authorisation process for the web app. Here we can see that there is a Trust Handler which verifies the rules in the trust section are met, in this case, the domains. There is also a Log Out Handler for un-authenticating the user. An Authentication Handler that checks the validity of the SAML token verifies the Subject (the user) is authenticated and finally that the user has the roles necessary.

The ROLE_KEY option tells the SAML2AuthenticationHandler which of the assertion attributes relate to the roles of the user. If this isn't supplied unfortunately the library doesn't seem to have an intelligent default because it includes everything as a role including the users email address and username.

<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1">
    <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1" BindingType="POST">
        <IdentityURL>${idp.url::https://dc.mydomain.com/adfs/ls/}</IdentityURL>
        <ServiceURL>${myapp.url::https://appserver.mydomain.com:10503/myapp/internal/}</ServiceURL>
        <Trust>
            <Domains>localhost,mydomain.com</Domains>
        </Trust>
    </PicketLinkSP>
    <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">
        <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2IssuerTrustHandler" />
        <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" />
        <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
            <Option Key="ROLE_KEY" Value="http://schemas.microsoft.com/ws/2008/06/identity/claims/role"/>
        </Handler>
        <Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" />
    </Handlers>
</PicketLink>

Pitfalls to Look Out For

The serviceURL in your picketlink.xml should end with a slash and needs to be a URL that requires authentication. Don’t worry what URL the user will be redirected to the URL they originally wanted.

Make absolutely certain that your clocks are synchronized properly. I lost quite a lot of time because my tomcat server was 20 seconds behind my identity server, this resulted in the tokens not yet being valid when they were received but the error reported was that the token had expired. This resulted in a continuous loop of authentication going back and forth between the Identity Provider (IdP) and the Service Provider (SP) / Tomcat

References:

PicketLink
ServiceProviderAuthenticator Documentation

authentication security Apache Tomcat

Opinions expressed by DZone contributors are their own.

Related

  • MuleSoft OAuth 2.0 Provider: Password Grant Type
  • The Evolution of User Authentication With Generative AI
  • API and Security: From IT to Cyber
  • Optimizing GitHub Access Management for Enterprises: Enhancing Security, Scalability, and Continuity with Jenkins GitHub App Authentication and Load Balancing

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!