Spring Security provides a package that can delegate authentication requests to the Java Authentication and Authorization Service (JAAS). This package is described in detail below.
AbstractJaasAuthenticationProvider
AbstractJaasAuthenticationProvider
is the basis for the provided AuthenticationProvider
implementations in JAAS. Subclasses must implement a method that creates a LoginContext
. AbstractJaasAuthenticationProvider
has a number of dependencies that can be injected into it, which are described below.
JAAS CallbackHandler
Most LoginModule
from JAAS require some type of callback. These callbacks are typically used to retrieve
the username and password from the user.
When deployed using Spring Security, Spring Security is responsible for this user interaction (via an authentication
mechanism). Thus, by the time the authentication request is passed to JAAS, the Spring Security authentication
mechanism will have already completely populated the Authentication
object containing all the
information required by the LoginModule
from JAAS.
The JAAS package for Spring Security therefore contains two standard callback handlers,
JaasNameCallbackHandler
and JaasPasswordCallbackHandler
. Each of these callback handlers
implements JaasAuthenticationCallbackHandler
. In most cases, these callback handlers can simply be used
without having to understand their internal mechanics.
For those who require full control over the callback logic, the AbstractJaasAuthenticationProvider
internally wraps these JaasAuthenticationCallbackHandler
instances with
InternalCallbackHandler
. InternalCallbackHandler
is a class that actually implements the
regular CallbackHandler
interface from JAAS. Each time a LoginModule
is used from JAAS, it
is passed a list of InternalCallbackHandler
instances configured in the application context. If LoginModule
requests a callback for InternalCallbackHandlers
, the callback is in turn passed to the wrapped
instances of JaasAuthenticationCallbackHandler
.
JAAS Authority Granter
JAAS works with principals. In JAAS, even "roles" are represented as principals. Spring Security, on the other hand,
works with Authentication
objects. Each Authentication
object contains one principal and
multiple GrantedAuthority
s. To make it easier to map between these different concepts, the JAAS package
in Spring Security contains the AuthorityGranter
interface.
The AuthorityGranter
is responsible for validating the JAAS principal and returns a set of
String
representing the authority granted to the principal. For each permission string returned, the
AbstractJaasAuthenticationProvider
creates a JaasGrantedAuthority
(which implements the
GrantedAuthority
interface from Spring Security) containing the authority string and the JAAS principal
that was passed AuthorityGranter
. The AbstractJaasAuthenticationProvider
obtains the JAAS
principals by first successfully authenticating the user's credentials using the LoginModule
from JAAS,
and then accessing the returned LoginContext
. A call to
LoginContext.getSubject().getPrincipals()
is made, and each principal received is passed to each AuthorityGranter
defined in the AbstractJaasAuthenticationProvider.setAuthorityGranters(List)
.
Spring Security does not contain any production AuthorityGranters
because each JAAS principal has an
implementation-specific value. However, unit tests have a TestAuthorityGranter
that clearly
demonstrates how a simple AuthorityGranter
implementation works.
DefaultJaasAuthenticationProvider
The DefaultJaasAuthenticationProvider
allows you to inject a JAAS Configuration
object into
it as a dependency. It then creates a LoginContext
using the injected Configuration
from
JAAS. This means that DefaultJaasAuthenticationProvider
is not bound to a specific
Configuration
implementation like JaasAuthenticationProvider
is.
InMemoryConfiguration
To make it easier to implement Configuration
in the DefaultJaasAuthenticationProvider
,
there is an in-memory implementation called InMemoryConfiguration
by default. The implementation
constructor takes a Map
in which each key represents a login configuration name and the value is a
Array
consisting of an AppConfigurationEntry
. InMemoryConfiguration
also
supports a standard Array
consisting of AppConfigurationEntry
objects, which will be used
if no mapping is found in the specified Map
. For details, refer to the class-level javadoc on InMemoryConfiguration
.
DefaultJaasAuthenticationProvider configuration example
Although the Spring configuration for InMemoryConfiguration
can be more crowded than standard JAAS
configuration files, using it in combination with the DefaultJaasAuthenticationProvider
is more
flexible than using the JaasAuthenticationProvider
, since it does not depend on the standard
implementation of Configuration
.
The following is an example of a DefaultJaasAuthenticationProvider
configuration using InMemoryConfiguration
.
Please note that custom implementations of Configuration
can easily be implemented in DefaultJaasAuthenticationProvider
.
<bean id="jaasAuthProvider"
class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
<property name="configuration">
<bean class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
<constructor-arg>
<map>
<entry key="SPRINGSECURITY">
<array>
<bean class="javax.security.auth.login.AppConfigurationEntry">
<constructor-arg value="sample.SampleLoginModule" />
<constructor-arg>
<util:constant static-field=
"javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED"/>
</constructor-arg>
<constructor-arg>
<map></map>
</constructor-arg>
</bean>
</array>
</entry>
</map>
</constructor-arg>
</bean>
</property>
<property name="authorityGranters">
<list>
<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
</list>
</property>
</bean>
JaasAuthenticationProvider
JaasAuthenticationProvider
assumes that the default Configuration
is an instance of ConfigFile. This assumption is made in order to attempt to update Configuration
.
The JaasAuthenticationProvider
then uses the standard Configuration
to create a LoginContext
.
Suppose we have a JAAS login configuration file, /WEB-INF/login.conf
, with the following content:
JAASTest {
sample.SampleLoginModule required;
};
Like all Spring Security beans, JaasAuthenticationProvider
is configured through the application
context. The following definitions will match the login JAAS configuration file above:
<bean id="jaasAuthenticationProvider"
class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
<property name="loginConfig" value="/WEB-INF/login.conf"/>
<property name="loginContextName" value="JAASTest"/>
<property name="callbackHandlers">
<list>
<bean
class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
<bean
class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"/>
</list>
</property>
<property name="authorityGranters">
<list>
<bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
</list>
</property>
</bean>
Run as Subject
JaasApiIntegrationFilter
- if added to the configuration - will try to execute as Subject
for JaasAuthenticationToken
. This means that Subject
can be accessed with:
Subject subject = Subject.getSubject(AccessController.getContext());
This integration can be easily configured using the jaas-api-provision attribute. This feature is useful when integrating with legacy or external APIs that rely on JAAS entity population.