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

Bearer token passa pelo postman, mas não por uma aplicação angular

Olá estou desenvolvendo uma aplicação tanto no front quanto no back-end. Implementei a parte de segurança da api, colocando validação por bearer token. O token é gerado normalmente tanto via postman quando pela aplicação front em angular. Quando o o bearer token é passado para o back-end no postman, usando a aba de authorization, funciona normal, porém quando o token é passado pelo header na requisição da aplicação angular(browser) o token não aparece no header do filtro no back-end(java spring boot). Fiz uma modificação e passei via parâmetro na requisição do angular e dessa forma deu certo. du gostaria de saber se posso manter dessa forma, ou o correto é passar via header e caso seja(isso em termos de segurança), como posso resolver esse problema. Segue abaixo as classes de segurança e validação da api. Desde já agradeço se alguém puder ajudar.

@Configuration
@EnableWebSecurity
public class SecurityConfig  extends WebSecurityConfigurerAdapter {


    @Autowired
    FilterToken filter;
    

    @Override
    protected void configure(HttpSecurity http) throws Exception {
         http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeRequests()
                .antMatchers( "/login/**").permitAll()
                 .antMatchers("/usuario/insert").permitAll()
                .anyRequest().authenticated()
                .and().addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);

    }

    @Bean
    public AuthenticationManager authenticationManager(
            AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }


}

Na classe do filtro fiz uma alteração para pegar o token para pegar tanto se vier do header quanto dos parâmetros

@Component
public class FilterToken extends OncePerRequestFilter {

    @Autowired
    ITokenService tokenService;

    @Autowired
    IUsuarioDao dao;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        String token;

        String authorizationHeader = request.getHeader("Authorization") == null ?
                request.getParameter("Authorization") : request.getHeader("Authorization");


        if(authorizationHeader != null){
            token = authorizationHeader.replace("Bearer ","");
            String subject = tokenService.getSubject(token);

            Usuario usuario = dao.findByEmail(subject);

            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(usuario,
                    null, usuario.getAuthorities());

            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        filterChain.doFilter(request,response);

    }
}

6 respostas

Olá Raphael,

Pelo que entendi, você está tendo problemas ao passar o bearer token pelo header na requisição da aplicação Angular. É importante lembrar que o token de autenticação deve ser passado no header da requisição, para garantir a segurança da sua aplicação.

Uma possível solução para o seu problema é verificar se o nome do header está correto na requisição Angular. O nome do header deve ser "Authorization" e o valor deve ser "Bearer " + token.

Caso o problema persista, pode ser necessário verificar se a sua aplicação Angular está enviando a requisição corretamente. Uma forma de fazer isso é utilizando o console do navegador para verificar se o header está sendo enviado corretamente.

Sobre a sua dúvida em relação à segurança, é importante lembrar que passar o token via parâmetro não é uma prática recomendada, pois pode deixar o seu token exposto na URL. Portanto, o ideal é passar o token pelo header da requisição.

Espero ter ajudado e bons estudos!

Olá Rodrigo, obrigado pelo retorno. Eu verifiquei e a aplicação angular está setando o Authorization no header, mas não está chegando na api. Eu li em um forum que o spring security precisa ser configurado quando há uma requisição via browser mas ainda não cheguei a uma solução

Precisa configurar o CORS na api backend, para que o frontend consiga se comunicar com ela. Verifica se está configurado o CORS no seu projeto backend

Acredito que tem um erro parecido ao seu. Dá uma olhada nesse link:

https://cursos.alura.com.br/forum/topico-cors-error-89874

Olá pessoal. Mais uma vez obrigado. Eu havia criado uma classe como vocês colocaram no exemplo para liberar o cors segue:

@Configuration
public class CorsConfiguration implements WebMvcConfigurer {


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

e também desabilitei no security config

@Configuration
@EnableWebSecurity
public class SecurityConfig  extends WebSecurityConfigurerAdapter {


    @Autowired
    FilterToken filter;
    

    @Override
    protected void configure(HttpSecurity http) throws Exception {
         http.csrf().disable()
                 .cors().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeRequests()
                .antMatchers( "/login/**").permitAll()
                 .antMatchers("/usuario/insert").permitAll()
                .anyRequest().authenticated()
                .and().addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);

    }

Dei print no console também e o bearer token está sendo setando no angular.

A requisição chega no filter, mas sem o bearer token no header. Ela chega assim no objeto:

=== MimeHeaders ===
host = localhost:5000
sec-fetch-site = same-site
accept-encoding = gzip, deflate
access-control-request-method = GET
sec-fetch-mode = cors
accept-language = en-GB,en-US;q=0.9,en;q=0.8
origin = http://localhost:4200
access-control-request-headers = access-control-allow-headers,authorization,content-type,x-access-token
user-agent = Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Safari/605.1.15
referer = http://localhost:4200/
content-length = 0
connection = keep-alive
sec-fetch-dest = empty
accept = */*

Quando é via postman, ela chega com o valor do header do authorization no header:

=== MimeHeaders ===
content-type = application/json
authorization = Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJyYXBoYV9wZmVpZmVyQHlhaG9vLmNvbS5iciIsImlzcyI6IlRDUyIsImlkIjoxLCJleHAiOjE2ODc4MDE0ODd9.3nGi9Rb7K_QchP6drhO6kVTYEbjxQDaykW91MO5urN4
user-agent = PostmanRuntime/7.32.3
accept = */*
postman-token = d4aea881-d332-4274-8ce0-30c2d202612b
host = localhost:5000
accept-encoding = gzip, deflate, br
connection = keep-alive
solução!

Olá pessoal. dei mais uma pesquisada e inclui na classe SecurityConfig uma linha para autorizar as requisições OPTIONS e isso aparentemente resolveu o problema.

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