package it.bgates.remotebe.service.auth; import com.fasterxml.jackson.databind.ObjectMapper; import it.bgates.remotebe.config.BGatesUserDetailService; import it.bgates.remotebe.config.BGatesUserDetails; import it.bgates.remotebe.config.JwtService; import it.bgates.remotebe.controller.auth.beans.AuthenticationRequest; import it.bgates.remotebe.controller.auth.beans.AuthenticationResponse; import it.bgates.remotebe.controller.auth.beans.RefreshTokenRequest; import it.bgates.remotebe.entities.Role; import it.bgates.remotebe.entities.User; import it.bgates.remotebe.entities.token.RefreshToken; import it.bgates.remotebe.entities.token.Token; import it.bgates.remotebe.entities.token.TokenRepository; import it.bgates.remotebe.exception.AutorizationMissingException; import it.bgates.remotebe.exception.DisabledUserException; import it.bgates.remotebe.exception.UserNotFoundException; import it.bgates.remotebe.service.UserService; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpHeaders; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.stereotype.Service; import java.io.IOException; import java.security.Principal; import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class AuthService { private final BGatesUserDetailService authenticationProvider; private final JwtService jwtService; private final BGatesUserDetailService userDetailsService; private final TokenRepository tokenRepository; private final RefreshTokenService refreshTokenService; private final UserService userService; /*** * * @param request (username, password) * @return AuthenticationResponse con dettagli per l'autenticazione * accessToken, refreshToken, expirationTime, ... */ public AuthenticationResponse authenticate(AuthenticationRequest request) throws AuthenticationException, DisabledUserException, UserNotFoundException { Authentication authentication = authenticationProvider.authenticate( new UsernamePasswordAuthenticationToken( request.getUsername(), request.getPassword() ) ); // recupera utente UserDetails userDetails = (UserDetails) authentication.getPrincipal(); Optional user = userService.findByUsername(userDetails.getUsername()); if (user.isEmpty()) { throw new UserNotFoundException("User not found"); } if (!user.get().getEnabled()) { throw new DisabledUserException("User not enabled"); } var jwtToken = jwtService.generateToken(userDetails); var refreshToken = jwtService.generateRefreshToken(userDetails); revokeAllUserTokens(userDetails); saveUserToken(userDetails, jwtToken); List roles = user.get().getRoles().stream() .map(Role::getName) .collect(Collectors.toList()); List authorities = new ArrayList<>(); for (Role role: user.get().getRoles()) { role.getPrivileges().forEach(privilege -> authorities.add(privilege.getName())); } return AuthenticationResponse.builder() .accessToken(jwtToken) .refreshToken(refreshToken) .username(userDetails.getUsername()) .authorities(authorities) .roles(roles) .build(); } /*** * Logout user * @param name */ public void logout(String name) { tokenRepository.findAllValidTokenByUser(name).forEach(token -> { token.setRevoked(true); token.setExpired(true); tokenRepository.save(token); }); } private void saveUserToken(UserDetails user, String jwtToken) { var token = Token.builder() .username(user.getUsername()) .token(jwtToken) .expired(false) .revoked(false) .build(); tokenRepository.save(token); } private void revokeAllUserTokens(UserDetails user) { var validUserTokens = tokenRepository.findAllValidTokenByUser(user.getUsername()); if (validUserTokens.isEmpty()) return; validUserTokens.forEach(token -> { token.setExpired(true); token.setRevoked(true); }); tokenRepository.saveAll(validUserTokens); } public void refreshToken( HttpServletRequest request, HttpServletResponse response ) throws IOException { final String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION); final String refreshToken; final String username; if (authHeader == null ||!authHeader.startsWith("Bearer ")) { return; } refreshToken = authHeader.substring(7); username = jwtService.extractUsername(refreshToken); if (username != null) { BGatesUserDetails userDetails = userDetailsService.loadUserByUsername(username); if (jwtService.isTokenValid(refreshToken, userDetails)) { var accessToken = jwtService.generateToken(userDetails); revokeAllUserTokens(userDetails); saveUserToken(userDetails, accessToken); var authResponse = AuthenticationResponse.builder() .accessToken(accessToken) .refreshToken(refreshToken) .username(username) .build(); new ObjectMapper().writeValue(response.getOutputStream(), authResponse); } } } @org.springframework.transaction.annotation.Transactional(readOnly = true) public BGatesUserDetails getCurrentUser() { // System.out.println(SecurityContextHolder.getContext().getAuthentication().getPrincipal()); BGatesUserDetails principal = (BGatesUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); return userDetailsService.loadUserByUsername(principal.getUsername()); } }