In the first
blog on this topic I explained how to add security domains to the Fediz STS which is based on the Apache CXF STS. This blog focuses on how to set up the Fediz IDP thus you can access an application but authenticate either against the requestor IDP of realm A or realm B.
I posted a blog some time back about WS-Federation across several companies and explained the benefits and key requirements here. I recommend to read that blog first.
Here a quick summary of the goals and requirements by introducing WS-Federation for Web Application Single-Sign-On:
- Application doesn't care about authentication
- Application doesn't care against which authentication system the user has been authenticated
- Application doesn't care where the user attributes are coming from
- Application has got a trusted relationship with a single IDP/STS instance which ensures the user is authenticated and the user attributes are provided in one syntax and semantic independent from which source they are coming from
- Application must be able to enforce certain authentication methods (ex. strong authentication)
- Application must be able to enforce certain user attributes in the security token
In the last blog, we've prepared the STS which is responsible to issue tokens for the two realms REALMA and REALMB. Further, the STS is able to federate between the two realms by mapping the identities (attribute type of Relationship
bean configuration. This means, a person must have an identity in realm A (ex. bob) and an identity in realm B (ex. BOB). To keep it simple, the mapping is based to lowercase the username. Another option is to federate/map the claims which doesn't require that a person must have an identity in both realms. This requires more effort to set up a demo and might be provided in the future for illustration purposes, but all required functionality and extension points are available.
Notes:
Install Apache CXF Fediz IDP
The Fediz IDP is provided as part of the subproject Fediz in Apache CXF. The new version provides the Apache Maven profile
realm-a (Default) and
realm-b which packages the IDP either for security domain
REALM A and
REALM B.
You can either download the sources of the Fediz IDP from the following location
git clone git://git.apache.org/cxf-fediz.git
or
svn co https://svn.apache.org/repos/asf/cxf/fediz/trunk
You can build the IDP for
realm A with the following Maven command
mvn clean install -Prealm-a
The IDP is packaged as a WAR file at
services/idp/target/fediz-idp.war
You can build the IDP for realm B with the following Maven command
mvn clean install -Prealm-b
The IDP is packaged as a WAR file at
services/idp/target/fediz-idp-remote.war
Note: The WAR file and therefore the servlet context name is not fediz-idp
but fediz-idp-remote
. This is required because cookies are bound to the hostname (ex. localhost) and the path (ex. fediz-idp). If the servlet context is the same, cookies are overwritten between the two IDP instances. There are also other options to bound the WAR file with a specific servlet context name but this relies on the Servlet Container provider.
Last option is to download the archive from the snapshot maven repository. Keep in mind that this IDP is built with the profile realm-a. Only the following files must be updated for realm B:
WEB-INF/applicationContext.xml
Change
<import resource="idp-config-realma.xml" />
to
<import resource="idp-config-realmb.xml" />
WEB-INF/classes/realm.properties
Change
realm.STS_URI=REALMA
to
realm.STS_URI=REALMB
WEB-INF/web.xml
Change
<param-value>urn:org:apache:cxf:fediz:idp:realm-A</param-value>
to
<param-value>urn:org:apache:cxf:fediz:idp:realm-B</param-value>
Note: The built WAR files require that IDP Realm A is deployed into a Servlet Container running on port 9443
and IDP Realm B is deployed into a Servlet Container running on port 12443
. If you want to change that then you must update the file WEB-INF/classes/realm.properties
or at source location services/idp/src/main/resources/
.
Update Relying Party (Application)
I assume you have installed
fedizhellworld
example into a supported Serlvet Container. If not, install the
fedizhellworld
example based on the
README.txt
.
The following steps must be processed to establish the trust with the IDP Realm A:
- Issuer URL must be Realm A (ex.
https://localhost:9443/fediz-idp/federation
)
- Signer certificate of Realm A must be imported into the truststore because new certificates are used for realm A and realm B
You can either copy the file stsstore.jks
from the STS archive within WEB-INF/classes
or copy the file realma.cert
from the STS archive from the same location.
Run the demo
You have now deployed the IDP realm A (fediz-idp.war) into a Servlet Container listening on port
9443
and IDP realm B (fediz-idp-remote.war) into a Servlet Container listening on port
12443
. Finally, the Relying Party has been updated to trust the IDP Realm A.
When you now access the fedizhelloworld application (ex. https://localhost:8443/fedizhelloworld/secure/fedservlet) you get redirected to the IDP Realm A and the following web page is shown
You can now choose in which domain you would like to authenticate. Choose the IDP in the list and click Select Home Realm. If you choose Realm B you get redirected to IDP Realm B and username/password popup is shown (use uppercase username and passwords) or IDP Realm A shows username/password popup (use lowercase username and passwords).
If you choose Realm B and enter the user ALICE and the password ECILA you finally see the user alice (lowercase) shown in the application. You know why? Exactly, the STS does the identity mapping when the REALM A is requested a SAML token for the application fedizhelloworld on-behalf-of the SAML token issued by Realm B.
Notes
- The IDP will ask you only once to choose your home realm. The choice is stored in the cookie
FEDIZ_HOME_REALM
- If your home realm is realm B and you're successfully authenticated, the IDP realm A won't redirect you to realm B the next time, as the original SAML token of realm B is cached in realm A.
IDP Configurations
The design of the IDP changed (Spring Web Flow and Spring Security), new features are implemented and thus the configuration is completely different to version 1.0. I don't want to go into too much details in this blog, instead I'll update the Apache CXF Fediz
Wiki soon.
Use form based login
Change the spring security configuration in
WEB-INF/security-config.xml
and set the following configuration:
<!--<security:http-basic />-->
<security:form-login />
Configure an additional Relying Party
The main configuration file of the IDP is
idp-config-realma.xml
. This file contains configurations for the IDP, trusted IDPs and Relying Parties.
If you want to configure an additional application add a ServiceConfig
bean and add it to the map services
in the IDP configuration bean.
<bean id="idp-realmA" class="org.apache.cxf.fediz.service.idp.model.IDPConfig">
...
<property name="services">
<util:map>
<entry key="urn:org:apache:cxf:fediz:fedizhelloworld" value-ref="srv-fedizhelloworld" />
</util:map>
</property>
...
<bean id="srv-fedizhelloworld" class="org.apache.cxf.fediz.service.idp.model.ServiceConfig">
<property name="realm" value="urn:org:apache:cxf:fediz:fedizhelloworld" />
<property name="protocol" value="http://docs.oasis-open.org/wsfed/federation/200706" />
<property name="serviceDisplayName" value="Fedizhelloworld" />
<property name="serviceDescription" value="Web Application to illustrate WS-Federation" />
<property name="role" value="ApplicationServiceType" />
<property name="tokenType" value="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" />
<property name="lifeTime" value="3600" />
<property name="requestedClaims">
<util:list>
<bean class="org.apache.cxf.fediz.service.idp.model.RequestClaim">
<property name="claimType" value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname" />
<property name="optional" value="false" />
</bean>
<bean class="org.apache.cxf.fediz.service.idp.model.RequestClaim">
<property name="claimType" value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname" />
<property name="optional" value="false" />
</bean>
<bean class="org.apache.cxf.fediz.service.idp.model.RequestClaim">
<property name="claimType" value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" />
<property name="optional" value="false" />
</bean>
<bean class="org.apache.cxf.fediz.service.idp.model.RequestClaim">
<property name="claimType" value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role" />
<property name="optional" value="true" />
</bean>
</util:list>
</property>
</bean>
It's important that the attribute
realm
matches with the realm configured in the application (
fediz-config.xml
). The attributes
tokenType
,
lifeTime
and
requestedClaims
are optional. Only the protocol defined in the above bean is supported by the IDP and therefore the default value. The remaining attributes are ignored but used in the future like the Web GUI.
Configure an additional Trusted IDP
If you want to configure an additional trusted IDP add a
TrustedIDPConfig
bean and add it to the map
trustedIDPs
in the IDP configuration bean.
<bean id="idp-realmA" class="org.apache.cxf.fediz.service.idp.model.IDPConfig">
...
<property name="trustedIDPs">
<util:map>
<entry key="urn:org:apache:cxf:fediz:idp:realm-B" value-ref="trusted-idp-realmB" />
</util:map>
</property>
...
<bean id="trusted-idp-realmB" class="org.apache.cxf.fediz.service.idp.model.TrustedIDPConfig">
<property name="realm" value="urn:org:apache:cxf:fediz:idp:realm-B" />
<property name="cacheTokens" value="true" />
<property name="url" value="https://localhost:${realmB.port}/fediz-idp-remote/federation" />
<property name="certificate" value="realmb.cert" />
<property name="trustType" value="PEER_TRUST" /> <!-- Required for Fediz Core, Process SignInResponse -->
<property name="protocol" value="http://docs.oasis-open.org/wsfed/federation/200706" />
<property name="federationType" value="FederateIdentity" /> <!-- Required for STS Relationship -->
<property name="name" value="REALM B" />
<property name="description" value="IDP of Realm B" />
</bean>
It's important that the filename of the PEM encoded certificate is configured which has been used to sign the SAML token by the trusted IDP. The attribute
name
is required for informational purposes whereas the remaining attributes are ignored but used in the future like the Web GUI.
Even there is much more to say I finish this post and write about other features of the new Fediz IDP in the near future.
Please post feedback and ideas to the CXF mailing list.
Thank you for all support and feedback!