About

This module enables support for Spring security for the Across based application. The standard Spring security filter chain and method security annotation processors will be registered automatically if this module is present.

1. General information

1.1. Artifact

<dependencies>
    <dependency>
        <groupId>com.foreach.across.modules</groupId>
        <artifactId>spring-security-module</artifactId>
        <version>2.0.1.RELEASE</version>
    </dependency>
</dependencies>

1.2. Module dependencies

Module Type Description

AcrossHibernateJpaModule

extension

Creates the AuditableEntityInterceptor bean.

1.3. Module settings

SpringSecurityModule does not have any settings.

1.4. Cache configuration

SpringSecurityModule uses the following caches:

Name Description

securityPrincipalCache
(SpringSecurityModuleCache.SECURITY_PRINCIPAL)

Caches SecurityPrincipal instances by principal name. Used by the default SecurityPrincipalService.

2. What’s new in this version?

2.0.1.RELEASE

Minor bugfixes.

2.0.0.RELEASE

Requires Across 2.0.0+.

1.1.0.RELEASE

SecurityPrincipalService#authenticate() now returns a Closeable instance.

1.0.0.RELEASE

Initial public release available on Maven central.

3. Module configuration

The SpringSecurityModule registers 2 separate modules. The SpringSecurityInfrastructureModule provides the SecurityPrincipal infrastructure as early as possible during the bootstrap phase. The SpringSecurityModule itself is responsible for registering the security filters. Only the SpringSecurityModule should be manually added to the AcrossContext, the infrastructure module will be added automatically.

4. Configuring web security

The SpringSecurityModule enables support for SpringSecurityWebConfigurer implementations to be provided by different modules. Usually this is done by implementing your own SpringSecurityWebConfigurerAdapter. Every SpringSecurityWebConfigurerAdapter results in a separate request filter to be added to the Spring security filter chain. Once a request has been handled by a filter, all remaining filters will be skipped.

For this reason it is vital that SpringSecurityWebConfigurerAdapter instances are added in the correct order and are correctly scoped to the subset of requests they are meant for. The SpringSecurityModule respects all bean ordering rules that Across provides: using the module order by default and allowing the use of @Order, @OrderInModule or their respective interfaces.

Note
Spring security itself allows very advanced configuration and customization. Please refer to the official Spring security documentation for more details.

4.1. Debugging SpringSecurityWebConfigurer ordering

If you want to trace the different configurers that are being applied, you should enable DEBUG logging for class com.foreach.across.modules.spring.security.config.AcrossWebSecurityConfiguration. This will output the different configurer beans in the order they will be applied, along with their type, bean and module name (if available).

5. SecurityPrincipal abstraction

The SpringSecurityModule provides an additional abstraction layer on top of the standard Authentication in the form of the SecurityPrincipal interface. Other modules like the UserModule and OAuth2Module provide an implementation of the SecurityPrincipal concept.

Since SecurityPrincipal is a relatively straightforward interface, a principal can be pretty much anything (user, group, machine…​). The only requirement is that every SecurityPrincipal has a unique principal name that identifies it.

Several beans are available for interacting with the current security principal:

Type Description

SecurityPrincipalService

Allows you to fetch any SecurityPrincipal by its unique principal name using a backing SecurityPrincipalRetrievalStrategy. Also provides some helper methods to quickly authenticate or de-authenticate a principal.

CurrentSecurityPrincipalProxy

Proxies the current security principal (if there is one). Allows authority checking from anywhere in your code using the hasAuthority(String) method.

The SpringSecurityAclModule wires a CurrentAclSecurityPrincipalProxy instead that provides additional methods to check for ACL permissions.

Example of using the SecurityPrincipalService to authenticate a principal
// execute a section within the scope of an authenticated SecurityPrincipal,
// when the block closes the previous authentication will be reset
try ( CloseableAuthentication authenticatedBlock
                    = securityPrincipalService.authenticate( principal ) ) {
    // do something
}

5.1. SecurityPrincipalRetrievalStrategy

The default SecurityPrincipalService uses a backing SecurityPrincipalRetrievalStrategy to fetch the actual principal based on its unique name. If you want to define your own custom implementation you can do so by replacing the strategy implementation, see the javadoc and source code for more information.

5.2. SecurityPrincipal caching

The default SecurityPrincipalService uses the securityPrincipalCache for retrieving principal instances. If the cache does not return an instance, the request is delegated to the the SecurityPrincipalRetrievalStrategy. Actually maintaining the cache however is left to the implementation providers, the default SecurityPrincipalService only caches null values (principal not found). Examples can be found in SecurityPrincipal providing modules, for example UserModule.

5.3. SecurityPrincipalLabelResolver

Any module can define one or more SecurityPrincipalLabelResolver beans. These are used to generate a pretty label for a given SecurityPrincipal instance. SecurityPrincipalLabelResolver instances are ordered and the first resolver to return a valid label will be used.

SecurityPrincipalLabelResolver beans should not be used directly but through the exposed SecurityPrincipalLabelResolverStrategy.

Note
It is a best practice to provide a SecurityPrincipalLabelResolver for every SecurityPrincipal implementation your module provides. The resolver beans do not need to be exposed.

6. AllowableActions

SpringSecurityModule also provides an AllowableActions construct that can easily be used to define a set of actions that can be performed on an item. The purpose is for code to check if an action is present in the AllowableActions collection, meaning that the action can be performed. This helps decoupling your business code from the specifics of the security layer and can be supported in both an ACL and non-ACL context.

A single AllowableAction is identified by a unique string, making it very easy to extend. Useful implementations can be found in the com.foreach.across.modules.spring.security.actions package. The AuthorityMatchingAllowableActions maps AllowableAction on AuthorityMatcher and provides concrete implementation supporting both Authentication and SecurityPrincipal.

Actions can be mapped against anything (most likely authorities or ACL permissions) and can also be completely different depending on the target they need to be applied to. This allows for as much granularity you might want, without having to change your permission model.

Example of mapping AllowableActions against GrantedAuthorities
@Autowired
private CurrentSecurityPrincipalProxy currentPrincipal;

public AllowableActions createAllowableActionsForCurrentSecurityPrincipal() {
    Map<AllowableAction, AuthorityMatcher> actionAuthorityMatcherMap = new HashMap<>();
    actionAuthorityMatcherMap.put( AllowableAction.READ, AuthorityMatcher.allOf( "read items" ) );
    actionAuthorityMatcherMap.put( AllowableAction.UPDATE, AuthorityMatcher.allOf( "write items" ) );

    return AuthorityMatchingAllowableActions.forSecurityPrincipal( currentPrincipal, actionAuthorityMatcherMap )
}
Tip
Use the AllowableAction concept to hide specifics of the security permission layer.

7. AuditableEntityInterceptor

If the AcrossHibernateJpaModule is present in the Across context, an AuditableEntityInterceptor bean will be created. Any entity implementing the com.foreach.across.modules.hibernate.business.Auditable interface will get its auditing properties updated before it is persisted.