Tuesday, October 14, 2014

Using JAAS with Apache CXF

Apache CXF supports a wide range of tokens for authentication (SAML, UsernameTokens, Kerberos, etc.), and also offers different ways of authenticating these tokens. A standard way of authenticating a received token is to use a JAAS LoginModule. This article will cover some of the different ways you can configure JAAS in CXF, and some of the JAAS LoginModules that are available.

1) Configuring JAAS in Apache CXF

There are a number of different ways to configure your CXF web service to authenticate tokens via JAAS. For all approaches, you must define the System property "java.security.auth.login.config" to point towards your JAAS configuration file.

1.1) JAASLoginInterceptor

CXF provides a interceptor called the JAASLoginInterceptor that can be added either to the "inInterceptor" chain of an endpoint (JAX-WS or JAX-RS) or a CXF bus (so that it applies to all endpoints). The JAASLoginInterceptor typically authenticates a Username/Password credential (such as a WS-Security UsernameToken or HTTP/BA) via JAAS. Note that for WS-Security, you must tell WSS4J not to authenticate the UsernameToken itself, but just to process it and store it for later authentication via the JAASLoginInterceptor. This is done by setting the JAX-WS property "ws-security.validate.token" to "false".

At a minimum it is necessary to set the "contextName" attribute of the JAASLoginInterceptor, which references the JAAS Context Name to use. It is also possible to define how to retrieve roles as part of the authentication process, by default CXF assumes that javax.security.acl.Group Objects are interpreted as "role" Principals. See the CXF wiki for more information on how to configure the JAASLoginInterceptor. After successful authentication, a CXF SecurityContext Object is created with the name and roles of the authenticated principal.

1.2) JAASAuthenticationFeature

Newer versions of CXF also have a CXF Feature called the JAASAuthenticationFeature. This simply wraps the JAASLoginInterceptor with default configuration for Apache Karaf. If you are deploying a CXF endpoint in Karaf, you can just add this Feature to your endpoint or Bus without any additional information, and CXF will authenticate the received credential to whatever Login Modules have been configured for the "karaf" realm in Apache Karaf.

1.3) JAASUsernameTokenValidator

As stated above, it is possible to validate a WS-Security UsernameToken in CXF via the JAASLoginInterceptor or the JAASAuthenticationFeature by first setting the JAX-WS property "ws-security.validate.token" to "false". This tells WSS4J to avoid validating UsernameTokens. However it is possible to also validate UsernameTokens using JAAS directly in WSS4J via the JAASUsernameTokenValidator. You can configure this validator when using WS-SecurityPolicy via the JAX-WS property "ws-security.ut.validator".

2) Using JAAS LoginModules in Apache CXF

Once you have decided how you are going to configure JAAS in Apache CXF, it is time to pick a JAAS LoginModule that is appropriate for your authentication requirements. Here are some examples of LoginModules you can use.

2.1) Validating a Username + Password to LDAP / Active Directory

For validating a Username + Password to an LDAP / Active Directory backend, use one of the following login modules:
  • com.sun.security.auth.module.LdapLoginModule: Example here (context name "sun").
  • org.eclipse.jetty.plus.jaas.spi.LdapLoginModule: Example here (context name "jetty"). Available via the org.eclipse.jetty/jetty-plus dependency. This login module is useful as it's easy to retrieve roles associated with the authenticated user.
2.2) Validating a Kerberos token

Kerberos tokens can be validated via:
  • com.sun.security.auth.module.Krb5LoginModule: Example here.
2.3) Apache Karaf specific LoginModules

Apache Karaf contains some LoginModules that can be used when deploying your application in Karaf:
  • org.apache.karaf.jaas.modules.properties.PropertiesLoginModule: Authenticates Username + Passwords and retrieves roles via "etc/users.properties".
  • org.apache.karaf.jaas.modules.properties.PublickeyLoginModule: Authenticates SSH keys and retrieves roles via "etc/keys.properties".
  • org.apache.karaf.jaas.modules.properties.OsgiConfigLoginModule: Authenticates Username + Passwords and retrieves roles via the OSGi Config Admin service.
  • org.apache.karaf.jaas.modules.properties.LDAPLoginModule: Authenticates Username + Passwords and retrieves roles from an LDAP backend.
  • org.apache.karaf.jaas.modules.properties.JDBCLoginModule:  Authenticates Username + Passwords and retrieves roles from a database.
  • org.apache.karaf.jaas.modules.properties.SyncopeLoginModule: Authenticates Username + Passwords and retrieves roles via the Apache Syncope IdM.
See Jean-Baptiste Onofré's excellent blog for a description of how to set up and test the SyncopeLoginModule. Note that it is also possible to use this LoginModule in other containers, see here for an example.

1 comment:

  1. Wow... this looks frighteningly similar to stuff I did back in... 2007 to hook up an app running in Tomcat to our campus Kerberos domain. http://wiki.wsmoak.net/cgi-bin/wiki.pl?TomcatKerberos I wonder, did the JAAS spec ever get finalized?