Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

Não estou conseguindo validar o token usando um client em angular

Primeiramente, muito bom o curso.

Estou usando a api do curso, um pouco customizada com novos endpoints para receber requisições de um cliente angular.

Pelo que estou percebendo, o token está indo sim na requisição. No entanto, ele está chegando como null no spring boot. É como ele estivesse ignorando o cabeçalho "Authorization". Quando tento fazer a requisição via o swagger, tudo funciona.

Estou adaptando o famoso projeto do petclinic-rest para usar jwt para aprender. Todo o código está neste repositório: https://github.com/emerson-diego/spring-petclinic-rest

Até comentei o @CrossOrigin em cima das classes do endpoint e adicionei a seguinte classe abaixo, mas não funcionou:

public class CorsConfiguration implements WebMvcConfigurer {

    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**").allowedOrigins("http://localhost:4200/**")
                .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS").exposedHeaders("Authorization");
    }
}
5 respostas

Fiz alguns ajustes e agora está funcionando. Eu verifiquei que o método que estava chegando no spring era do tipo "OPTIONS", por mais que eu realmente estivesse enviando um "GET" no lado Angular.

Sendo assim, acrescentei a seguinte permissão na configuração do spring security:

.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()

Via debug, verifiquei que o filtro do spring estava sendo invocado duas vezes, sendo uma com a requisição do tipo "OPTIONS" e o token vindo nulo e outra vindo a "GET" normal com o token.

Eu até exclui a classe CorsConfiguration, pois ela, aparentemente, não estava servindo para nada.

De toda forma, gostaria de explicação, se possível, do motivo do filtro estar sendo invocado duas vezes.

O commit com as mudanças estão em: https://github.com/emerson-diego/spring-petclinic-rest/commit/a08f408e4334cc7d3a2486c35817c648d6cd1b6a

solução!

Olá!

Como são 2 aplicações distintas(front Angular e api Spring) e as requisições feitas do Angular são via JavaScript, o browser considera que são requisições Cross-Origin.

Nesse caso o comportamento padrão do browser é sempre enviar antes da requisição em si, uma outra requisição do tipo Options, para que o servidor devolva os cabeçalhos CORS(Access-Control-Allow-Origin e Access-Control-Allow-Methods) e se o endereço e método a ser chamado pelo client for permitido, o browser então envia a requisição original.

É por isso que o Filter de autenticação está sendo chamado 2 vezes(uma para a requisição Options e outra para a requisição GET), sendo que na requisição Options o header Authorization não é enviado, chegando null no filter.

Para evitar que a requisição options seja interceptada pelo Spring Security, devemos adicionar a seguinte configuração no método configure, da classe SecurityConfigurations:

//codigo anterior omitido
.anyRequest().authenticated()
.and().cors()
.and().csrf().disable()
//codigo restante omitido

E também precisa da classe CorsConfiguration no projeto, lembrando que ela precisar estar anotada com @Configuration:

@Configuration
public class CorsConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedOrigins("http://localhost:4200")
            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "TRACE", "CONNECT");
    }
}

Bons estudos!

Perfeito, deu certo.

Se possível, poderia me passar uma indicação de livro? Sempre trabalhei com JAVA EE, mas gostaria de começar a estudar spring mais a fundo.

Obrigado.