October 13, 2011

Configure and deploy Identity Provider (IdP) - Part II

In my previous blog I talked about setting an STS which supports username/password authentication and the issuance of a SAML 2.0 token which contains additional claims information.
We need these claims information to provide the application (called Relying Party in WS-Federation specification) the information like application roles for role based access control. Claims based authorization goes one step further and provides other claims data of the authenticated entity (SAML subject).

Introduction

This blog is about the Identity Provider (IDP) implementation which is referenced in the WS-Federation specification. Therefore, I'm giving a short introduction. This blog series looks at the passive requestor profile only of WS-Federation.

The following picture is used by Microsoft which supports WS-Federation in their Windows Identity Foundation framework.


(C) Microsoft



The key principals of WS-Federation are:
  • Externalize authentication process from the application container
  • Provide the claims/attributes of the authenticated identity to the application for role based and fine grained authorization
WS-Federation gives you the following benefits:
  • Applications can benefit of stronger security mechanism without changes
  • Identities/users don't have to be provisioned in all security domains to propagate identities across the security domains
  • B2B partners can be integrated without changing the application (includes programming and configuration)
  • Audit-Trail end-to-end


    Deploy Identity Provider (IdP)



    This sample IDP will support the following functionality:
    • Authentication based on username/password (Basic Authentication)
    • The authentication store is configured in the STS and can be file based (part of this example) or LDAP
    • Following federation parameters are supported:
      • wtrealm
      • wreply
      • wctx
      • wresult
    • Required claims can be configured per Relying Party (based on wtrealm value)
    Jürg Portmann and myself have put together this IDP. You can download the maven project services/idp here.


    1. Claims configuration per relying party

    The required claims per relying party are configured in the WEB-INF/RPClaims.xml. The XML file has the following structure. The key of each map entry must match with the wtrealm paramater in the redirect triggered by the relying party.
    (the set up of the relying part will be covered in the next blog).


        <util:map id="realm2ClaimsMap">
            <entry key="http://localhost:8080/wsfedhelloworldother/"
                value-ref="claimsWsfedhelloworld" />
            <entry key="http://localhost:8080/wsfedhelloworld/"
                value-ref="claimsWsfedhelloworldother" />
        </util:map>

        <util:list id="claimsWsfedhelloworld">
            <value>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname
            </value>
            <value>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname
            </value>
        </util:list>

        <util:list id="claimsWsfedhelloworldother">
            <value>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname
            </value>
            <value>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname
            </value>
            <value>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
            </value>
        </util:list>   


    You group the required claims in beans which are a list of String as illustrated in claimsWsfedhelloworld and claimsWsfedhelloworldother.

    The map bean must be named realm2ClaimsMap and maps the different relying parties (applications) to one of the claim lists.


    In a further release, this information will be pulled from a WS-Federation Metadata document published by the replying party.


    2. Project dependencies
     
    The IDP reuses a lot of existing projects like Apache CXF to communicate with the STS for instance and provides an adaption of the WS-Trust interface to pure HTTP functionality as it is supported by a browser. The IDP has the following dependencies in the Maven project:


        <properties>
          <cxf.version>2.5.2</cxf.version>
       </properties>

       <dependencies>
            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-rt-transports-http</artifactId>
                <version>${cxf.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-rt-frontend-jaxws</artifactId>
                <version>${cxf.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-rt-ws-policy</artifactId>
                <version>${cxf.version}</version>
            </dependency>
            <dependency>
                <groupId>
    org.apache.cxf</groupId>
                <artifactId>
    cxf-rt-ws-security</artifactId>
                <version>${cxf.version}</version>
            </dependency>

       </dependencies>  


    3. IDP web application configuration

    Setting up the IDP involves a few steps only. If you you don't deploy the IDP in the same servlet container as the STS you must first download Tomcat 7 and update server.xml. If you deploy the IDP in the same servlet container you can skip 3.1

    3.1 Configure HTTP/S connector in Tomcat

    The HTTP connector should be configured with port 9080.


    The HTTPS connector in Tomcat is configured in conf/server.xml. Deploy the tomcatkeystore.jks of the example project  to the Tomcat root directory if the Connector is configured as illustrated:

        <Connector port="9443" protocol="HTTP/1.1" SSLEnabled="true"
                   maxThreads="150" scheme="https" secure="true"
                   keystoreFile="tomcatKeystore.jks"
                   keystorePass="tompass" sslProtocol="TLS" />

    This connector configures a self-signed certificate which is used for simplification only. You should get a certificate signed by a Certificate Authority for production usage.

    3.2 Configure Username/password authentication


    As described in section 1. the requested claims per relying party are managed in the file WEB-INF/RPclaims.xml.

    3.3 IDP and STS distributed
     
    If the IDP and STS are not deployed on the same machine (likewise in production) you have to update the following configuration:






    1) The remote WSDL location of the STS:

    WEB-INF/web.xml:

      <init-param>
        <param-name>sts.wsdl.url</param-name>
        <param-value>https://localhost:9443/wsfedidpsts/STSService?wsdl</param-value>
      </init-param>


    2) the transport conduit to enable the truststore as described in more detail here:


    WEB-INF/beans.xml

      <http:conduit name="https://localhost:9443/.*">
        <http:tlsClientParameters disableCNCheck="true">
          <sec:trustManagers>
            <sec:keyStore type="jks" password="cspass" resource="clientstore.jks"/>
          </sec:trustManagers>
        </http:tlsClientParameters>
      </http:conduit>




    3) fully qualified realm in realm2ClaimsMap


    As described in 1) the key of an entry in the map realm2ClaimsMap must match with the  parameter wtrealm in the redirect triggered by the relying party. If you access the relying party using a fully qualified URL, you must use the fully qualified URL in the IDP too.  


    WEB-INF/RPclaims.xml


        <util:map id="realm2ClaimsMap">
            <entry key="http://localhost:8080/wsfedhelloworldother/"
                value-ref="claimsWsfedhelloworld" />
            <entry key="http://localhost:8080/wsfedhelloworld/"
                value-ref="claimsWsfedhelloworld2" />
        </util:map>



    4. Deploy the IDP to Tomcat

    To deploy the IDP using Maven you have to follow these steps:
    • Configuring the following maven plugin
          <plugin>
              <groupId>org.codehaus.mojo</groupId>
              <artifactId>tomcat-maven-plugin</artifactId>
              <version>1.1</version>
              <configuration>
                   <server>myTomcat</server>
                   <url>http://localhost:9080/manager/text</url>
                   <path>/${project.build.finalName}</path>
              </configuration>
          </plugin>
    • Add the server with username and password to your settings.xml
    • Ensure the user has the role "manager-script" as described here
    • Run mvn tomcat:redeploy
      (I recommend to use redeploy as deploy works the first time only)
    If you use Tomcat 6, you must change the url of the tomcat maven plugin:
        <url>http://localhost:9080/manager</url>


    4. Test the IDP

    As long as you don't have a relying party in place you can't easily test the IDP. The following post explains the set up of the relying party using Tomcat 7.


    If you like you can test the IDP by using an HTTP client and pass the following request parameters (urls must be encoded):

    wa       wsignin1.0
    wreply   http://localhost:8080/wsfedhelloworld/secureservlet/fed
    wtrealm  http://localhost:8080/wsfedhelloworld/


    The browser will get a HTML form back (auto-submit). The action of the form is equal to the value of wreply which doesn't exist. You see the response of the STS escaped in the form parameter wresult.

    1 comment:

    1. Please ensure that the wtrealm parameter (url of your web application) matches a key in the bean realm2ClaimsMap.

      ReplyDelete