1) The STS JAAS LoginModule
The new STS JAAS LoginModule is available in the CXF WS-Security runtime module. It takes a Username and Password from the Callbackhandler passed to the LoginModule, and uses them to create a WS-Security UsernameToken structure. What happens then depends on a configuration setting in the LoginModule.
If the "require.roles" property is set, then the UsernameToken is added to a WS-Trust "Issue" request to the STS, and a "TokenType" attribute is sent in the request (defaults to the standard "SAML2" URI, but can be configured). The client also adds a WS-Trust "Claim" to the request that tells the STS to add the role of the authenticated end user to the request. How the token is added to the WS-Trust request depends on whether the "disable.on.behalf.of" property is set or not. By default, the token is added as an "OnBehalfOf" token in the WS-Trust request. However, if "disable.on.behalf.of" is set to "true", then the credentials are used according to the WS-SecurityPolicy of the STS endpoint. For example, if the policy requires a UsernameToken, then the credentials are added to the security header of the WS-Trust request. If the "require.roles" property is not set, the the UsernameToken is added to a WS-Trust "Validate" request.
The STS validates the received UsernameToken credentials supplied by the end user, and then either creates a token (if the Issue binding was used), or just returns a simple response telling the client whether the validation was successful or not. In the former use-case, the token that is returned is cached meaning that the end user does not have to re-authenticate until the token expires from the cache.
The LoginModule has the following configuration properties:
- require.roles - If this is defined, then the WS-Trust Issue binding is used, passing the value specified for the "token.type" property as the TokenType, and the "key.type" property for the KeyType. It also adds a Claim to the request for the default "role" URI.
- disable.on.behalf.of - Whether to disable passing Username + Password credentials via "OnBehalfOf".
- disable.caching - Whether to disable caching of validated credentials. Default is "false". Only applies when "require.roles" is defined.
- wsdl.location - The location of the WSDL of the STS
- service.name - The service QName of the STS
- endpoint.name - The endpoint QName of the STS
- key.size - The key size to use (if requesting a SymmetricKey KeyType). Defaults to 256.
- key.type - The KeyType to use. Defaults to the standard "Bearer" URI.
- token.type - The TokenType to use. Defaults to the standard "SAML2" URI.
- ws.trust.namespace - The WS-Trust namespace to use. Defaults to the standard WS-Trust 1.3 namespace.
Here is an example of the new JAAS LoginModule configuration:
2) A testcase for the new LoginModule
Using an STS via WS-Trust for authentication and authorization can be quite difficult to set up and understand, but the new LoginModule makes it easy. I created a testcase + uploaded it to github:
- cxf-jaxrs-jaas-sts: This project demonstrates how to use the new STS JAAS LoginModule in CXF to authenticate and authorize a user. It contains a "double-it" module which contains a "double-it" JAX-RS service. It is secured with JAAS at the container level, and requires a role of "boss" to access the service. The "sts" module contains a Apache CXF STS web application which can authenticate users and issue SAML tokens with embedded roles.
- cp double-it/target/cxf-double-it.war ${catalina.home}/webapps
- cp sts/target/cxf-sts.war ${catalina.home}/webapps
- cp double-it/src/main/resources/jaas.conf ${catalina.home}/conf
- export JAVA_OPTS=-Djava.security.auth.login.config=${catalina.home}/conf/jaas.conf
http://localhost:8080/cxf-double-it/doubleit/services/100
Use credentials "alice/security" when prompted. The STS JAAS LoginModule takes the username and password, and dispatches them to the STS for validation.