# How CoSec Handles Authentication: JWT, OAuth2, and Custom Providers

> Discover how CoSec handles authentication using JWT OAuth2 and custom providers. Explore its type-safe interface for transforming credentials into a CoSecPrincipal.

- Repository: [Ahoo Wang/cosec](https://github.com/ahoo-wang/cosec)
- Tags: deep-dive
- Published: 2026-02-23

---

**CoSec handles authentication through a generic, type-safe `Authentication<C, P>` interface that transforms credentials into a `CoSecPrincipal`, supporting JWT tokens, OAuth2 social logins, and custom providers as injectable Spring beans.**

CoSec (Context-Oriented Security) is a policy-based authorization framework for Spring applications that cleanly separates authentication from authorization. Whether you are securing reactive gateways or traditional MVC services, understanding how CoSec handles authentication allows you to integrate JWT validation, social logins, or proprietary credential schemes using the same extensible contract defined in the `cosec-api` module.

## Core Authentication Architecture

The foundation of CoSec authentication is the `Authentication<C, P>` interface located in [`cosec-api/src/main/kotlin/me/ahoo/cosec/api/authentication/Authentication.kt`](https://github.com/ahoo-wang/cosec/blob/main/cosec-api/src/main/kotlin/me/ahoo/cosec/api/authentication/Authentication.kt). This contract is intentionally generic, allowing any credential type (`C`) to be verified and mapped to a principal type (`P`).

### The Authentication Contract

All authentication providers implement the following signature:

```kotlin
interface Authentication<C : Credentials, out P : CoSecPrincipal> {
    val supportCredentials: Class<C>
    fun authenticate(credentials: C): Mono<out P>
}

```

Implementations are **stateless Spring beans**. The framework selects the appropriate provider by matching the `supportCredentials` property to the credential type extracted from the incoming request (e.g., `JwtCredentials`, `SocialCredentials`). This design allows multiple authentication strategies to coexist without coupling.

### Security Context Population

Once a provider successfully authenticates the credentials, it returns a `CoSecPrincipal` containing the user identity and granted authorities. The principal is immediately stored in a `SecurityContext` that downstream components—such as the policy engine and business controllers—access to enforce authorization decisions.

## Built-in Authentication Methods

CoSec provides auto-configuration for two primary authentication mechanisms, controlled via [`application.yml`](https://github.com/ahoo-wang/cosec/blob/main/application.yml) properties.

### JWT Token Authentication

When you provide a signing key, CoSec automatically configures JWT validation. Enable this by setting:

```yaml
cosec:
  authentication:
    jwt:
      secret: <base64-encoded-secret>
      issuer: my-app

```

The `JwtAuthenticationProvider` (located in the `cosec-jwt` module) implements `Authentication<JwtCredentials, CoSecPrincipal>`. It extracts the token from the `Authorization: Bearer <token>` header, validates the signature and claims, and maps the JWT payload to a `CoSecPrincipal`. Because its `supportCredentials` returns `JwtCredentials::class.java`, it is automatically selected for requests containing Bearer tokens.

### Social OAuth2 Authentication

CoSec integrates with JustAuth to provide out-of-the-box support for Google, GitHub, and other OAuth2 providers. This is orchestrated by `CoSecSocialAuthenticationAutoConfiguration` in [`cosec-spring-boot-starter/src/main/kotlin/me/ahoo/cosec/spring/boot/starter/authentication/social/CoSecSocialAuthenticationAutoConfiguration.kt`](https://github.com/ahoo-wang/cosec/blob/main/cosec-spring-boot-starter/src/main/kotlin/me/ahoo/cosec/spring/boot/starter/authentication/social/CoSecSocialAuthenticationAutoConfiguration.kt).

Configure providers in your YAML:

```yaml
cosec:
  authentication:
    social:
      registration:
        google:
          type: google
          client-id: <client-id>
          client-secret: <client-secret>
          redirect-uri: https://my-app.com/oauth/callback/google
        github:
          type: github
          client-id: <client-id>
          client-secret: <client-secret>

```

The flow works as follows:

1. **Auto-configuration** creates a `JustAuthProvider` for each registration and registers them with `SocialProviderManager`.
2. **Login request** redirects to `/oauth/authorize/{provider}`, returning a `SocialCredentials` object containing the authorization code.
3. **Authentication** is handled by `SocialAuthentication` in [`cosec-social/src/main/kotlin/me/ahoo/cosec/social/SocialAuthentication.kt`](https://github.com/ahoo-wang/cosec/blob/main/cosec-social/src/main/kotlin/me/ahoo/cosec/social/SocialAuthentication.kt), which exchanges the code for an access token and fetches the user profile.
4. **Principal conversion** occurs via `SocialUserPrincipalConverter`, transforming the `SocialUser` into a `CoSecPrincipal` for the security context.

## Implementing Custom Authentication Providers

For non-standard requirements—such as API keys or LDAP—you can implement the `Authentication` interface directly. CoSec will automatically detect and register your bean.

```kotlin
@Component
class ApiKeyAuthenticationProvider : Authentication<ApiKeyCredentials, CoSecPrincipal> {
    override val supportCredentials = ApiKeyCredentials::class.java

    override fun authenticate(credentials: ApiKeyCredentials): Mono<CoSecPrincipal> {
        // Validate against database or cache
        return if (isValidKey(credentials.key)) {
            Mono.just(CoSecPrincipal(
                id = credentials.key,
                roles = setOf("API_USER")
            ))
        } else {
            Mono.error(InvalidCredentialsException("Invalid API Key"))
        }
    }
}

```

No additional configuration is required; Spring’s component scanning injects your provider into the authentication chain.

## Request Flow and Filter Integration

Authentication executes early in the request lifecycle, before the policy engine evaluates authorization rules. In reactive applications, `ReactiveAuthorizationFilter` ([`cosec-webflux/src/main/kotlin/me/ahoo/cosec/webflux/ReactiveAuthorizationFilter.kt`](https://github.com/ahoo-wang/cosec/blob/main/cosec-webflux/src/main/kotlin/me/ahoo/cosec/webflux/ReactiveAuthorizationFilter.kt)) intercepts the request. For gateway scenarios, `AuthorizationGatewayFilter` ([`cosec-gateway/src/main/kotlin/me/ahoo/cosec/gateway/AuthorizationGatewayFilter.kt`](https://github.com/ahoo-wang/cosec/blob/main/cosec-gateway/src/main/kotlin/me/ahoo/cosec/gateway/AuthorizationGatewayFilter.kt)) performs the same role.

These filters:

1. Extract credentials from headers or request parameters.
2. Locate the matching `Authentication` bean via `supportCredentials`.
3. Execute `authenticate()` and populate the `SecurityContext`.
4. Proceed to authorization only if authentication succeeds.

Your controllers then access the principal directly:

```kotlin
@RestController
@RequestMapping("/api")
class ProfileController {

    @GetMapping("/profile")
    suspend fun getProfile(context: ReactiveSecurityContext): ProfileDto {
        val principal = context.authentication.principal as CoSecPrincipal
        return profileService.getById(principal.id)
    }
}

```

## Summary

- **Pluggable Interface**: All authentication flows implement `Authentication<C, P>` in [`cosec-api/src/main/kotlin/me/ahoo/cosec/api/authentication/Authentication.kt`](https://github.com/ahoo-wang/cosec/blob/main/cosec-api/src/main/kotlin/me/ahoo/cosec/api/authentication/Authentication.kt), enabling type-safe credential handling.
- **Auto-configuration**: JWT and OAuth2 providers are instantiated automatically based on property files, with logic centralized in [`CoSecSocialAuthenticationAutoConfiguration.kt`](https://github.com/ahoo-wang/cosec/blob/main/CoSecSocialAuthenticationAutoConfiguration.kt).
- **Social Login**: JustAuth integration via [`SocialAuthentication.kt`](https://github.com/ahoo-wang/cosec/blob/main/SocialAuthentication.kt) handles OAuth2 flows and converts social profiles to `CoSecPrincipal` objects.
- **Custom Extensions**: Implement the interface as a Spring component to add API-key, LDAP, or proprietary authentication without modifying core code.
- **Filter Chain**: `AuthorizationGatewayFilter` and `ReactiveAuthorizationFilter` trigger authentication before policy evaluation, ensuring the security context is populated for downstream authorization.

## Frequently Asked Questions

### How do I enable JWT authentication in CoSec?

Enable JWT authentication by adding a signing key to your [`application.yml`](https://github.com/ahoo-wang/cosec/blob/main/application.yml) under `cosec.authentication.jwt.secret`. The auto-configuration in the `cosec-jwt` module then creates a `JwtAuthenticationProvider` bean that validates `Authorization: Bearer` headers and maps claims to a `CoSecPrincipal`.

### Can I use multiple authentication methods at the same time?

Yes. CoSec supports simultaneous authentication strategies because each provider declares its supported credential type via the `supportCredentials` property. The framework selects the appropriate `Authentication` bean based on the credential type present in the request, allowing JWT and social login to coexist.

### How does CoSec convert a social login to an internal principal?

The `SocialAuthentication` class delegates to a `SocialUserPrincipalConverter` (default: `DirectSocialUserPrincipalConverter`). This converter transforms the `SocialUser` object returned by JustAuth into a `CoSecPrincipal` containing the user ID and roles, which is then stored in the security context for authorization checks.

### Where does authentication occur in the CoSec request pipeline?

Authentication occurs in the filter layer before authorization. `AuthorizationGatewayFilter` (for gateways) or `ReactiveAuthorizationFilter` (for WebFlux applications) invokes the configured `Authentication` bean immediately after credential extraction. Only after successful authentication does the request proceed to the policy engine for authorization decisions.