Erro de autenticação JWT

Boa noite a todos,

Estou com problema para realizar a autenticação via token JWT, as requisições GET funcionam os POSTs esta dando acesso negado.

As tecnologias usadas são Spring Boot e Kotlin, em um api rest.

Consigo realizar a solicitação e obter o login.

As solicitações GET, passam corretamente pelos filtros de autenticação.

As solicitações POST, retornam um Exception falando que não existe autorização

Criei um filtro para rastrear, e o header “Authorization” é sim enviado para o servidor tanto nas solicitações GET, quanto na POST

As solicitações POST nunca chegam a passar pela classe JWTAuthorizationFilter, enquanto as GET sim.

Alguma luz, pode ser em java a resposta.
Se precisar de mais alguma informação.

Exception

org.springframework.security.authentication.InsufficientAuthenticationException: Full authentication is required to access this resource
    at org.springframework.security.web.access.ExceptionTranslationFilter.handleSpringSecurityException(ExceptionTranslationFilter.java:189)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:140)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:461)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:384)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312)
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:394)
    at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:253)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:175)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1591)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:834)

Seguem as classes

JWTAuthenticationFilter

package com.arda.asincor.config

import com.arda.asincor.model.sistema.Usuario
import com.arda.asincor.objects.Credentials
import com.arda.asincor.service.Constantes
import com.fasterxml.jackson.databind.ObjectMapper
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.SignatureAlgorithm
import io.jsonwebtoken.security.Keys
import org.slf4j.LoggerFactory
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.Authentication
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
import java.nio.charset.Charset
import java.util.*
import java.util.stream.Collectors
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

class JWTAuthenticationFilter : UsernamePasswordAuthenticationFilter
{
    private val ardaLogger = LoggerFactory.getLogger(JWTAuthenticationFilter::class.java)

    constructor(authenticationManager: AuthenticationManager) : super()
    {
        this.authenticationManager = authenticationManager
    }

    override fun attemptAuthentication(request: HttpServletRequest, response: HttpServletResponse?): Authentication?
    {
        ardaLogger.info("Antes da autenticação")
        val (username, password) = try
        {
            ObjectMapper().readValue(request.inputStream, Credentials::class.java)
        } catch (ex: Exception)
        {
            ardaLogger.error("Usuário e/ou senha não encontrados: ${ex.message}", ex)
            throw throw UsernameNotFoundException("Usuário e/ou senha não encontrados!")
        }
        try
        {
            val token = UsernamePasswordAuthenticationToken(username, password)
            return authenticationManager.authenticate(token)
        } catch (ex: Exception)
        {
            ardaLogger.error("Usuário e/ou senha inválidos: ${ex.message}", ex)
            throw UsernameNotFoundException("Usuário e/ou senha inválidos")
        }
    }

    override fun successfulAuthentication(request: HttpServletRequest?, response: HttpServletResponse, chain: FilterChain?, authResult: Authentication)
    {
        ardaLogger.info("Autenticação")
        val user = authResult.principal as Usuario
        val roles = user.authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList())
        val signingKey = Constantes.SECRET_KEY.toByteArray(Charset.forName("UTF-8"))
        ardaLogger.info("Chave: $signingKey")
        val token = Jwts.builder()
                .signWith(Keys.hmacShaKeyFor(signingKey), SignatureAlgorithm.HS256)
                .setHeaderParam("typ", Constantes.TOKEN_TYPE)
                .setIssuer(Constantes.TOKEN_ISSUER)
                .setAudience(Constantes.TOKEN_AUDIENCE)
                .setSubject(user.username)
                .setExpiration(Date(System.currentTimeMillis() + 300000))
                .claim("rol", roles)
                .compact()
        response.addHeader(Constantes.AUTHORIZATION, "${Constantes.BEARER} $token")
    }
}

JWTAuthorizationFilter

package com.arda.asincor.config

import com.arda.asincor.service.Constantes
import io.jsonwebtoken.ExpiredJwtException
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.MalformedJwtException
import io.jsonwebtoken.UnsupportedJwtException
import io.jsonwebtoken.security.SignatureException
import org.slf4j.LoggerFactory
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter
import java.nio.charset.Charset
import java.util.stream.Collectors
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

class JWTAuthorizationFilter : BasicAuthenticationFilter
{
    private val ardaLogger = LoggerFactory.getLogger(JWTAuthorizationFilter::class.java)
    private var authManager: AuthenticationManager

    constructor(authenticationManager: AuthenticationManager) : super(authenticationManager)
    {
        this.authManager = authenticationManager
    }

    override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain)
    {
        ardaLogger.info("Filtro autenticação")
        val authentication = getAuthentication(request)
        if (authentication != null)
        {
            SecurityContextHolder.getContext().authentication = authentication
        }
        chain.doFilter(request, response)
    }

    private fun getAuthentication(request: HttpServletRequest): UsernamePasswordAuthenticationToken?
    {
        ardaLogger.info("Verificando autenticação")
        val authorizationHeader = request.getHeader(Constantes.AUTHORIZATION)
        if (authorizationHeader.isNullOrBlank())
        {
            return null
        } else
        {
            val token = authorizationHeader.replace("Bearer ", "")
            if (token.isNullOrBlank())
            {
                return null
            } else
            {
                try
                {
                    val signingKey = Constantes.SECRET_KEY.toByteArray(Charset.forName("UTF-8"))
                    val parsedToken = Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token)
                    val username = parsedToken.body.subject
                    val authoritiesList = parsedToken.body["rol"] as List<*>
                    val authorities = authoritiesList.stream().map { authority -> GrantedAuthority { authority as String } }.collect(Collectors.toList())
                    if (username.isNullOrBlank())
                    {
                        return null
                    } else
                    {
                        return UsernamePasswordAuthenticationToken(username, null, authorities)
                    }
                } catch (ex: ExpiredJwtException)
                {
                    ardaLogger.error("Token expirado: ${ex.message}", ex)
                } catch (ex: UnsupportedJwtException)
                {
                    ardaLogger.error("Jwt não suportado: ${ex.message}", ex)
                } catch (ex: MalformedJwtException)
                {
                    ardaLogger.error("Token inválido: ${ex.message}", ex)
                } catch (ex: SignatureException)
                {
                    ardaLogger.error("Assinatura inválida: ${ex.message}", ex)
                } catch (ex: Exception)
                {
                    ardaLogger.error("Erro desconhecido ou token vazio: ${ex.message}", ex)
                }
                return null
            }
        }
    }
}

WebSecurityConfig

override fun configure(http: HttpSecurity)
{
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    http.cors().configurationSource(corsConfiguration())
    http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll()
    http.addFilter(JWTAuthenticationFilter(authenticationManager()))
    http.addFilter(JWTAuthorizationFilter(authenticationManager()))
    http.authorizeRequests().antMatchers("/admin/user/**").permitAll()
    http.authorizeRequests().antMatchers("/asincor").permitAll()
    http.authorizeRequests().antMatchers("/asincor/**").permitAll()
    val regras = regraRepository.findAll()
    if (regras.isNotEmpty())
    {
        for (regra in regras)
        {
            http.authorizeRequests().antMatchers(regra.nome).hasAuthority(regra.role)
        }
    }
    http.authorizeRequests().anyRequest().authenticated()
    http.exceptionHandling().authenticationEntryPoint(ardaEntryPoint)
}

Consegui resolver desativando o CSRF, adicionando a seguinte configuração no WebSecurityConfig

http.csrf().disable()