Federated authentication between two Identity Servers

In this post I shall be explaining how federated authentication can be used to redirect the authentication of a user to another Identity Server.

Download the Identity Server from here, if you have not done so already. The installation guide can be found here.

Checkout the repository of the travelocity SSO sample from the link below, follow these instructions to checkout a folder.

https://github.com/wso2/product-is/tree/master/modules/samples/sso

In this tutorial we will be using two Identity Server instances namely an internal IS running on port 9443, and an external IS running on port 9445. Check this post if you need more information on how to run multiple Identity Servers on different ports. The travelocity sample will be deployed on tomcat. The travelocity webapp will redirect the login to the external IS, which again will redirect the authentication to the internal IS. The stepwise scenario is as follows.

  1. User visits the travelocity website and clicks to login through SAML SSO then the user is redirected to the external IS.
  2. The external IS redirects the authentication to the internal IS.
  3. The internal IS login screen is displayed and the user enters the credentials.
  4. The user credentials are checked against the LDAP of the internal IS.
  5. If authenticated, the user is redirected back to the external IS.
  6. The external IS redirects the user back to travelocity website as a logged in user.

dfdf

Step 1: Travelocity.properties

Go to the directory you saved the sample in and open src/main/resources/travelocity.properties. Check if the the configuration is as below and change the port of the IdPURL to 9445.

SAML2.SPEntityId=travelocity.com

SAML2.AssertionConsumerURL=http://localhost:8080/travelocity.com/home.jsp

SAML2.IdPEntityId=localhost

SAML2.IdPURL=https://localhost:9445/samlsso

Step 2: External IS Configuration

The external IS should have a new Identity Provider configured to federate the users to the internal IS. It should also have a service provider configured to identify the webapp.

  1. Add a new Identity Provider in the internal IS. Give a name and expand Federated Authenticators then SAML2 Web SSO Configuration. Do the configuration as follows. 

123.png

Save the configuration.

  1. Add a new Service Provider and click on Configure under Inbound Authentication Configuration -> SAML2 Web SSO Configuration then do the configuration as follows.

45Expand the Local & Outbound Authentication Configuration, then click on the  Federated Authentication radio button then select the identity provider you configured from the drop down.

6

Save the configuration.

Step 3: Internal IS Configuration

A new service provider needs to be configured in the Internal IS with the external IS as the Assertion Consumer URL.

Add a new Service Provider and click on Configure under Inbound Authentication Configuration -> SAML2 Web SSO Configuration then do the configuration as follows.

89

Save the configuration.

Step 4: Testing the authentication

Now if you add a user to the internal IS, you should be able to log in with the user even though you have configured the service provider in the external IS.

The basic HTTP header flow is as follows.

http://localhost:8080/travelocity.com 1. User visits travelocity webpage
http://localhost:8080/travelocity.com/samlsso?SAML2.HTTPBinding=HTTP-Redirect 2. User clicks on the login with SAML hyperlink
https://localhost:9445/samlsso?SAMLRequest=**** 3. User is directed to the external IS
https://localhost:9443/samlsso?SAMLRequest=**** 4. User is directed to the login page of the internal IS from the external IS
https://localhost:9443/samlsso 5. User logs in
https://localhost:9445/commonauth 6. Logged in user is redirected back to external IS
https://localhost:9445/samlsso?sessionDataKey=**** 7. User is given a session data key and is considered a logged in user

Hope this helps, this would prove useful in scenarios where the service provider has to be registered in one IS while the LDAP has been configured to another IS. Do drop a comment if you come across any issues :)

IDP Initiated SSO vs SP Initiated SSO

When working with SSO with SAML, it is vital that one understands the difference between Identity Provider Initiated Single Sign On and Service Provider Initiated SSO. Before that, it’s important to understand who Identity Providers and Service Providers are and their differences.

Given below are the definitions from the OASIS Organization that created SAML.

“An Identity Provider is a kind of provider that creates, maintains, and manages identity information for principals and provides principal authentication to other service providers within a federation, such as with web browser profiles”

“A Service Provider is a role donned by a system entity where the system entity provides services to principals or other system entities”

In the context of this discussion, an Identity Provider is basically an entity that provides authentication for it’s users, whereas the webapp using this service could be called as the Service Provider.  In the Travelocity Sample in my previous post, travelocity.com is the SP whereas the WSO2 Identity Server is the IDP.

Now the difference between IDP Initiated SSO and SP Initiated SSO is quite simple. In SP Initiated SSO, the Single Sign On process is initiated by the web application. The user first visits the webapp, then the user is redirected to the IDP along with an AuthnRequest generated at the SP. The Travelocity Sample in my previous post is a classic example of this scenario. When the user visits http://localhost:8080/travelocity.com, and when he clicks on the hyperlink to login with SAML, the webapp initiates the SSO process with an AuthnRequest. A sample of the AuthnRequest sent is given below.

<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                    AssertionConsumerServiceURL="http://localhost:8080/travelocity.com/home.jsp"
                    Destination="https://localhost:9443/samlsso"
                    ForceAuthn="false"
                    ID="0"
                    IsPassive="false"
                    IssueInstant="2016-01-18T12:36:02.365Z"
                    ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                    Version="2.0"
                    >
    <samlp:Issuer xmlns:samlp="urn:oasis:names:tc:SAML:2.0:assertion">concurUSD</samlp:Issuer>
    <saml2p:NameIDPolicy xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                         AllowCreate="true"
                         Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
                         SPNameQualifier="Issuer"
                         />
    <saml2p:RequestedAuthnContext xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                                  Comparison="exact"
                                  >
        <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
    </saml2p:RequestedAuthnContext>
</samlp:AuthnRequest>

The AuthnRequest contains important information such as the Assertion Consumer URL, the issuer and the NameID Format which is required by the IDP to identify where to redirect the request. Having authenticated the user, the IDP responds with a SAML Response and the process is similar for both types after this.

On the other hand, when using IDP Initiated SSO, the user does not go through the webapp first, but rather is directed to the IDP. So the first thing the user sees is the authentication page of the IDP. This is done by using a query string along with the URL.

The sample URL with the query string used by the WSO2 IS running on localhost port 9443, is given below.

https://localhost:9443/samlsso?spEntityID=<sp-issuer&gt;

Here the <sp-issuer> is the Issuer value we define when creating a Service Provider in the WSO2 IS Management Console.

So in the same travelocity example, if I want to use IDP Initiated SSO, the first thing that needs to be done is to “Enable IdP Initiated SSO” in the Service Provider configuration in the WSO2 IS. This is done by selecting the Service Provider “travelocity.com” from the list of SPs, then Inbound Authentication Configuration -> SAML2 Web SSO Configuration. Then click on edit, then check the “Enable IdP Initiated SSO” check-box at the very bottom. The save the configuration.

Now instead of having to go through http://localhost:8080/travelocity.com, and having to click on the SAML 2 hyperlink, the user can directly go to the URL given below and he shall be directed to the WSO2 IS authentication page.

https://localhost:9443/samlsso?spEntityID=travelocity.com

Both these methods are equally used in real life and the choice of one over the other, depends heavily on the requirement of the user.

Hope you enjoyed the post, do drop a comment if I’ve missed anything :)

How the Travelocity Sample Works

If you’ve been following the Configuring Single Sign-On with SAML 2.0 on the WSO2 Identity Server Documentation, but can’t seem to figure out how SSO works on it, you’ve arrived at the right place. In this post I’ll be explaining my understanding of how the sample works. This might not be the most accurate description, so please feel free to drop a comment if I’ve mistaken something :)

You can checkout the sample from the SVN repository using the command given below.

svn co http://svn.wso2.org/repos/wso2/carbon/platform/branches/turing/products/is/5.0.0/modules/samples/sso/

The tree structure is given below,

12

Here the most important files for the purposes of this tutorial are, the java classes, the properties files, the web.xml and the home and index java servlet pages. The rest can be disregarded since they are not concerned with SSO.

To make this tutorial simple, we’ll be going through each of the components similar to the order in which they are referred in SAML2 based SSO. So once you have done the configuration based on the tutorial and the war file is deployed on tomcat, the first thing that happens when you visit http://localhost:8080/travelocity.com is that you will be directed to the index page.

Part 1: The index.jsp

Given below is the index page of the travelocity sample.

3

For this tutorial, we shall only be focused on “login with SAML from WSO2 Identity Server”. If you look at the source code of the index.jsp page, you will see that the hyperlink for the SAML Login is “samlsso

4

So when you click on the “here” hyperlink, you will get redirected to http://localhost:8080/travelocity.com/samlsso but in reality you get directed to the authentication page of the WSO2 Identity Server which is given below.

x

This is where the next component comes into play. So let’s look at the SSOFilter.

Part 2: The SSOFilter

A filter is a way of performing filtered functionality on a java web application. Typically filters are used to perform some piece of functionality either before or after the primary functionality of the web application. The architecture of the filter is given below.

5

How the filter is triggered will be discussed in the web.xml (Part 3).

In this scenario, the SSO functionality has been implemented in the form of a filter using the WSO2 library org.wso2.carbon.identity.sso.agent. When the filter is triggered, the request is sent through the SSOFilter. Here a SAML Assertion is generated and the browser is redirected to the WSO2 IS authentication page and once a user is authenticated, the SAML Response is again sent through the filter. During this process the SAML response is validated using the public and private key pair found in the wso2carbon.jks file. Once the user is validated, the browser is redirected to the home.jsp which is the Assertion Consumer URL.

Part 3: The web.xml

The web.xml is the deployment descriptor file of a java web application and is used to determine how URLs map to servlets, which URLs require authentication, and other information. It can be found inside the WEB-INF directory in the webapp folder.

In the web.xml of travelocity, the SSOFilter is defined.

6

Here the filter class name is given to locate the jar file from the libraries. The jar file was added as a dependency in the pom.xml.

The filter mapping is used to initialize the filter. When a particular url is requested, if it contains any of the url-patterns as given in the filter mapping, the particular filter is initiated. In this scenario, when the url http://localhost:8080/travelocity.com/samlsso is requested, since it contains the /samlsso url pattern, the SSOFilter is initiated.

Now once the request is sent through the SSOFilter and the SAML Response is validated, the user is then redirected to the Assertion Consumer URL. In this case the consumer url is http://localhost:8080/travelocity.com/home.jsp. So next let’s look at the home.jsp.

Part 4: The home.jsp

7

In this example, the default dashboard of the webapp is implemented within the consumer url itself, but in practical situations, the consumer url merely redirects the user to the particular dashboard of the logged in user.

Given below is the source of the home.jsp.

8

The first few lines of code in the home.jsp are there to retrieve the attributes from the response. the claimedID and openIDAttributes are irrelevant because we are only focused on SAML in this tutorial. The subject is the username of the logged in user. The samlSSOAttributes and accessTokenResponseBean are also saved if needed to be used. At any point if any of the if statements become false, that means that the user is not validated, and redirects the browser back to the index.jsp.

The rest of the home.jsp is HTML and is fairly irrelevant except for the part where it displays the username of the logged in user from the subjectID.

g

That concludes the SAML process but to fully understand the working of SSO, it’s important to know how the properties file is defined and how it is loaded.

Part 5: The travelocity.properties

The file is found inside the resources folder and this file contains all the information about SAML based SSO for the travelocity.com webapp. The file is loaded to the SSOAgentConfigs by the SampleContextEventListener.java, which will be discussed in the next part.

The information in the properties file such as the issuerID, the Assertion Consumer URL are used by the SSOFilter to identify the Service Provider in the WSO2 Identity Server. This also says if the response and assertion are signed or not, which needs to be configured in the IS.

Other information such as the Keystore Password are used to retrieve the public and private keys from the keystore wso2carbon.jks, to validate the saml response received by the filter.

It is important to understand that the properties file nor the keystore are used by the web application but rather are used by the SSOFilter.

Part 6: The SampleContextEventListener.java

So how does the SSOFilter know where to find the properties file and the keystore. This is where the SampleContextEventListener.java is used. The SampleContextEventListener is initialized as a listener in the web.xml as follows.

t

When the webapp is deployed, the SampleContextEventListener loads the properties file and the keystore to the SSOAgentConfigs in the org.wso2.carbon.identity.sso.agent library. From here it is again retrieved whenever needed.

So that’s a brief explanation as to how the travelocity.com sample works, there’s much more to it, specially the functioanlity of the SSOFilter. Hope I covered everything correctly, do drop a comment if I’ve missed anything.