123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- [[servlet-jaas]]
- = Java Authentication and Authorization Service (JAAS) Provider
- Spring Security provides a package to delegate authentication requests to the Java Authentication and Authorization Service (JAAS).
- This section discusses that package.
- [[jaas-abstractjaasauthenticationprovider]]
- == AbstractJaasAuthenticationProvider
- The `AbstractJaasAuthenticationProvider` class is the basis for the provided JAAS `AuthenticationProvider` implementations.
- Subclasses must implement a method that creates the `LoginContext`.
- The `AbstractJaasAuthenticationProvider` has a number of dependencies that can be injected into it, as discussed in the remainder of this section.
- [[jaas-callbackhandler]]
- === JAAS CallbackHandler
- Most JAAS `LoginModule` instances require a callback of some sort.
- These callbacks are usually used to obtain the username and password from the user.
- In a Spring Security deployment, Spring Security is responsible for this user interaction (through the authentication mechanism).
- Thus, by the time the authentication request is delegated through to JAAS, Spring Security's authentication mechanism has already fully populated an `Authentication` object that contains all the information required by the JAAS `LoginModule`.
- Therefore, the JAAS package for Spring Security provides two default callback handlers: `JaasNameCallbackHandler` and `JaasPasswordCallbackHandler`.
- Each of these callback handlers implements `JaasAuthenticationCallbackHandler`.
- In most cases, these callback handlers can be used without understanding the internal mechanics.
- For those needing full control over the callback behavior, `AbstractJaasAuthenticationProvider` internally wraps these `JaasAuthenticationCallbackHandler` instances with an `InternalCallbackHandler`.
- The `InternalCallbackHandler` is the class that actually implements the JAAS normal `CallbackHandler` interface.
- Any time that the JAAS `LoginModule` is used, it is passed a list of application contexts configured `InternalCallbackHandler` instances.
- If the `LoginModule` requests a callback against the `InternalCallbackHandler` instances, the callback is, in turn, passed to the `JaasAuthenticationCallbackHandler` instances being wrapped.
- [[jaas-authoritygranter]]
- === JAAS AuthorityGranter
- JAAS works with principals.
- Even "`roles`" are represented as principals in JAAS.
- Spring Security, on the other hand, works with `Authentication` objects.
- Each `Authentication` object contains a single principal and multiple `GrantedAuthority` instances.
- To facilitate mapping between these different concepts, Spring Security's JAAS package includes an `AuthorityGranter` interface.
- An `AuthorityGranter` is responsible for inspecting a JAAS principal and returning a set of `String` objects that represent the authorities assigned to the principal.
- For each returned authority string, the `AbstractJaasAuthenticationProvider` creates a `JaasGrantedAuthority` (which implements Spring Security's `GrantedAuthority` interface) that contains the authority string and the JAAS principal that the `AuthorityGranter` was passed.
- The `AbstractJaasAuthenticationProvider` obtains the JAAS principals by first successfully authenticating the user's credentials by using the JAAS `LoginModule` and then accessing the `LoginContext` it returns.
- A call to `LoginContext.getSubject().getPrincipals()` is made, with each resulting principal passed to each `AuthorityGranter` defined against the `AbstractJaasAuthenticationProvider.setAuthorityGranters(List)` property.
- Spring Security does not include any production `AuthorityGranter` instances, given that every JAAS principal has an implementation-specific meaning.
- However, there is a `TestAuthorityGranter` in the unit tests that demonstrates a simple `AuthorityGranter` implementation.
- [[jaas-defaultjaasauthenticationprovider]]
- == DefaultJaasAuthenticationProvider
- The `DefaultJaasAuthenticationProvider` lets a JAAS `Configuration` object be injected into it as a dependency.
- It then creates a `LoginContext` by using the injected JAAS `Configuration`.
- This means that `DefaultJaasAuthenticationProvider` is not bound to any particular implementation of `Configuration`, as `JaasAuthenticationProvider` is.
- [[jaas-inmemoryconfiguration]]
- === InMemoryConfiguration
- To make it easy to inject a `Configuration` into `DefaultJaasAuthenticationProvider`, a default in-memory implementation named `InMemoryConfiguration` is provided.
- The implementation constructor accepts a `Map` where each key represents a login configuration name, and the value represents an `Array` of `AppConfigurationEntry` instances.
- `InMemoryConfiguration` also supports a default `Array` of `AppConfigurationEntry` objects that is used if no mapping is found within the provided `Map`.
- For details, see the Javadoc of javadoc:org.springframework.security.authentication.jaas.memory.InMemoryConfiguration[].
- [[jaas-djap-config]]
- === DefaultJaasAuthenticationProvider Example Configuration
- While the Spring configuration for `InMemoryConfiguration` can be more verbose than the standard JAAS configuration files, using it in conjunction with `DefaultJaasAuthenticationProvider` is more flexible than `JaasAuthenticationProvider`, since it not dependent on the default `Configuration` implementation.
- The next example provides a configuration of `DefaultJaasAuthenticationProvider` that uses `InMemoryConfiguration`.
- Note that custom implementations of `Configuration` can easily be injected into `DefaultJaasAuthenticationProvider` as well.
- [source,xml]
- ----
- <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>
- <!--
- SPRINGSECURITY is the default loginContextName
- for AbstractJaasAuthenticationProvider
- -->
- <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>
- <!-- You will need to write your own implementation of AuthorityGranter -->
- <bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
- </list>
- </property>
- </bean>
- ----
- [[jaas-jaasauthenticationprovider]]
- == JaasAuthenticationProvider
- The `JaasAuthenticationProvider` assumes that the default `Configuration` is an instance of https://docs.oracle.com/javase/8/docs/jre/api/security/jaas/spec/com/sun/security/auth/login/ConfigFile.html[`ConfigFile`].
- This assumption is made in order to try to update the `Configuration`.
- The `JaasAuthenticationProvider` then uses the default `Configuration` to create the `LoginContext`.
- Assume that we have a JAAS login configuration file, `/WEB-INF/login.conf`, with the following contents:
- [source,txt]
- ----
- JAASTest {
- sample.SampleLoginModule required;
- };
- ----
- Like all Spring Security beans, the `JaasAuthenticationProvider` is configured through the application context.
- The following definitions would correspond to the above JAAS login configuration file:
- [source,xml]
- ----
- <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>
- ----
- [[jaas-apiprovision]]
- == Running as a Subject
- If configured, the `JaasApiIntegrationFilter` tries to run as the `Subject` on the `JaasAuthenticationToken`.
- This means that the `Subject` can be accessed using:
- [source,java]
- ----
- Subject subject = Subject.getSubject(AccessController.getContext());
- ----
- You can configure this integration by using the xref:servlet/appendix/namespace/http.adoc#nsa-http-jaas-api-provision[jaas-api-provision] attribute.
- This feature is useful when integrating with legacy or external API's that rely on the JAAS Subject being populated.
|