diff --git a/auth-service-api/build.gradle b/auth-service-api/build.gradle index 976c35d..c764dd0 100644 --- a/auth-service-api/build.gradle +++ b/auth-service-api/build.gradle @@ -23,10 +23,6 @@ configurations { } } -repositories { - mavenCentral() -} - dependencies { implementation 'org.springframework.boot:spring-boot-starter' compileOnly 'org.projectlombok:lombok' @@ -40,3 +36,7 @@ dependencies { tasks.named('test') { useJUnitPlatform() } + +tasks.withType(org.springframework.boot.gradle.tasks.aot.ProcessAot).configureEach { + enabled = false +} \ No newline at end of file diff --git a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/configs/SecurityConfig.java b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/configs/SecurityConfig.java index 3771c36..aec922b 100644 --- a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/configs/SecurityConfig.java +++ b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/configs/SecurityConfig.java @@ -3,46 +3,35 @@ package br.com.rayankonecny.authserviceapi.configs; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; -import static org.springframework.security.config.Customizer.withDefaults; - @Configuration public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http - .authorizeHttpRequests(auth -> auth - // AUTH - .requestMatchers("/auth/login").permitAll() + http.authorizeHttpRequests(auth -> auth.requestMatchers("/auth/login", "/v3/api-docs/**", "/swagger-ui/**", + "/swagger-ui.html", "/swagger-ui/index.html").permitAll().anyRequest().authenticated()) - // SWAGGER / OPENAPI - .requestMatchers( - "/v3/api-docs/**", - "/swagger-ui/**", - "/swagger-ui.html", - "/swagger-ui/index.html" - ).permitAll() + // API pura → sem Basic + .httpBasic(httpBasic -> httpBasic.disable()) - // TODO o resto protegido - .anyRequest().authenticated() - ) + // Stateless (JWT) + .csrf(csrf -> csrf.disable()) - // API pura → sem Basic - .httpBasic(httpBasic -> httpBasic.disable()) - - // Stateless (JWT) - .csrf(csrf -> csrf.disable()) - - // Sem sessão - .sessionManagement(session -> - session.sessionCreationPolicy( - org.springframework.security.config.http.SessionCreationPolicy.STATELESS - ) - ); + // Sem sessão + .sessionManagement(session -> session.sessionCreationPolicy( + org.springframework.security.config.http.SessionCreationPolicy.STATELESS)); return http.build(); } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + } diff --git a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/controllers/AuthController.java b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/controllers/AuthController.java index 326a88d..e6beb05 100644 --- a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/controllers/AuthController.java +++ b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/controllers/AuthController.java @@ -7,9 +7,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import br.com.rayankonecny.hdcommoslib.models.exceptions.StandardError; import br.com.rayankonecny.hdcommoslib.models.requests.AuthenticateRequest; import br.com.rayankonecny.hdcommoslib.models.responses.AuthenticationResponse; +import org.springframework.web.bind.annotation.RequestBody; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.media.Schema; @@ -17,7 +17,6 @@ import jakarta.validation.Valid; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; - @RequestMapping("/auth") public interface AuthController { @@ -27,9 +26,10 @@ public interface AuthController { @ApiResponse(responseCode = "400", description = "Bad request", content = @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = StandardError.class))), @ApiResponse(responseCode = "401", description = "Bad credentials", content = @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = StandardError.class))), @ApiResponse(responseCode = "404", description = "Username not found", content = @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = StandardError.class))), - @ApiResponse(responseCode = "500", description = "Internal server error", content = @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = StandardError.class))), - }) + @ApiResponse(responseCode = "500", description = "Internal server error", content = @Content(mediaType = APPLICATION_JSON_VALUE, schema = @Schema(implementation = StandardError.class))), }) @PostMapping("/login") - ResponseEntity authenticate(@Valid @RequestBody final AuthenticateRequest requests) throws Exception; + ResponseEntity authenticate(@RequestBody + @Valid + final AuthenticateRequest requests) throws Exception; } diff --git a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/controllers/impl/AuthControllerImpl.java b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/controllers/impl/AuthControllerImpl.java index 0b78ab3..b3183cc 100644 --- a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/controllers/impl/AuthControllerImpl.java +++ b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/controllers/impl/AuthControllerImpl.java @@ -1,27 +1,26 @@ package br.com.rayankonecny.authserviceapi.controllers.impl; import org.springframework.http.ResponseEntity; -import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.web.bind.annotation.RestController; import br.com.rayankonecny.authserviceapi.controllers.AuthController; -import br.com.rayankonecny.authserviceapi.security.JWTAuthenticationImpl; -import br.com.rayankonecny.authserviceapi.utils.JWTUtils; +import br.com.rayankonecny.authserviceapi.services.AuthService; import br.com.rayankonecny.hdcommoslib.models.requests.AuthenticateRequest; import br.com.rayankonecny.hdcommoslib.models.responses.AuthenticationResponse; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @RestController @RequiredArgsConstructor public class AuthControllerImpl implements AuthController { - private final JWTUtils jwtUtils; - private final AuthenticationConfiguration authenticationConfiguration; + private final AuthService authService; @Override - public ResponseEntity authenticate(final AuthenticateRequest requests) throws Exception { - return ResponseEntity.ok().body( - new JWTAuthenticationImpl(jwtUtils, authenticationConfiguration.getAuthenticationManager()).authentication(requests)); + public ResponseEntity authenticate(@Valid + AuthenticateRequest request) { + + return ResponseEntity.ok(authService.authenticate(request)); } } diff --git a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/models/User.java b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/models/User.java index ea0939a..40d8bd9 100644 --- a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/models/User.java +++ b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/models/User.java @@ -2,15 +2,21 @@ package br.com.rayankonecny.authserviceapi.models; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import java.util.Set; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + import br.com.rayankonecny.hdcommoslib.models.enums.ProfileEnum; @Getter -@AllArgsConstructor +@NoArgsConstructor +@Document(collection = "user") public class User { + @Id private String id; private String name; private String email; diff --git a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/security/UserDetailsDTO.java b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/security/UserDetailsDTO.java index afa0100..725bb4a 100644 --- a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/security/UserDetailsDTO.java +++ b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/security/UserDetailsDTO.java @@ -6,11 +6,13 @@ import java.util.Collection; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @Getter @Builder +@AllArgsConstructor public class UserDetailsDTO implements UserDetails { @Serial @@ -18,13 +20,13 @@ public class UserDetailsDTO implements UserDetails { private String id; private String name; - private String username; + private String email; private String password; private Collection authorities; @Override - public Collection getAuthorities() { - return this.authorities; + public String getUsername() { + return this.email; // 🔥 FUNDAMENTAL } @Override @@ -33,15 +35,10 @@ public class UserDetailsDTO implements UserDetails { } @Override - public String getUsername() { - return this.username; + public Collection getAuthorities() { + return this.authorities; } - public String getName() { - return this.name; - } - - @Override public boolean isAccountNonExpired() { return true; @@ -52,4 +49,13 @@ public class UserDetailsDTO implements UserDetails { return true; } + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } } diff --git a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/services/AuthService.java b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/services/AuthService.java new file mode 100644 index 0000000..ebf1bda --- /dev/null +++ b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/services/AuthService.java @@ -0,0 +1,33 @@ +package br.com.rayankonecny.authserviceapi.services; + +import org.springframework.security.authentication.BadCredentialsException; + +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import br.com.rayankonecny.authserviceapi.utils.JWTUtils; +import br.com.rayankonecny.hdcommoslib.models.requests.AuthenticateRequest; +import br.com.rayankonecny.hdcommoslib.models.responses.AuthenticationResponse; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class AuthService { + + private final UserDetailsServiceImpl userDetailsService; + private final PasswordEncoder passwordEncoder; + private final JWTUtils jwtUtils; + + public AuthenticationResponse authenticate(AuthenticateRequest request) { + + var user = userDetailsService.loadUserByUsername(request.email()); + + if (!passwordEncoder.matches(request.password(), user.getPassword())) { + throw new BadCredentialsException("Invalid credentials"); + } + + String token = jwtUtils.generateToken(user); + + return new AuthenticationResponse(token,user.getUsername()); + } +} diff --git a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/services/BadCredentialsExceptionion.java b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/services/BadCredentialsExceptionion.java new file mode 100644 index 0000000..caa8480 --- /dev/null +++ b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/services/BadCredentialsExceptionion.java @@ -0,0 +1,5 @@ +package br.com.rayankonecny.authserviceapi.services; + +public class BadCredentialsExceptionion { + +} diff --git a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/services/UserDetailsServiceImpl.java b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/services/UserDetailsServiceImpl.java index 0037ff1..2581771 100644 --- a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/services/UserDetailsServiceImpl.java +++ b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/services/UserDetailsServiceImpl.java @@ -1,10 +1,8 @@ package br.com.rayankonecny.authserviceapi.services; -import java.util.stream.Collector; import java.util.stream.Collectors; import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; @@ -20,7 +18,7 @@ public class UserDetailsServiceImpl implements UserDetailsService { private final UserRepository repository; @Override - public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException { + public UserDetailsDTO loadUserByUsername(final String email) throws UsernameNotFoundException { final var entity = repository.findByEmail(email) .orElseThrow(() -> new UsernameNotFoundException("User not found: " + email)); @@ -28,7 +26,7 @@ public class UserDetailsServiceImpl implements UserDetailsService { return UserDetailsDTO.builder() .id(entity.getId()) .name(entity.getName()) - .username(entity.getEmail()) + .email(entity.getEmail()) .password(entity.getPassword()) .authorities(entity.getProfiles().stream().map(x -> new SimpleGrantedAuthority(x.getDescription())).collect(Collectors.toSet())) .build(); diff --git a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/utils/JWTUtils.java b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/utils/JWTUtils.java index 3706391..e507912 100644 --- a/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/utils/JWTUtils.java +++ b/auth-service-api/src/main/java/br/com/rayankonecny/authserviceapi/utils/JWTUtils.java @@ -19,12 +19,12 @@ public class JWTUtils { @Value("${jwt.expiration}") private Long expiration; - public String generateToken(final UserDetailsDTO dto) { + public String generateToken(final UserDetailsDTO user) { return Jwts.builder() - .claim("id", dto.getId()) - .claim("name", dto.getName()) - .claim("authorities", dto.getAuthorities()) - .setSubject(dto.getUsername()) + .claim("id", user.getId()) + .claim("name", user.getName()) + .claim("authorities", user.getAuthorities()) + .setSubject(user.getUsername()) .signWith(SignatureAlgorithm.HS512, secret.getBytes()) .setExpiration(new Date(System.currentTimeMillis()+ expiration)) .compact(); diff --git a/auth-service-api/src/main/resources/application.yml b/auth-service-api/src/main/resources/application.yml index 83a5098..4636bec 100644 --- a/auth-service-api/src/main/resources/application.yml +++ b/auth-service-api/src/main/resources/application.yml @@ -5,6 +5,7 @@ spring: mongodb: uri: mongodb://175.15.15.6:27017/olympdb auto-index-creation: true - + aot: + enabled: false jwt.secret: "IHf3Yua/byvtA+iIcGWmkrLvpKEXTb5ClkXaZ0VDmYbr/6b1otCs38x68bidvZLAOB7anUtVQlCid6YDULO5XA==" jwt.expiration: 120000