[[security]]
= Security in Spring Integration

Security is one of the important functions in any modern enterprise (or cloud) application.
Moreover, it is critical for distributed systems, such as those built on Enterprise Integration Patterns.
Messaging independence and loose coupling let target systems communicate with each other with any type of data in the message's `payload`.
We can either trust all those messages or secure our service against "`infecting`" messages.

NOTE: Starting with version `6.3` the whole `spring-integration-security` module is removed in favor of an API proposed by the more common `spring-security-messaging` library.

[[securing-channels]]
== Securing channels

To secure message channels in the integration flow, an `AuthorizationChannelInterceptor` has to be added to those channels, or it can be configured as a global channel interceptor with respective pattern:

[tabs]
======
Java::
+
[source, java, role="primary"]
----
@Bean
@GlobalChannelInterceptor(patterns = "secured*")
AuthorizationChannelInterceptor authorizationChannelInterceptor() {
    return new AuthorizationChannelInterceptor(AuthorityAuthorizationManager.hasAnyRole("ADMIN", "PRESIDENT"));
}
----

XML::
+
[source, xml, role="secondary"]
----
<channel-interceptor pattern="securedChannel*">
    <beans:bean class="org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor">
        <beans:constructor-arg>
            <beans:bean class="org.springframework.security.authorization.AuthorityAuthorizationManager"
                        factory-method="hasAnyRole">
                <beans:constructor-arg>
                    <beans:array>
                        <beans:value>ADMIN</beans:value>
                        <beans:value>PRESIDENT</beans:value>
                    </beans:array>
                </beans:constructor-arg>
            </beans:bean>
        </beans:constructor-arg>
    </beans:bean>
</channel-interceptor>
----
======

See xref:channel/configuration.adoc#global-channel-configuration-interceptors[Global Channel Interceptor Configuration] for more information.

[[security-context-propagation]]
== Security Context Propagation

To be sure that our interaction with the application is secure, according to its security system rules, we should supply some security context with an authentication (principal) object.
The Spring Security project provides a flexible, canonical mechanism to authenticate our application clients over HTTP, WebSocket, or SOAP protocols (as can be done for any other integration protocol with a simple Spring Security extension).
It also provides a `SecurityContext` for further authorization checks on the application objects, such as message channels.
By default, the `SecurityContext` is tied to the execution state of the current `Thread` by using the (`ThreadLocalSecurityContextHolderStrategy`).
It is accessed by an AOP (Aspect-oriented Programming) interceptor on secured methods to check (for example) whether that `principal` of the invocation has sufficient permissions to call that method.
This works well with the current thread.
Often, though, processing logic can be performed on another thread, on several threads, or even on external systems.

Standard thread-bound behavior is easy to configure if our application is built on the Spring Integration components and its message channels.
In this case, the secured objects can be any service activator or transformer, secured with a
`MethodSecurityInterceptor` in their `<request-handler-advice-chain>` (see xref:handler-advice.adoc[Adding Behavior to Endpoints]) or even `MessageChannel` (see xref:security.adoc#securing-channels[Securing channels], earlier).
When using `DirectChannel` communication, the `SecurityContext` is automatically available, because the downstream flow runs on the current thread.
However, in the cases of the `QueueChannel`, `ExecutorChannel`, and `PublishSubscribeChannel` with an `Executor`, messages are transferred from one thread to another (or several) by the nature of those channels.
In order to support such scenarios, we have two choices:

* Transfer an `Authentication` object within the message headers and extract and authenticate it on the other side before secured object access.
* Propagate the `SecurityContext` to the thread that receives the transferred message.

This is implemented as a `org.springframework.security.messaging.context.SecurityContextPropagationChannelInterceptor` in the `spring-security-messaging` module, which can be added to any `MessageChannel` or configured as a `@GlobalChannelInterceptor`.
The logic of this interceptor is based on the `SecurityContext` extraction from the current thread (from the `preSend()` method) and its populating to another thread from the `postReceive()` (`beforeHandle()`) method.
See the `SecurityContextPropagationChannelInterceptor` Javadocs for more information.

Propagation and population of `SecurityContext` is just one half of the work.
Since the message is not an owner of the threads in the message flow, and the system should be sure that it is secured against any incoming messages, the `SecurityContext` has to be cleaned up from `ThreadLocal`.
The `SecurityContextPropagationChannelInterceptor` provides the `afterMessageHandled()` interceptor method implementation.
It cleans up operation by freeing the thread at the end of invocation from that propagated principal.
This means that, when the thread that processes the handed-off message finishes processing the message (successful or otherwise), the context is cleared so that it cannot inadvertently be used when processing another message.

[NOTE]
====
When working with an xref:jms.adoc#jms-async-gateway[asynchronous gateway], you should use an appropriate `AbstractDelegatingSecurityContextSupport` implementation from Spring Security https://docs.spring.io/spring-security/site/docs/current/reference/html/servlet-webclient.html#concurrency[Concurrency Support], to let security context propagation be ensured over gateway invocation.
The following example shows how to do so:


[source,java]
----
@Configuration
@EnableIntegration
@IntegrationComponentScan
public class ContextConfiguration {

    @Bean
    public AsyncTaskExecutor securityContextExecutor() {
        return new DelegatingSecurityContextAsyncTaskExecutor(
                         new SimpleAsyncTaskExecutor());
    }

}

@MessagingGateway(asyncExecutor = "securityContextExecutor")
public interface SecuredGateway {

    @Gateway(requestChannel = "queueChannel")
    Future<String> send(String payload);

}
----
====
