Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions kerb4j-server/kerb4j-server-spring-security/krb5.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

[libdefaults]
kdc_realm = EXAMPLE.COM
default_realm = EXAMPLE.COM
udp_preference_limit = 1
kdc_tcp_port = 10010
#_KDC_UDP_PORT_

[realms]
EXAMPLE.COM = {
kdc = localhost:10010
}
173 changes: 173 additions & 0 deletions kerb4j-server/kerb4j-server-spring-webflux/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Spring WebFlux Support for Kerb4J

This module provides Spring WebFlux reactive support for Kerberos/SPNEGO authentication in kerb4j.

## Overview

The `kerb4j-server-spring-webflux` module extends kerb4j to support Spring WebFlux applications with reactive streams and non-blocking I/O. This module provides WebFlux equivalents of the Spring MVC components found in the `kerb4j-server-spring-security` module.

## Key Components

### SpnegoServerAuthenticationEntryPoint

Reactive equivalent of `SpnegoEntryPoint` that implements `ServerAuthenticationEntryPoint`. This component:

- Sends `WWW-Authenticate: Negotiate` header to initiate SPNEGO authentication
- Supports optional redirect URLs for fallback authentication (e.g., form login)
- Works with reactive ServerWebExchange instead of servlet request/response

### SpnegoServerAuthenticationConverter

Reactive authentication converter that implements `ServerAuthenticationConverter`. This component:

- Parses SPNEGO `Negotiate` headers from incoming requests
- Supports basic authentication fallback when configured
- Creates `SpnegoRequestToken` objects from Kerberos tickets
- Handles both SPNEGO and basic authentication headers

### ReactiveAuthenticationManagerAdapter

Adapter that wraps traditional `AuthenticationManager` implementations for use in reactive applications. This component:

- Adapts blocking authentication managers to reactive streams
- Uses bounded elastic scheduler for non-blocking operations
- Allows reuse of existing Kerberos authentication providers

### SpnegoWebFluxConfigurer

Utility class providing helper methods to configure SPNEGO authentication in WebFlux applications:

- `createSpnegoAuthenticationWebFilter()` - Creates configured authentication web filters
- Supports custom matchers and authentication managers
- Provides both blocking and reactive authentication manager support

## Usage

### Basic Configuration

```java
@Configuration
@EnableWebFluxSecurity
public class WebFluxSecurityConfig {

@Value("${serverPrincipal}")
private String serverPrincipal;

@Value("${serverKeytab}")
private String serverKeytab;

@Bean
public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) {
return http
.exceptionHandling(e -> e.authenticationEntryPoint(spnegoServerAuthenticationEntryPoint()))
.authorizeExchange(exchanges -> exchanges
.pathMatchers("/").permitAll()
.pathMatchers("/hello").hasRole("USER")
.anyExchange().permitAll())
.addFilterBefore(spnegoAuthenticationWebFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
.build();
}

@Bean
public AuthenticationWebFilter spnegoAuthenticationWebFilter() {
return SpnegoWebFluxConfigurer.createSpnegoAuthenticationWebFilter(
new ReactiveAuthenticationManagerAdapter(authManager()));
}

@Bean
public AuthenticationManager authManager() {
return new ProviderManager(kerberosServiceAuthenticationProvider());
}

@Bean
public SpnegoServerAuthenticationEntryPoint spnegoServerAuthenticationEntryPoint() {
return new SpnegoServerAuthenticationEntryPoint();
}

@Bean
public SpnegoAuthenticationProvider kerberosServiceAuthenticationProvider() {
SpnegoAuthenticationProvider provider = new SpnegoAuthenticationProvider();
provider.setTicketValidator(sunJaasKerberosTicketValidator());
provider.setUserDetailsService(userDetailsService());
return provider;
}

@Bean
public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() {
SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator();
ticketValidator.setServicePrincipal(serverPrincipal);
ticketValidator.setKeyTabLocation(new FileSystemResource(serverKeytab));
return ticketValidator;
}

// ... other beans
}
```

### With Form Login Fallback

```java
@Bean
public SpnegoServerAuthenticationEntryPoint spnegoServerAuthenticationEntryPoint() {
return new SpnegoServerAuthenticationEntryPoint("/login");
}
```

### Custom Authentication Matching

```java
@Bean
public AuthenticationWebFilter spnegoAuthenticationWebFilter() {
ServerWebExchangeMatcher matcher = ServerWebExchangeMatchers.pathMatchers("/secure/**");
return SpnegoWebFluxConfigurer.createSpnegoAuthenticationWebFilter(
new ReactiveAuthenticationManagerAdapter(authManager()),
matcher,
true // support basic auth fallback
);
}
```

## Dependencies

This module depends on:

- `kerb4j-server-common` - Core server functionality
- `kerb4j-server-spring-security` - Reuses authentication providers and tokens
- `spring-boot-starter-webflux` - Spring WebFlux reactive web framework
- `spring-boot-starter-security` - Spring Security with reactive support
- `reactor-core` - Reactive streams implementation

## Integration with Existing Code

This module is designed to work alongside the existing `kerb4j-server-spring-security` module:

- **Reuses**: Authentication providers, ticket validators, tokens, and user details services
- **Adds**: Reactive/WebFlux-specific filters, entry points, and configuration helpers
- **Maintains**: Full backward compatibility with existing WebMVC applications

## Testing

The module includes comprehensive tests for:

- `SpnegoServerAuthenticationEntryPoint` - Entry point behavior and configuration
- `SpnegoServerAuthenticationConverter` - Token parsing and conversion
- `ReactiveAuthenticationManagerAdapter` - Reactive wrapper functionality
- Integration scenarios with sample configurations

Run tests with:

```bash
mvn test
```

## Migration from WebMVC

To migrate from WebMVC to WebFlux:

1. Replace `@EnableWebSecurity` with `@EnableWebFluxSecurity`
2. Replace `SecurityFilterChain` with `SecurityWebFilterChain`
3. Replace `HttpSecurity` with `ServerHttpSecurity`
4. Use `SpnegoWebFluxConfigurer` instead of manual filter configuration
5. Wrap existing `AuthenticationManager` with `ReactiveAuthenticationManagerAdapter`

The authentication providers, ticket validators, and business logic remain unchanged.
83 changes: 83 additions & 0 deletions kerb4j-server/kerb4j-server-spring-webflux/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.kerb4j</groupId>
<artifactId>kerb4j-server</artifactId>
<version>0.2.0</version>
</parent>

<artifactId>kerb4j-server-spring-webflux</artifactId>
<name>kerb4j-server-spring-webflux</name>

<properties>
<spring.security.version>6.1.5</spring.security.version>
<spring.webflux.version>6.0.12</spring.webflux.version>
</properties>

<dependencies>
<dependency>
<groupId>com.kerb4j</groupId>
<artifactId>kerb4j-server-common</artifactId>
<version>${project.parent.version}</version>
</dependency>

<!-- Reuse core Spring Security components from the webmvc module -->
<dependency>
<groupId>com.kerb4j</groupId>
<artifactId>kerb4j-server-spring-security</artifactId>
<version>${project.parent.version}</version>
</dependency>

<!-- Add explicit Spring Security WebFlux support -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>${spring.boot.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>${spring.boot.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>${spring.security.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<version>3.5.11</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.kerb4j.server.spring.webflux;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.util.Assert;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

/**
* Reactive wrapper for {@link AuthenticationManager} to be used in WebFlux applications.
*
* <p>This allows existing {@link AuthenticationManager} implementations (like those used
* for SPNEGO authentication) to be used in reactive WebFlux applications by wrapping
* the blocking authentication calls.</p>
*
* @author GitHub Copilot
* @since 1.0
*/
public class ReactiveAuthenticationManagerAdapter implements ReactiveAuthenticationManager {

private final AuthenticationManager authenticationManager;

/**
* Creates a new reactive authentication manager adapter.
*
* @param authenticationManager the underlying authentication manager to adapt
*/
public ReactiveAuthenticationManagerAdapter(AuthenticationManager authenticationManager) {
Assert.notNull(authenticationManager, "AuthenticationManager cannot be null");
this.authenticationManager = authenticationManager;
}

@Override
public Mono<Authentication> authenticate(Authentication authentication) {
return Mono.fromCallable(() -> authenticationManager.authenticate(authentication))
.subscribeOn(Schedulers.boundedElastic());
}
}
Loading
Loading