How CoSec Handles Reactive Authorization Flows in Spring WebFlux
TLDR: CoSec implements reactive authorization flows using Spring WebFlux and Project Reactor, where ReactiveAuthorizationFilter delegates to ReactiveSecurityFilter.filterInternal to parse requests and return non-blocking Mono<AuthorizeResult> decisions through a fully asynchronous pipeline.
CoSec is a cloud-native security framework designed for high-performance reactive applications. Understanding how CoSec authorization reactive flows work is essential for building scalable, non-blocking security layers on Spring WebFlux. The framework ensures that every security check—from token parsing to policy evaluation—operates without blocking threads.
The Reactive Authorization Architecture
CoSec's reactive stack leverages Spring WebFlux and Project Reactor to ensure zero thread-blocking during security decisions. The entire pipeline returns reactive types, allowing the framework to handle thousands of concurrent connections with minimal resource consumption.
Entry Point - ReactiveAuthorizationFilter
The flow begins at ReactiveAuthorizationFilter, a standard WebFilter implementation located in cosec-webflux/src/main/kotlin/me/ahoo/cosec/webflux/ReactiveAuthorizationFilter.kt. This filter intercepts every HTTP request entering the WebFlux chain and delegates to the shared security logic.
class ReactiveAuthorizationFilter(...) : WebFilter {
override fun filter(exchange, chain): Mono<Void> =
filterInternal(exchange) { serverExchange, request ->
chain.filter(serverExchange)
}
}
Request Parsing and Security Context Extraction
Inside ReactiveSecurityFilter.filterInternal at cosec-webflux/src/main/kotlin/me/ahoo/cosec/webflux/ReactiveSecurityFilter.kt, the framework performs two critical operations. First, RequestParser transforms the ServerWebExchange into a CoSec Request object. Second, SecurityContextParser extracts authentication details from the request headers.
If token verification fails with a TokenVerificationException, the system gracefully falls back to an anonymous SimpleSecurityContext rather than terminating the reactive flow.
Non-Blocking Authorization Decisions
The core authorization logic resides in the Authorization functional interface at cosec-api/src/main/kotlin/me/ahoo/cosec/api/authorization/Authorization.kt. This interface defines a single method that returns a Mono<AuthorizeResult>:
authorization.authorize(request, securityContext) // returns Mono<AuthorizeResult>
This non-blocking call allows the framework to defer the decision until underlying data sources—such as databases, caches, or external policy engines—respond asynchronously.
Processing Authorization Results
The Mono<AuthorizeResult> undergoes transformation via flatMap operations within ReactiveSecurityFilter. The framework handles three distinct outcomes:
- Allowed: When
authorizeResult.authorized == true, the filter enriches the exchange with the security principal viasecurityContext.principal.toMono()and continues the chain usingchain.filter(serverExchange). - Denied: For unauthorized access, the filter sets HTTP status codes (
401for unauthenticated,403for forbidden) and writes a JSON response body containing theAuthorizeResult. - Rate Limiting: On
TooManyRequestsException, the filter returns HTTP 429 usingwriteWithAuthorizeResult(AuthorizeResult.TOO_MANY_REQUESTS).
Core Source Files and Components
Understanding the reactive authorization flow requires familiarity with these key source files:
-
ReactiveAuthorizationFilter(cosec-webflux/src/main/kotlin/me/ahoo/cosec/webflux/ReactiveAuthorizationFilter.kt): The WebFlux entry filter that triggers the security pipeline. -
ReactiveSecurityFilter(cosec-webflux/src/main/kotlin/me/ahoo/cosec/webflux/ReactiveSecurityFilter.kt): Contains shared logic for parsing, token verification, and result handling. Lines 89-94 implementServerHttpResponse.writeWithAuthorizeResultfor JSON serialization. -
Authorization(cosec-api/src/main/kotlin/me/ahoo/cosec/api/authorization/Authorization.kt): The functional interface defining the contract for authorization providers. -
TracingAuthorization(cosec-opentelemetry/src/main/kotlin/me/ahoo/cosec/opentelemetry/TracingAuthorization.kt): A decorator that adds OpenTelemetry tracing around authorization decisions. -
CoSecMonoTrace(cosec-opentelemetry/src/main/kotlin/me/ahoo/cosec/opentelemetry/AuthorizationMono.kt): AMonowrapper that creates and ends OpenTelemetry spans around the reactive authorization call.
Implementing Custom Reactive Authorizers
Developers can extend CoSec's reactive capabilities by implementing the Authorization interface. Because the method returns Mono<AuthorizeResult>, you can integrate asynchronous data sources such as reactive databases or remote policy services.
@Component
class MyReactiveAuthorizer : Authorization {
override fun authorize(request: Request, context: SecurityContext): Mono<AuthorizeResult> {
return policyRepository.findPolicy(request.path, context.principal.id)
.map { policy ->
if (policy.allows(request.action)) AuthorizeResult.ALLOW
else AuthorizeResult.EXPLICIT_DENY
}
.defaultIfEmpty(AuthorizeResult.IMPLICIT_DENY)
}
}
The framework automatically incorporates custom implementations into the reactive pipeline without blocking threads.
OpenTelemetry Integration for Reactive Streams
CoSec provides optional distributed tracing through the TracingAuthorization decorator. This component wraps the authorization Mono with CoSecMonoTrace, creating OpenTelemetry spans that start when the Mono subscribes and end when it completes or errors.
This integration ensures observability across asynchronous boundaries, allowing developers to trace authorization decisions through complex reactive call chains.
Summary
- CoSec authorization reactive flows begin at
ReactiveAuthorizationFilter, a WebFilter that intercepts all incoming requests. - The
ReactiveSecurityFilter.filterInternalmethod handles request parsing and security context extraction without blocking. - Authorization decisions return
Mono<AuthorizeResult>, enabling fully non-blocking policy evaluation. - Results are processed reactively: allowed requests continue down the chain, while denied requests return appropriate HTTP status codes with JSON bodies.
- Optional OpenTelemetry tracing via
TracingAuthorizationandCoSecMonoTraceprovides visibility into asynchronous authorization operations.
Frequently Asked Questions
What is the entry point for CoSec reactive authorization?
The entry point is ReactiveAuthorizationFilter located in cosec-webflux/src/main/kotlin/me/ahoo/cosec/webflux/ReactiveAuthorizationFilter.kt. This class implements Spring WebFlux's WebFilter interface and intercepts every HTTP request, delegating to ReactiveSecurityFilter.filterInternal to begin the security evaluation.
How does CoSec handle token verification failures in reactive flows?
When SecurityContextParser throws a TokenVerificationException, ReactiveSecurityFilter.filterInternal catches the exception and creates an anonymous SimpleSecurityContext instead of blocking the request. This allows the authorization flow to continue, where the subsequent authorization check will typically deny access with a 401 status if authentication is required.
Can I use CoSec reactive authorization with custom authentication providers?
Yes. Implement the Authorization interface from cosec-api/src/main/kotlin/me/ahoo/cosec/api/authorization/Authorization.kt and return a Mono<AuthorizeResult>. Because the interface is designed for reactive programming, you can integrate with any asynchronous data source, such as reactive Redis, MongoDB, or external HTTP services, without blocking the WebFlux event loop.
How does OpenTelemetry tracing work with CoSec's reactive streams?
CoSec's TracingAuthorization decorator wraps the authorization Mono with CoSecMonoTrace (found in cosec-opentelemetry/src/main/kotlin/me/ahoo/cosec/opentelemetry/AuthorizationMono.kt). This wrapper creates an OpenTelemetry span when the Mono is subscribed and ends it upon completion or error, ensuring distributed traces capture the full latency of asynchronous authorization decisions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →