The title is self explanatory, I have this API made in Spring, and after JWT implementation I can login, but the gets doesn't work anymore.
But if I comment the the CorsConfigurationSource corsConfigurationSource() and the Lombok annotation @RequiredArgsConstructor in SecurityConfig, the login stop to work, but all the gets work beautifully.
I'll post the class SecurityConfig, AuthorizationFilter and the AuthenticationFilter respectively for you guys try to see whats going wrong.
import org.alterdata.shopback.app.security.AuthenticationFilter;
import org.alterdata.shopback.app.security.AuthorizationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
UserDetailsService userDetailsService;
@Autowired
BCryptPasswordEncoder bCryptPasswordEncoder;
@Override
protected void configure(HttpSecurity http) throws Exception {
AuthenticationFilter authenticationFilter = new AuthenticationFilter(authenticationManagerBean());
http.cors().and().csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers("/login").permitAll()
.antMatchers("/cadastrar/**").hasAnyAuthority("ADMIN")
.antMatchers("/cadastro/**").hasAnyAuthority("ADMIN")
.anyRequest().authenticated();
http.addFilter(authenticationFilter);
http.addFilterBefore(new AuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
@Override
public AuthenticationManager authenticationManager()throws Exception{
return super.authenticationManager();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE","OPTIONS", "HEAD"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Arrays;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.auth0.jwt.exceptions.JWTVerificationException;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.bytebuddy.implementation.bind.annotation.IgnoreForBinding.Verifier;
import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;
@Slf4j
public class AuthorizationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if(request.getServletPath().equals("/login")) {
filterChain.doFilter(request, response);
}else {
String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
if(authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
try {
String token = authorizationHeader.substring("Bearer ".length());
Algorithm algorithm = Algorithm.HMAC256("segredinho".getBytes());
JWTVerifier jwtVerifier = JWT.require(algorithm).build();
DecodedJWT decodedJWT = jwtVerifier.verify(token);
String user = decodedJWT.getSubject();
String [] roles = decodedJWT.getClaim("roles").asArray(String.class);
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
Arrays.stream(roles).forEach(role ->{
authorities.add(new SimpleGrantedAuthority(role));
});
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user,null, authorities);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
filterChain.doFilter(request, response);
}catch(Exception e){
log.error("erro ao realizar o login! {}", e.getMessage());
response.setHeader("erro", e.getMessage());
response.setStatus(401);
Map<String, String> error = new HashMap<>();
error.put("mensagem de erro", e.getMessage());
response.setContentType(APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getOutputStream(), error);
}
}else {
filterChain.doFilter(request, response);
}
}
}
}
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import org.springframework.web.bind.annotation.CrossOrigin;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@CrossOrigin(origins = {"*"})
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
public AuthenticationFilter (AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
try{
String nome = request.getParameter("nome");
String senha = request.getParameter("senha");
UsernamePasswordAuthenticationToken uspsToken = new UsernamePasswordAuthenticationToken(nome, senha);
//response.setHeader("teste", String.valueOf(uspsToken));
return authenticationManager.authenticate(uspsToken);
}catch (Exception e){
throw new RuntimeException();
}
}
// @Override
// public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
// throws AuthenticationException {
// try{
// UserPasswordAuthRequest userPasswordAuthRequest = new ObjectMapper()
// .readValue(request.getInputStream(), UserPasswordAuthRequest.class);
//
// Authentication authentication = new UsernamePasswordAuthenticationToken(
// userPasswordAuthRequest.getNome(),
// userPasswordAuthRequest.getSenha()
// );
// return authenticationManager.authenticate(authentication);
// }catch (IOException e){
// throw new RuntimeException();
// }
// }
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
User user = (User) authResult.getPrincipal();
Algorithm algorithm = Algorithm.HMAC256("segredinho".getBytes());
String tokenAcesso = JWT.create().withSubject(user.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() 10*60*1000*60))
.withIssuer(request.getRequestURL()
.toString()).withClaim("roles", user.getAuthorities()
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
.sign(algorithm);
String tokenRefresh = JWT.create().withSubject(user.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() 10*60*1000*60))
.withIssuer(request.getRequestURL()
.toString()).withClaim("roles", user.getAuthorities()
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
.sign(algorithm);
Map<String, String> tokens = new HashMap<>();
tokens.put("tokenacesso", tokenAcesso);
tokens.put("tokenrefresh", tokenRefresh);
response.setContentType(APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getOutputStream(),tokens);
}
}
CodePudding user response:
First try to call your api with Postman, else i think you need to add authorization jwt header to every api request after you login.
export default function authHeader() {
const user = JSON.parse(localStorage.getItem('user'));
if (user && user.accessToken) {
return { Authorization: 'Bearer ' user.accessToken };
} else {
return {};
}
}
and then call your api like this:
return axios.get(API_URL 'user', { headers: authHeader() });
for more informations try to visit: https://www.bezkoder.com/react-jwt-auth/
CodePudding user response:
I just fixed using this global cors
@Bean
public CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}