after a lot of research i've found this and it is working
first i've created a Authorization filter like this :
package com.example.bda_test_11.security;
import com.example.bda_test_11.model.BdaUser;
import com.example.bda_test_11.model.Token;
import com.example.bda_test_11.repository.TokenRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
public class AuthorizationFilter extends BasicAuthenticationFilter {
private final TokenRepository tokenRepository;
public AuthorizationFilter(AuthenticationManager authenticationManager,TokenRepository tokenRepository) {
super(authenticationManager);
this.tokenRepository = tokenRepository;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String tokenCode = request.getHeader(HttpHeaders.AUTHORIZATION);
log.info(tokenCode);
if(tokenCode == null ) {
filterChain.doFilter(request,response);
return;
}
Token token = tokenRepository.findByCode(tokenCode).orElse(null);
if (token == null) {
filterChain.doFilter(request,response);
return;
}
BdaUser user = token.getUser();
UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken(user.getLogin(),null,user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(userToken);
filterChain.doFilter(request,response);
}
}
and a UsernamePasswordAuthenticationFilter like this
package com.example.bda_test_11.security;
import com.example.bda_test_11.security.domain.LoginCredentials;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
@Slf4j
public class JsonObjectAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
try{
BufferedReader reader = request.getReader();
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line=reader.readLine())!=null){
stringBuilder.append(line);
}
LoginCredentials authRequest = objectMapper.readValue(stringBuilder.toString(),LoginCredentials.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
authRequest.getLogin(),
authRequest.getPassword()
);
setDetails(request,token);
log.info(token.toString());
return this.getAuthenticationManager().authenticate(token);
} catch (IOException e){
throw new RuntimeException(e);
}
}
}
if the connection is successful we generate a token like :
package com.example.bda_test_11.security;
import com.example.bda_test_11.model.BdaUser;
import com.example.bda_test_11.model.Token;
import com.example.bda_test_11.repository.TokenRepository;
import com.example.bda_test_11.service.BdaUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j @Component
public class AuthSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private final TokenRepository tokenRepository;
private final BdaUserService userService;
@Autowired
public AuthSuccessHandler(TokenRepository tokenRepository, BdaUserService userService) {
this.tokenRepository = tokenRepository;
this.userService = userService;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
UserDetails principal = (UserDetails) authentication.getPrincipal();
BdaUser user = userService.findByLogin(principal.getUsername());
Token token = new Token(user);
tokenRepository.save(token);
log.info(token.getCode());
response.addHeader("Authorization",token.getCode());
response.addHeader("Content-Type","application/json");
response.getWriter().write("{\"token\":"+token.getCode()+",\"login\":"+user.getLogin());
}
}
and then ive configured the filterChain bean like this
package com.example.bda_test_11.security;
import com.example.bda_test_11.repository.TokenRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
@Configuration
public class BdaSecurity {
private final AuthenticationManager authenticationManager;
private final AuthSuccessHandler authSuccessHandler;
private final TokenRepository tokenRepository;
@Autowired
public BdaSecurity(AuthenticationManager authenticationManager, AuthSuccessHandler authSuccessHandler, TokenRepository tokenRepository) {
this.authenticationManager = authenticationManager;
this.authSuccessHandler = authSuccessHandler;
this.tokenRepository = tokenRepository;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.authorizeHttpRequests((auth)->{
try {
auth
.antMatchers("/api/admin").hasAuthority("ADMIN")
.antMatchers("/api/user").hasAuthority("USER")
.anyRequest().permitAll()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(authenticationFilter())
.addFilter(new AuthorizationFilter(authenticationManager,tokenRepository))
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
} catch (Exception e) {
throw new RuntimeException(e);
}
})
.httpBasic(Customizer.withDefaults());
return http.build();
}
@Bean
public JsonObjectAuthenticationFilter authenticationFilter() {
JsonObjectAuthenticationFilter filter = new JsonObjectAuthenticationFilter();
filter.setAuthenticationSuccessHandler(authSuccessHandler);
filter.setAuthenticationManager(authenticationManager);
return filter;
}
}