CoSec Security Extensions: JWT Authentication and OpenTelemetry Observability Explained
CoSec provides modular security extensions that add JWT-based stateless authentication and OpenTelemetry distributed tracing to the core policy engine, enabling comprehensive security observability in JVM applications.
The ahoo-wang/cosec repository delivers a policy-driven authorization framework designed for reactive and servlet-based Java applications. Its CoSec security extensions architecture allows developers to compose specific capabilities—such as JSON Web Token (JWT) verification and OpenTelemetry instrumentation—without bloating the runtime with unused features. These extensions integrate seamlessly with Spring Boot, Spring Cloud Gateway, and standard reactive stacks via interfaces like SecurityContextParser.
JWT Extension: Stateless Token Authentication
The JWT extension implements complete token lifecycle management within the CoSec ecosystem. Located in the cosec-jwt module, it provides classes like me.ahoo.cosec.jwt.Jwts, JwtTokenVerifier, and JwtTokenConverter to handle issuance, signature verification, and principal extraction.
How JWT Authentication Works
When a request arrives with an Authorization: Bearer <token> header, the InjectSecurityContextParser extracts the token and delegates to JwtTokenConverter. This converter uses JwtTokenVerifier to validate signatures (supporting HMAC algorithms like HS256) and map claims to a CoSecPrincipal object containing the subject, tenant ID, and authorities. The principal then feeds into the core AuthorizationService for policy evaluation.
Issuing Signed JWT Tokens
To generate tokens programmatically, use the Jwts builder class as implemented in cosec-jwt/src/main/kotlin/me/ahoo/cosec/jwt/Jwts.kt:
import me.ahoo.cosec.jwt.Jwts
import me.ahoo.cosec.token.TokenAttributes
val attrs = TokenAttributes.builder()
.subject("alice")
.tenantId("demo")
.addAuthority("ROLE_USER")
.expireAfter(3600)
.build()
val secret = "my-super-secret-key".toByteArray()
val token = Jwts.builder()
.setAttributes(attrs)
.signWith(secret)
.compact()
println("Bearer $token")
This creates a compact JWT string signed with the provided secret key, suitable for returning to clients after successful primary authentication.
Verifying Bearer Tokens
For resource servers verifying incoming requests, combine JwtTokenVerifier and JwtTokenConverter as defined in cosec-jwt/src/main/kotlin/me/ahoo/cosec/jwt/JwtTokenVerifier.kt:
import me.ahoo.cosec.jwt.JwtTokenVerifier
import me.ahoo.cosec.jwt.JwtTokenConverter
import me.ahoo.cosec.api.principal.CoSecPrincipal
val secret = "my-super-secret-key".toByteArray()
val verifier = JwtTokenVerifier(secret)
val converter = JwtTokenConverter(verifier)
val authHeader = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
val principal: CoSecPrincipal = converter.parse(authHeader)
The resulting CoSecPrincipal contains the authenticated identity and authorization context required by the policy engine.
OpenTelemetry Extension: Authorization Observability
The OpenTelemetry extension exports coarse-grained authorization traces to any OTLP collector. Implemented in the cosec-opentelemetry module, it uses CoSecInstrumenter and CoSecAttributesExtractor to capture policy evaluation metadata.
Tracing Authorization Decisions
The TracingAuthorization class (from cosec-opentelemetry/src/main/kotlin/me/ahoo/cosec/opentelemetry/TracingAuthorization.kt) wraps the core AuthorizationService. When authorize() is invoked, it creates an OpenTelemetry Span recording the policy name, decision result (PERMIT or DENY), tenant ID, and actor details. The AuthorizationMono utility handles reactive tracing for non-blocking pipelines.
Manual Configuration
To enable tracing programmatically:
import io.opentelemetry.sdk.OpenTelemetrySdk
import io.opentelemetry.sdk.trace.SdkTracerProvider
import me.ahoo.cosec.opentelemetry.TracingAuthorization
import me.ahoo.cosec.core.AuthorizationService
val tracerProvider = SdkTracerProvider.builder().build()
val openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(tracerProvider)
.buildAndRegisterGlobal()
val coreAuth: AuthorizationService = // obtain from container
val tracingAuth = TracingAuthorization(coreAuth)
Spring Boot Configuration
Alternatively, use the starter with YAML configuration:
cosec:
opentelemetry:
enabled: true
jwt:
secret: ${JWT_SECRET}
The CoSecOpenTelemetryAutoConfiguration class (located in cosec-spring-boot-starter/src/main/kotlin/me/ahoo/cosec/spring/boot/starter/opentelemetry/CoSecOpenTelemetryAutoConfiguration.kt) automatically wires the TracingAuthorization bean when cosec.opentelemetry.enabled is true and OpenTelemetry classes are present on the classpath.
Additional Security Extensions
Beyond JWT and OpenTelemetry, CoSec provides several other modular extensions:
- Social Authentication (JustAuth): Integrates OAuth providers like GitHub and Google through
JustAuthProviderandSocialUserConverter, converting social logins into CoSec principals that can optionally flow into JWT tokens. - Spring Boot Starter: The
cosec-spring-boot-startermodule auto-wires all components viaCosecAutoConfiguration, conditionally loading OpenTelemetry beans only whenConditionalOnOpenTelemetryEnabledmatches. - Gateway Filter: The
AuthorizationGatewayFilterenforces policies at the Spring Cloud Gateway layer. Implement it as follows:
import org.springframework.cloud.gateway.filter.GatewayFilterChain
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono
import me.ahoo.cosec.gateway.filter.AuthorizationGatewayFilter
class MyGatewayFilter(
private val authFilter: AuthorizationGatewayFilter
) : GatewayFilter {
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> =
authFilter.filter(exchange, chain)
}
Integration Architecture
The extensions follow a unified request processing pipeline:
- Context Extraction:
SecurityContextParser(JWT or Social) extracts aCoSecPrincipalfrom incoming requests. - Policy Evaluation: The core
AuthorizationServiceevaluates the principal against configured policies. - Observability: When enabled,
TracingAuthorizationcreates OpenTelemetry spans capturing decision metadata viaCoSecAttributesExtractor. - Framework Integration: Spring Boot starters and Gateway filters wire these components into the reactive processing chain without explicit bean configuration.
This modular design ensures that applications only load the bytecode and dependencies they explicitly require, keeping startup times fast while supporting enterprise-grade security patterns.
Summary
- CoSec security extensions provide optional, composable capabilities for JWT authentication and OpenTelemetry observability alongside the core policy engine.
- The JWT extension handles token issuance via
Jwts.builder(), verification throughJwtTokenVerifier, and principal conversion usingJwtTokenConverterlocated incosec-jwt/src/main/kotlin/me/ahoo/cosec/jwt/. - OpenTelemetry integration wraps
AuthorizationServicewithTracingAuthorizationto export authorization spans containing policy decisions and tenant context. - Spring Boot auto-configuration and Gateway filters enable zero-code integration for reactive applications via
CosecAutoConfigurationandAuthorizationGatewayFilter. - All extensions reside in separate modules (e.g.,
cosec-jwt,cosec-opentelemetry) and integrate via standard interfaces likeSecurityContextParserandAuthenticationProvider.
Frequently Asked Questions
How do I enable OpenTelemetry tracing in a CoSec Spring Boot application?
Add the cosec-spring-boot-starter dependency and set cosec.opentelemetry.enabled: true in your application.yml. The CoSecOpenTelemetryAutoConfiguration class automatically creates the TracingAuthorization wrapper and CoSecInstrumenter beans when OpenTelemetry classes are detected on the classpath.
What signing algorithms does the CoSec JWT extension support?
The JWT extension supports HMAC-based algorithms including HS256, as demonstrated in the Jwts.builder().signWith(secret) method implemented in Jwts.kt. The JwtTokenVerifier validates tokens using the same secret key byte array used during issuance.
Can I use CoSec extensions without Spring Boot?
Yes. While the Spring Boot starter provides convenient auto-configuration, you can manually instantiate extension classes like JwtTokenConverter, TracingAuthorization, and AuthorizationGatewayFilter in any JVM application using the core me.ahoo.cosec APIs and reactive programming models.
How does the Gateway filter interact with JWT verification?
The AuthorizationGatewayFilter extracts the Authorization header and delegates to a configured SecurityContextParser (typically the JWT converter via InjectSecurityContextParser). It then calls the AuthorizationService to evaluate policies before allowing the request to proceed to downstream services, effectively enforcing authentication and authorization at the edge.
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 →