package com.auth.config import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.security.config.Customizer import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer import org.springframework.security.config.http.SessionCreationPolicy import org.springframework.security.core.authority.SimpleGrantedAuthority import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter import org.springframework.security.web.SecurityFilterChain @Configuration @EnableWebSecurity @EnableMethodSecurity( prePostEnabled = true, // ← явно включаем securedEnabled = true // ← опционально ) class WebSecurityConfig () { private val logger = org.slf4j.LoggerFactory.getLogger(WebSecurityConfig::class.java) @Bean @Throws(Exception::class) fun filterChain(http: HttpSecurity): SecurityFilterChain? { http.authorizeHttpRequests(Customizer { auth -> auth.requestMatchers("/public/**", "/health", "/info").permitAll() //auth.anyRequest().permitAll() auth.anyRequest().authenticated() }) .oauth2ResourceServer(Customizer { oauth2 -> // oauth2!!.jwt(Customizer.withDefaults()) // добавляем конвертер для извлечения ролей oauth2.jwt { jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()) } }) // проверка JWT токен .sessionManagement(Customizer { session: SessionManagementConfigurer? -> session!!.sessionCreationPolicy(SessionCreationPolicy.STATELESS) }) // без сессий .csrf(Customizer { csrf: CsrfConfigurer? -> csrf!!.disable() }) // отключаем CSRF для API return http.build() } private fun jwtAuthenticationConverter(): JwtAuthenticationConverter { val converter = JwtAuthenticationConverter() converter.setJwtGrantedAuthoritiesConverter { jwt -> val roles = mutableSetOf() // Извлекаем роли из resource_access.test_client.roles val resourceAccess = jwt.claims["resource_access"] as? Map<*, *> logger.info("Roles! "+resourceAccess) val clientAccess = resourceAccess?.get("test_client") as? Map<*, *> val clientRoles = clientAccess?.get("roles") as? List<*> clientRoles?.forEach { role -> roles.add(SimpleGrantedAuthority("ROLE_$role")) } // Альтернативно: можно также читать из realm_access.roles val realmAccess = jwt.claims["realm_access"] as? Map<*, *> val realmRoles = realmAccess?.get("roles") as? List<*> realmRoles?.forEach { role -> roles.add(SimpleGrantedAuthority("ROLE_$role")) } roles.toList() } return converter } // // Конвертер JWT Authentication (извлекает роли из токена) // private fun jwtAuthenticationConverter(): JwtAuthenticationConverter { // val converter = JwtAuthenticationConverter() // // // Извлекаем роли из поля resource_access.test_client.roles // val authoritiesExtractor = JwtGrantedAuthoritiesConverter() // authoritiesExtractor.setAuthoritiesClaimName("resource_access.test_client.roles") // где лежат роли // authoritiesExtractor.setAuthorityPrefix("ROLE_") // добавляем префикс ROLE_ // // converter.setJwtGrantedAuthoritiesConverter(authoritiesExtractor) // //// // Дополнительно: проверяем, что роли не пустые //// converter.setJwtGrantedAuthoritiesConverter { jwt -> //// val authorities = authoritiesExtractor.convert(jwt) //// if (authorities.isEmpty()) { //// throw IllegalArgumentException("User has no roles assigned in token") //// } //// authorities //// } // // return converter // } }