fixing Keycloak JwtService entfernt
This commit is contained in:
@@ -25,8 +25,6 @@ dependencies {
|
||||
implementation(platform(projects.platform.platformBom))
|
||||
// Stellt gemeinsame Abhängigkeiten bereit.
|
||||
implementation(projects.platform.platformDependencies)
|
||||
// Nutzt die Client-Logik für die Kommunikation mit Keycloak.
|
||||
implementation(projects.infrastructure.auth.authClient)
|
||||
// Spring Boot Starter für einen Web-Service.
|
||||
// OPTIMIERUNG: Verwendung des `spring-boot-essentials`-Bundles.
|
||||
implementation(libs.bundles.spring.boot.essentials)
|
||||
|
||||
+4
-47
@@ -1,55 +1,12 @@
|
||||
package at.mocode.infrastructure.auth.config
|
||||
|
||||
import at.mocode.infrastructure.auth.client.JwtService
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.validation.annotation.Validated
|
||||
import jakarta.validation.constraints.Min
|
||||
import jakarta.validation.constraints.NotBlank
|
||||
import jakarta.validation.constraints.Size
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
/**
|
||||
* Spring-Konfiguration für das Auth-Server-Modul.
|
||||
* Stellt die notwendigen Beans und Einstellungen für JWT-Verarbeitung und Authentifizierung bereit.
|
||||
*
|
||||
* Note: JWT handling is now fully delegated to Keycloak via OAuth2 Resource Server.
|
||||
* This auth-server focuses on user management through Keycloak Admin Client.
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AuthServerConfiguration.JwtProperties::class)
|
||||
class AuthServerConfiguration {
|
||||
|
||||
/**
|
||||
* Erstellt einen JwtService-Bean mit Konfiguration aus den Application Properties.
|
||||
*/
|
||||
@Bean
|
||||
fun jwtService(jwtProperties: JwtProperties): JwtService {
|
||||
// Basic safeguard: warn if default secret is used
|
||||
if (jwtProperties.secret == "default-secret-for-development-only-please-change-in-production") {
|
||||
System.err.println("[SECURITY WARNING] Using default JWT secret – DO NOT use this in production!")
|
||||
}
|
||||
return JwtService(
|
||||
secret = jwtProperties.secret,
|
||||
issuer = jwtProperties.issuer,
|
||||
audience = jwtProperties.audience,
|
||||
expiration = jwtProperties.expiration.minutes
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Konfigurationseigenschaften für JWT-Einstellungen.
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "auth.jwt")
|
||||
@Validated
|
||||
data class JwtProperties(
|
||||
@field:NotBlank
|
||||
@field:Size(min = 32, message = "JWT secret must be at least 32 characters for HMAC512")
|
||||
val secret: String = "default-secret-for-development-only-please-change-in-production",
|
||||
@field:NotBlank
|
||||
val issuer: String = "meldestelle-auth-server",
|
||||
@field:NotBlank
|
||||
val audience: String = "meldestelle-services",
|
||||
@field:Min(1)
|
||||
val expiration: Long = 60 // minutes
|
||||
)
|
||||
}
|
||||
class AuthServerConfiguration
|
||||
|
||||
+12
-38
@@ -1,13 +1,16 @@
|
||||
package at.mocode.infrastructure.auth
|
||||
|
||||
import at.mocode.infrastructure.auth.client.JwtService
|
||||
import at.mocode.infrastructure.auth.config.AuthServerConfiguration
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
/**
|
||||
* Basic tests for the Auth Server application and configuration.
|
||||
* These tests verify the application structure and basic functionality without requiring full Spring context.
|
||||
* These tests verify the application structure without requiring full Spring context.
|
||||
*
|
||||
* Note: Custom JWT handling has been removed. Authentication is now fully handled
|
||||
* by Keycloak via OAuth2 Resource Server.
|
||||
*/
|
||||
class AuthServerApplicationTest {
|
||||
|
||||
@@ -30,43 +33,14 @@ class AuthServerApplicationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `auth server configuration should create JWT service bean`() {
|
||||
// Arrange
|
||||
val config = AuthServerConfiguration()
|
||||
val jwtProperties = AuthServerConfiguration.JwtProperties(
|
||||
secret = "test-secret-for-testing-only-at-least-512-bits-long-for-hmac512",
|
||||
issuer = "test-issuer",
|
||||
audience = "test-audience",
|
||||
expiration = 60
|
||||
)
|
||||
|
||||
// Act
|
||||
val jwtService = config.jwtService(jwtProperties)
|
||||
|
||||
// Assert
|
||||
assertNotNull(jwtService)
|
||||
assertInstanceOf(JwtService::class.java, jwtService)
|
||||
|
||||
// Test that the service can generate and validate tokens
|
||||
val token = jwtService.generateToken("test-user", "testuser", emptyList())
|
||||
assertNotNull(token)
|
||||
assertTrue(token.isNotEmpty())
|
||||
|
||||
val validationResult = jwtService.validateToken(token)
|
||||
assertTrue(validationResult.isSuccess)
|
||||
assertEquals(true, validationResult.getOrNull())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `JWT properties should have sensible defaults`() {
|
||||
fun `auth server configuration should be present`() {
|
||||
// Arrange & Act
|
||||
val defaultProperties = AuthServerConfiguration.JwtProperties()
|
||||
val config = AuthServerConfiguration()
|
||||
|
||||
// Assert
|
||||
assertNotNull(defaultProperties.secret)
|
||||
assertTrue(defaultProperties.secret.isNotEmpty())
|
||||
assertEquals("meldestelle-auth-server", defaultProperties.issuer)
|
||||
assertEquals("meldestelle-services", defaultProperties.audience)
|
||||
assertEquals(60L, defaultProperties.expiration)
|
||||
assertNotNull(config)
|
||||
assertTrue(config::class.java.isAnnotationPresent(org.springframework.context.annotation.Configuration::class.java)) {
|
||||
"AuthServerConfiguration should be annotated with @Configuration"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-196
@@ -1,10 +1,8 @@
|
||||
package at.mocode.infrastructure.auth
|
||||
|
||||
import at.mocode.infrastructure.auth.client.JwtService
|
||||
import at.mocode.infrastructure.auth.client.model.BerechtigungE
|
||||
import at.mocode.infrastructure.auth.config.AuthServerConfiguration
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
@@ -13,21 +11,16 @@ import org.springframework.test.context.TestPropertySource
|
||||
|
||||
/**
|
||||
* Minimal integration tests for the Auth Server.
|
||||
* Tests essential functionality without full Spring Boot context complexity.
|
||||
* Focuses on core service integration and configuration validation.
|
||||
*
|
||||
* This implements "Option 1: Minimale Integration Tests" focusing on essentials
|
||||
* without vollständige Spring Boot Konfiguration.
|
||||
* Note: Custom JWT handling has been removed. Authentication is now fully handled
|
||||
* by Keycloak via OAuth2 Resource Server. This test verifies the basic Spring
|
||||
* context loads correctly.
|
||||
*/
|
||||
@SpringBootTest(
|
||||
webEnvironment = SpringBootTest.WebEnvironment.NONE,
|
||||
classes = [AuthServerConfiguration::class]
|
||||
)
|
||||
@TestPropertySource(properties = [
|
||||
"auth.jwt.secret=test-secret-for-testing-only-at-least-512-bits-long-for-hmac512-algorithm",
|
||||
"auth.jwt.issuer=test-issuer",
|
||||
"auth.jwt.audience=test-audience",
|
||||
"auth.jwt.expiration=60",
|
||||
"spring.main.web-application-type=none",
|
||||
"logging.level.org.springframework.security=WARN"
|
||||
])
|
||||
@@ -36,22 +29,6 @@ class AuthServerIntegrationTest {
|
||||
@Autowired
|
||||
private lateinit var applicationContext: ApplicationContext
|
||||
|
||||
@Autowired
|
||||
private lateinit var jwtService: JwtService
|
||||
|
||||
private lateinit var testToken: String
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
testToken = jwtService.generateToken(
|
||||
userId = "test-user-123",
|
||||
username = "testuser",
|
||||
permissions = listOf(BerechtigungE.PERSON_READ, BerechtigungE.VEREIN_READ)
|
||||
)
|
||||
}
|
||||
|
||||
// ========== Core Service Integration Tests ==========
|
||||
|
||||
@Test
|
||||
fun `application context should load with minimal configuration`() {
|
||||
// Verify that the Spring context loads successfully
|
||||
@@ -63,138 +40,17 @@ class AuthServerIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `JwtService should be properly configured as Spring bean`() {
|
||||
// Verify that JwtService is available as a Spring bean
|
||||
assertTrue(applicationContext.containsBean("jwtService"))
|
||||
assertNotNull(jwtService)
|
||||
assertInstanceOf(JwtService::class.java, jwtService)
|
||||
|
||||
println("[DEBUG_LOG] JwtService bean configured successfully")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `JWT service should generate valid tokens`() {
|
||||
// Test token generation functionality
|
||||
val token = jwtService.generateToken(
|
||||
userId = "integration-test-user",
|
||||
username = "inttest",
|
||||
permissions = listOf(BerechtigungE.PERSON_CREATE, BerechtigungE.PFERD_READ)
|
||||
)
|
||||
|
||||
assertNotNull(token)
|
||||
assertTrue(token.isNotEmpty())
|
||||
|
||||
// Verify token can be validated
|
||||
val validationResult = jwtService.validateToken(token)
|
||||
assertTrue(validationResult.isSuccess)
|
||||
assertEquals(true, validationResult.getOrNull())
|
||||
|
||||
println("[DEBUG_LOG] Token generated and validated successfully")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `JWT service should extract user information correctly`() {
|
||||
// Test user ID extraction
|
||||
val userIdResult = jwtService.getUserIdFromToken(testToken)
|
||||
assertTrue(userIdResult.isSuccess)
|
||||
assertEquals("test-user-123", userIdResult.getOrNull())
|
||||
|
||||
// Test permissions extraction
|
||||
val permissionsResult = jwtService.getPermissionsFromToken(testToken)
|
||||
assertTrue(permissionsResult.isSuccess)
|
||||
val permissions = permissionsResult.getOrNull()!!
|
||||
assertEquals(2, permissions.size)
|
||||
assertTrue(permissions.contains(BerechtigungE.PERSON_READ))
|
||||
assertTrue(permissions.contains(BerechtigungE.VEREIN_READ))
|
||||
|
||||
println("[DEBUG_LOG] User information extracted correctly")
|
||||
println("[DEBUG_LOG] User ID: ${userIdResult.getOrNull()}")
|
||||
println("[DEBUG_LOG] Permissions: $permissions")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `JWT service should handle invalid tokens properly`() {
|
||||
val invalidToken = "invalid.jwt.token"
|
||||
|
||||
// Validation should fail
|
||||
val validationResult = jwtService.validateToken(invalidToken)
|
||||
assertTrue(validationResult.isFailure)
|
||||
|
||||
// User ID extraction should fail
|
||||
val userIdResult = jwtService.getUserIdFromToken(invalidToken)
|
||||
assertTrue(userIdResult.isFailure)
|
||||
|
||||
// Permissions extraction should fail
|
||||
val permissionsResult = jwtService.getPermissionsFromToken(invalidToken)
|
||||
assertTrue(permissionsResult.isFailure)
|
||||
|
||||
println("[DEBUG_LOG] Invalid token handling works correctly")
|
||||
}
|
||||
|
||||
// ========== Configuration Validation Tests ==========
|
||||
|
||||
@Test
|
||||
fun `configuration properties should be properly loaded`() {
|
||||
// Test that JWT configuration is loaded correctly
|
||||
val jwtProperties = applicationContext.getBean(AuthServerConfiguration.JwtProperties::class.java)
|
||||
assertNotNull(jwtProperties)
|
||||
assertEquals("test-issuer", jwtProperties.issuer)
|
||||
assertEquals("test-audience", jwtProperties.audience)
|
||||
assertEquals(60L, jwtProperties.expiration)
|
||||
|
||||
println("[DEBUG_LOG] Configuration properties loaded correctly")
|
||||
println("[DEBUG_LOG] Issuer: ${jwtProperties.issuer}")
|
||||
println("[DEBUG_LOG] Audience: ${jwtProperties.audience}")
|
||||
println("[DEBUG_LOG] Expiration: ${jwtProperties.expiration}")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `essential beans should be properly configured`() {
|
||||
// Verify that essential beans for auth functionality are available
|
||||
fun `configuration bean should be present`() {
|
||||
// Verify that essential beans are available
|
||||
val beanNames = applicationContext.beanDefinitionNames.toList()
|
||||
|
||||
// Check for JWT service bean
|
||||
assertTrue(applicationContext.containsBean("jwtService")) {
|
||||
"JwtService bean should be configured"
|
||||
}
|
||||
|
||||
// Check for configuration bean
|
||||
assertTrue(beanNames.any { it.contains("authServerConfiguration") }) {
|
||||
"AuthServerConfiguration bean should be configured"
|
||||
}
|
||||
|
||||
println("[DEBUG_LOG] Essential beans configured successfully")
|
||||
println("[DEBUG_LOG] Auth-related beans: ${beanNames.filter { it.contains("jwt") || it.contains("auth") }}")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `JWT configuration integration should work end-to-end`() {
|
||||
// Test the complete flow from configuration to token operations
|
||||
val userId = "end-to-end-test"
|
||||
val username = "e2etest"
|
||||
val permissions = listOf(BerechtigungE.PERSON_READ, BerechtigungE.PERSON_CREATE)
|
||||
|
||||
// Generate token
|
||||
val token = jwtService.generateToken(userId, username, permissions)
|
||||
assertNotNull(token)
|
||||
assertTrue(token.isNotEmpty())
|
||||
|
||||
// Validate token
|
||||
val isValid = jwtService.validateToken(token)
|
||||
assertTrue(isValid.isSuccess)
|
||||
|
||||
// Extract and verify data
|
||||
val extractedUserId = jwtService.getUserIdFromToken(token).getOrNull()
|
||||
val extractedPermissions = jwtService.getPermissionsFromToken(token).getOrElse { emptyList() }
|
||||
|
||||
assertEquals(userId, extractedUserId)
|
||||
assertEquals(2, extractedPermissions.size)
|
||||
assertTrue(extractedPermissions.containsAll(permissions))
|
||||
|
||||
println("[DEBUG_LOG] End-to-end test completed successfully")
|
||||
println("[DEBUG_LOG] Token validation: ${isValid.isSuccess}")
|
||||
println("[DEBUG_LOG] Extracted user: $extractedUserId")
|
||||
println("[DEBUG_LOG] Extracted permissions: $extractedPermissions")
|
||||
println("[DEBUG_LOG] Auth-related beans: ${beanNames.filter { it.contains("auth") }}")
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -217,48 +73,4 @@ class AuthServerIntegrationTest {
|
||||
println("[DEBUG_LOG] Total bean count: $beanCount")
|
||||
println("[DEBUG_LOG] Web-related beans: $webBeans")
|
||||
}
|
||||
|
||||
// ========== Service Functionality Tests ==========
|
||||
|
||||
@Test
|
||||
fun `JWT service should handle different permission combinations`() {
|
||||
// Test various permission combinations
|
||||
val testCases = listOf(
|
||||
emptyList(),
|
||||
listOf(BerechtigungE.PERSON_READ),
|
||||
listOf(BerechtigungE.PERSON_READ, BerechtigungE.PERSON_CREATE),
|
||||
BerechtigungE.entries
|
||||
)
|
||||
|
||||
testCases.forEach { permissions ->
|
||||
val token = jwtService.generateToken("test-user", "test", permissions)
|
||||
val validationResult = jwtService.validateToken(token)
|
||||
val extractedPermissions = jwtService.getPermissionsFromToken(token).getOrElse { emptyList() }
|
||||
|
||||
assertTrue(validationResult.isSuccess)
|
||||
assertEquals(permissions.size, extractedPermissions.size)
|
||||
assertTrue(extractedPermissions.containsAll(permissions))
|
||||
}
|
||||
|
||||
println("[DEBUG_LOG] Different permission combinations handled correctly")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `JWT service should be thread-safe for concurrent access`() {
|
||||
// Test concurrent token operations
|
||||
val threads = (1..5).map { threadIndex ->
|
||||
Thread {
|
||||
repeat(10) { iteration ->
|
||||
val token = jwtService.generateToken("user-$threadIndex-$iteration", "test", listOf(BerechtigungE.PERSON_READ))
|
||||
val isValid = jwtService.validateToken(token).isSuccess
|
||||
assertTrue(isValid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
threads.forEach { it.start() }
|
||||
threads.forEach { it.join() }
|
||||
|
||||
println("[DEBUG_LOG] Concurrent access test completed successfully")
|
||||
}
|
||||
}
|
||||
|
||||
+5
-21
@@ -1,29 +1,13 @@
|
||||
package at.mocode.infrastructure.auth.config
|
||||
|
||||
import at.mocode.infrastructure.auth.client.JwtService
|
||||
import org.springframework.boot.test.context.TestConfiguration
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Primary
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
/**
|
||||
* Test configuration for Auth Server integration tests.
|
||||
* Provides minimal bean configuration needed for tests to run.
|
||||
*
|
||||
* Note: Custom JWT handling has been removed. Authentication is now fully handled
|
||||
* by Keycloak via OAuth2 Resource Server. This configuration class is kept as a
|
||||
* placeholder for future test-specific beans if needed.
|
||||
*/
|
||||
@TestConfiguration
|
||||
class AuthServerTestConfiguration {
|
||||
|
||||
/**
|
||||
* Provides a JwtService bean for testing with test-specific configuration.
|
||||
*/
|
||||
@Bean
|
||||
@Primary
|
||||
fun testJwtService(): JwtService {
|
||||
return JwtService(
|
||||
secret = "test-secret-for-testing-only-at-least-512-bits-long-for-hmac512-algorithm",
|
||||
issuer = "test-issuer",
|
||||
audience = "test-audience",
|
||||
expiration = 60.minutes
|
||||
)
|
||||
}
|
||||
}
|
||||
class AuthServerTestConfiguration
|
||||
|
||||
Reference in New Issue
Block a user