11package fi.hsl.jore4.timetables.config
22
3+ import jakarta.servlet.FilterChain
4+ import jakarta.servlet.http.HttpServletRequest
5+ import jakarta.servlet.http.HttpServletResponse
6+ import mu.KotlinLogging
37import org.springframework.context.annotation.Bean
48import org.springframework.context.annotation.Configuration
59import org.springframework.http.HttpMethod
10+ import org.springframework.security.authentication.AuthenticationProvider
611import org.springframework.security.config.annotation.web.builders.HttpSecurity
712import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
813import org.springframework.security.config.http.SessionCreationPolicy
14+ import org.springframework.security.core.context.SecurityContextHolder
915import org.springframework.security.web.SecurityFilterChain
16+ import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
17+ import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
18+ import org.springframework.web.filter.OncePerRequestFilter
1019
1120@Configuration
1221@EnableWebSecurity
1322class WebSecurityConfig {
1423
24+ val logger = KotlinLogging .logger {}
25+
26+ inner class HasuraFilter (private val authenticationProvider : AuthenticationProvider ) : OncePerRequestFilter() {
27+ override fun doFilterInternal (
28+ request : HttpServletRequest ,
29+ response : HttpServletResponse ,
30+ filterChain : FilterChain
31+ ) {
32+ val sessionCookie = request.cookies?.find { it.name.lowercase() == " session" }
33+ val roleHeader = request.getHeader(" X-Hasura-Role" )
34+
35+ if (" OPTIONS" == request.method) {
36+ response.status = HttpServletResponse .SC_OK
37+ } else {
38+ if (sessionCookie == null || sessionCookie.value.isBlank()) {
39+ logger.info(" No session cookie in request http request" )
40+ } else if (roleHeader == null ) {
41+ logger.info(" No role header in http request" )
42+ } else {
43+ logger.info(" cookie value ${sessionCookie.value} " )
44+
45+ val preauth = PreAuthenticatedAuthenticationToken (sessionCookie.value, roleHeader)
46+ SecurityContextHolder .getContext().authentication = authenticationProvider.authenticate(preauth)
47+ }
48+ }
49+ filterChain.doFilter(request, response)
50+ }
51+ }
52+
1553 @Bean
1654 @Throws(Exception ::class )
17- fun configure (httpSecurity : HttpSecurity ): SecurityFilterChain {
55+ fun configure (httpSecurity : HttpSecurity , authentication : RemoteAuthenticationProvider ): SecurityFilterChain {
1856 return httpSecurity
57+ .addFilterBefore(HasuraFilter (authentication), UsernamePasswordAuthenticationFilter ::class .java)
1958 .sessionManagement { it.sessionCreationPolicy(SessionCreationPolicy .NEVER ) }
2059 .csrf { it.disable() }
2160 .cors {}
@@ -24,16 +63,19 @@ class WebSecurityConfig {
2463 .requestMatchers(
2564 HttpMethod .GET ,
2665 " /actuator/health" ,
27- " /error" ,
28- " /hello" ,
29- " /hello/test" ,
30- " /timetables/to-replace"
66+ " /error"
3167 )
3268 .permitAll()
69+ .requestMatchers(
70+ HttpMethod .GET ,
71+ " /timetables/to-replace"
72+ )
73+ .hasAuthority(" admin" )
3374 .requestMatchers(
3475 HttpMethod .POST ,
3576 " /timetables/*"
36- ).permitAll()
77+ )
78+ .hasAuthority(" admin" )
3779 .anyRequest().denyAll()
3880 }
3981 .build()
0 commit comments