I described in the previous blogs how to set up the IDP which plays a key role in Web SSO based on the Passive requestor profile of WS-Federation and the CXF STS to issue security tokens. The IDP delegates authentication requests to the STS.
In WS-Federation, the authentication process is externalized to the IDP/STS. It provides you a SAML token (or another security token, WS-Federation is not tight to SAML) which contains all information of the authenticated user you need to implement finer grained authorization requirements without being tight to the user name.
The information in the SAML token must be integrated in Tomcat in such a way that application developers can use J2EE security as they are used to.
Example:
- HttpServletRequest.getUserPrincipal()
- HttpServletRequest.isUserInRole()
- security constraints in web.xml
It's standardized here how claim information (firstname, lastname, email, etc) must be represented in an AttributeStatement of a SAML token (assertion) but there is no Java API standard how this information could be accessed by programming. The federation plugin provides an extension of the Tomcat principal class which provides all these information.
This blog addresses two topics:
- how to build and deploy the federation plugin into Tomcat
- how to build and deploy a federation enabled web application into Tomcat
The plugin has been tested with JDK 1.6 and Tomcat 7.0.
Build and deploy the federation plugin into Tomcat
The source code is bundled as maven plugins which can be downloaded here and contains the following maven modules:
- plugins/core
This module contains the core ws-federation functionality which is container agnostic. The core functionality includes SAML 1.1/2.0 token validation (signature verification), lifetime and audience restriction validation. The FederationProcessor returns all information like roles, claims and authenticated user. - plugins/tomcat
This module contains the tomcat authenticator which integrates the ws-federation functionality into Tomcat. It hydrates the tomcat security context - examples/simpleWebapp/
This is a sample web application where the federation plugin is configured and makes use of security constraints and the Servlet Security API.
This module is described in section "Build and deploy the federation sample application".
Run mvn clean install in each module to build the jar file.
After the build, please follow these steps to deploy and configure the federation plugin.
1) Create sub-directory fediz in ${catalina.home}/lib
2) Update calatina.properties in ${catalina.home}/conf
add the previously created directory to the common loader:
common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,${catalina.home}/lib/fediz/*.jar
3) Deploy the built libraries and dependencies to the directory created in (1)
The built libraries and their dependencies can be found in the zip file located in fediz-tomcat/target/...zip-with-dependencies.zip
4) Configure Federation plugin
The current release of the federation plugin requires to configure the FederationAuthenticator which is configured like any other Valve as described here.
You can either configure the context in the server.xml or in META-INF/context.xml as part of your WAR file.
server.xml
<Context path="/fedizhelloworld" docBase="fedizhelloworld">
<Valve className="org.apache.cxf.fediz.tomcat.FederationAuthenticator"
issuerURL="https://localhost:9443/fedizidp/"
truststoreFile="conf/stsstore.jks"
truststorePassword="stsspass"
trustedIssuer=".*CN=www.sts.com.*" />
</Context>
META-INF/context.xml
<Context>
<Valve className="org.apache.cxf.fediz.tomcat.FederationAuthenticator"
issuerURL="https://localhost:9443/fedizidp/"
truststoreFile="conf/stsstore.jks"
truststorePassword="stsspass"
trustedIssuer=".*CN=www.sts.com.*" />
</Context>
The attribute issuerURL tells the plugin where to redirect unauthenticated requests which access a protected resource (security constraint matches URI pattern).
The current release of the federation plugin supports SAML 1.1/2.0 tokens. The SAML token is signed to provide a way to establish a trust. The federation plugin must validated the SAML token. The validation process includes verifying whether the certificate has been issued by a trusted CA and whether the certificate subject is trusted. The certificate subject identifies the IDP/STS.
You can have more than one IDP/STS in your company. As soon as you grant B2B partners access (internet) to your web application you have at least 2 IDP/STS instances. Usually, you create a chain of IDP instances where the RP trusts only the internal IDP/STS instance and the internal IDP (so called Relying Party IDP) trusts the external IDP. This scenario is addressed in one of the next blogs.
The attribute truststoreFile tells the plugin where the truststore is located (Java Keystore format) and the password is configured in the attribute truststorePassword. The trusted IDP/STS is configured as a regular expression in the attribute trustedIssuer.
It's not yet possible to configure a custom security token validator.
5) Configure the CA certificates
If you use the STS as described here you can copy the keystore from fediz-idp-sts/src/test/resources/stsstore.jks to the configured location in the attribute truststoreFile.
(you can ignore the fact in this demo that the private key is contained in this keystore also which must not be the case for production. The certificate is sufficient for signature validation)
Build and deploy the federation sample application
I've chosen the META-INF/context.xml approach to configure the federation plugin for ease of use.
This web application provides three accessible resources:
- index.html
This static page is not secured by a security constraint - secure/test.html
This static page is secured by a security constraint in the web.xml - /secureservlet/fed
This servlet provides information about the authenticated user like username, roles and claims as illustrated in the following picture:
The user and role information can be retrieved using standard J2EE security API. Unfortunately, there is no standard API to retrieve claims information thus the federation plugin provides an extension of the principal which can be accessed as illustrated here:
Principal p = request.getUserPrincipal();
if (p instanceof FederationPrincipal) {
FederationPrincipal fp = (FederationPrincipal)p;
FederationPrincipal fp = (FederationPrincipal)p;
ClaimCollection claims = fp.getClaims();
...
}
Every security constraint must define at least one role in auth-constraint as defined in the Servlet specification. There are use cases where you might want to give access to resources to everybody who is authenticated. Therefore, the plugin can add a default role if no roles are provided as part of the SAML token. If not explicitly configured, the default role name is Authenticated.
Encoding of roles in SAML token
The federation authenticator provides the following attributes to customize where and how the role information is encoded in the SAML token. The role is like any other claim represented within the attribute statement.
The IDP/STS in this example uses the following URI for the role claim:
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role
If your IDP/STS stores the role information in another claim, configure the attribute roleClaimURI in the FederationAuthenticator. The value of the attribute is a string where the list of roles are delimited by a character. The IDP/STS in this example use "," as the default delimiter. If you want to use another delimiter configure the attribute roleDelimiter in the FederationAuthenticator.
SEVERE: Parse error in context.xml for /manager
ReplyDeletejava.lang.ClassNotFoundException: org.apache.fediz.tomcat.FederationAuthenticator
Caused by: java.lang.ClassNotFoundException: org.apache.fediz.tomcat.FederationAuthenticator
Mar 6, 2012 3:31:40 PM org.apache.catalina.startup.ContextConfig processContextConfig
SEVERE: Occurred at line 40 column 44
Mar 6, 2012 3:31:40 PM org.apache.tomcat.util.digester.Digester endElement
WARNING: No rules found matching 'Context/Valve/Context'.
Mar 6, 2012 3:31:40 PM org.apache.catalina.startup.ContextConfig configureStart
SEVERE: Marking this application unavailable due to previous error(s)
Mar 6, 2012 3:31:40 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Error getConfigured
Mar 6, 2012 3:31:40 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [/manager] startup failed due to previous errors
Mar 6, 2012 3:31:40 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory C:\apache-tomcat-7.0.25\tomcat-instance2\webapps\ROOT
Mar 6, 2012 3:31:40 PM org.apache.tomcat.util.digester.Digester startElement
SEVERE: Begin event threw exception
java.lang.ClassNotFoundException: org.apache.fediz.tomcat.FederationAuthenticator
Mar 6, 2012 3:31:40 PM org.apache.catalina.startup.ContextConfig processContextConfig
SEVERE: Parse error in context.xml for
java.lang.ClassNotFoundException: org.apache.fediz.tomcat.FederationAuthenticator
Caused by: java.lang.ClassNotFoundException: org.apache.fediz.tomcat.FederationAuthenticator
Mar 6, 2012 3:31:40 PM org.apache.catalina.startup.ContextConfig processContextConfig
SEVERE: Occurred at line 40 column 44
Mar 6, 2012 3:31:40 PM org.apache.catalina.startup.ContextConfig configureStart
SEVERE: Marking this application unavailable due to previous error(s)
Mar 6, 2012 3:31:40 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Error getConfigured
Mar 6, 2012 3:31:40 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [] startup failed due to previous errors
Mar 6, 2012 3:31:40 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-apr-8282"]
Mar 6, 2012 3:31:40 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-apr-8283"]
Mar 6, 2012 3:31:40 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8222"]
Mar 6, 2012 3:31:40 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-apr-8209"]
Mar 6, 2012 3:31:40 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 11208 ms
when ever I insert this code to the context.xml file , it gives me the above errors.. especially this error
ReplyDeletejava.lang.ClassNotFoundException: org.apache.fediz.tomcat.FederationAuthenticator
where am i suppose to get this class?
META-INF/context.xml
I haven't updated the classname on this blog - only the example. The correct class name is: org.apache.cxf.fediz.tomcat.FederationAuthenticator
ReplyDeletewill update this now. Thanks for the hint.
HTTP Status 403 - Requesting security token failed
ReplyDeletetype Status report
message Requesting security token failed
description Access to the specified resource (Requesting security token failed) has been forbidden
https://localhost:8222/fedizidp/?wa=wsignin1.0&wreply=http%3A%2F%2Flocalhost%3A8282%2Fmanager%2Fhtml&wtrealm=http%3A%2F%2Flocalhost%3A8282%2Fmanager%2F
how do i pass this stage , because Class Not Found Exception is ok now , the web page is complaining about the certificate
Thanks a lot
The Federation plugin is called and the redirect to the IDP triggered.
DeleteCould you please raise this with the CXF user list (http://cxf.apache.org/mailing-lists.html) as it is much easier to attach log files?
Could you send me the logfile of both tomcat instances?
The browser makes the following checks when establishing an HTTPS connection:
- certificate of server (self-signed) or the CA certificate must be in the truststore of the browser
- verifies whether the subject CN of the certificate matchs with the hostname of the Url
- the certificate must be valid
Otherwise, the browser shows a warning message.
i'm not sure if you have seen it, but i have posted it .......
ReplyDeletehttp://cxf.547215.n5.nabble.com/HTTP-Status-403-Requesting-security-token-failed-td5543684.html
I've prepared a zip file which contains two tomcat instances:
ReplyDelete- tomcat-idp
- tomcat-rp (contains the application)
You can download it here:
https://docs.google.com/open?id=0B39bWm6JgpkfMDZDVkFZemdTX202YlVWM2xMUjEwdw
After starting the two tomcat instances, open a browser and enter the following url:
https://localhost:8443/fedizhelloworld/secureservlet/fed
The following usernames are configured:
user: alice password:ecila
user: bob password:bob
user: ted password:det
when I enter this URL https://localhost:8443/fedizhelloworld/secureservlet/fed, it says
ReplyDeleteThe server localhost:9443 requires a username and password
The server says :IDP
and I have tried the configured usernames and passwords
user: alice password:ecila
user: bob password:bob
user: ted password:det
but it returns HTTP Status 403 - Requesting security token failed
I want to have different services such that I’m able to use single sign on across all the services using certificate
ReplyDeleteNot as In the case of SAML Sender-Vouches, where there is one security (trust) domain