Token's returns worked

This commit is contained in:
rayankonecny 2025-12-17 00:51:56 +00:00
parent ef8c2e8ca0
commit dbf9d46679
11 changed files with 103 additions and 66 deletions

View file

@ -23,10 +23,6 @@ configurations {
} }
} }
repositories {
mavenCentral()
}
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter'
compileOnly 'org.projectlombok:lombok' compileOnly 'org.projectlombok:lombok'
@ -40,3 +36,7 @@ dependencies {
tasks.named('test') { tasks.named('test') {
useJUnitPlatform() useJUnitPlatform()
} }
tasks.withType(org.springframework.boot.gradle.tasks.aot.ProcessAot).configureEach {
enabled = false
}

View file

@ -3,46 +3,35 @@ package br.com.rayankonecny.authserviceapi.configs;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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 org.springframework.security.web.SecurityFilterChain;
import static org.springframework.security.config.Customizer.withDefaults;
@Configuration @Configuration
public class SecurityConfig { public class SecurityConfig {
@Bean @Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http http.authorizeHttpRequests(auth -> auth.requestMatchers("/auth/login", "/v3/api-docs/**", "/swagger-ui/**",
.authorizeHttpRequests(auth -> auth "/swagger-ui.html", "/swagger-ui/index.html").permitAll().anyRequest().authenticated())
// AUTH
.requestMatchers("/auth/login").permitAll()
// SWAGGER / OPENAPI // API pura sem Basic
.requestMatchers( .httpBasic(httpBasic -> httpBasic.disable())
"/v3/api-docs/**",
"/swagger-ui/**",
"/swagger-ui.html",
"/swagger-ui/index.html"
).permitAll()
// TODO o resto protegido // Stateless (JWT)
.anyRequest().authenticated() .csrf(csrf -> csrf.disable())
)
// API pura sem Basic // Sem sessão
.httpBasic(httpBasic -> httpBasic.disable()) .sessionManagement(session -> session.sessionCreationPolicy(
org.springframework.security.config.http.SessionCreationPolicy.STATELESS));
// Stateless (JWT)
.csrf(csrf -> csrf.disable())
// Sem sessão
.sessionManagement(session ->
session.sessionCreationPolicy(
org.springframework.security.config.http.SessionCreationPolicy.STATELESS
)
);
return http.build(); return http.build();
} }
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
} }

View file

@ -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.exceptions.StandardError;
import br.com.rayankonecny.hdcommoslib.models.requests.AuthenticateRequest; import br.com.rayankonecny.hdcommoslib.models.requests.AuthenticateRequest;
import br.com.rayankonecny.hdcommoslib.models.responses.AuthenticationResponse; 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.Operation;
import io.swagger.v3.oas.annotations.media.Content; 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.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.media.Schema; 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; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@RequestMapping("/auth") @RequestMapping("/auth")
public interface AuthController { 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 = "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 = "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 = "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") @PostMapping("/login")
ResponseEntity<AuthenticationResponse> authenticate(@Valid @RequestBody final AuthenticateRequest requests) throws Exception; ResponseEntity<AuthenticationResponse> authenticate(@RequestBody
@Valid
final AuthenticateRequest requests) throws Exception;
} }

View file

@ -1,27 +1,26 @@
package br.com.rayankonecny.authserviceapi.controllers.impl; package br.com.rayankonecny.authserviceapi.controllers.impl;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import br.com.rayankonecny.authserviceapi.controllers.AuthController; import br.com.rayankonecny.authserviceapi.controllers.AuthController;
import br.com.rayankonecny.authserviceapi.security.JWTAuthenticationImpl; import br.com.rayankonecny.authserviceapi.services.AuthService;
import br.com.rayankonecny.authserviceapi.utils.JWTUtils;
import br.com.rayankonecny.hdcommoslib.models.requests.AuthenticateRequest; import br.com.rayankonecny.hdcommoslib.models.requests.AuthenticateRequest;
import br.com.rayankonecny.hdcommoslib.models.responses.AuthenticationResponse; import br.com.rayankonecny.hdcommoslib.models.responses.AuthenticationResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
public class AuthControllerImpl implements AuthController { public class AuthControllerImpl implements AuthController {
private final JWTUtils jwtUtils; private final AuthService authService;
private final AuthenticationConfiguration authenticationConfiguration;
@Override @Override
public ResponseEntity<AuthenticationResponse> authenticate(final AuthenticateRequest requests) throws Exception { public ResponseEntity<AuthenticationResponse> authenticate(@Valid
return ResponseEntity.ok().body( AuthenticateRequest request) {
new JWTAuthenticationImpl(jwtUtils, authenticationConfiguration.getAuthenticationManager()).authentication(requests));
return ResponseEntity.ok(authService.authenticate(request));
} }
} }

View file

@ -2,15 +2,21 @@ package br.com.rayankonecny.authserviceapi.models;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.Set; 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; import br.com.rayankonecny.hdcommoslib.models.enums.ProfileEnum;
@Getter @Getter
@AllArgsConstructor @NoArgsConstructor
@Document(collection = "user")
public class User { public class User {
@Id
private String id; private String id;
private String name; private String name;
private String email; private String email;

View file

@ -6,11 +6,13 @@ import java.util.Collection;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
@Getter @Getter
@Builder @Builder
@AllArgsConstructor
public class UserDetailsDTO implements UserDetails { public class UserDetailsDTO implements UserDetails {
@Serial @Serial
@ -18,13 +20,13 @@ public class UserDetailsDTO implements UserDetails {
private String id; private String id;
private String name; private String name;
private String username; private String email;
private String password; private String password;
private Collection<? extends GrantedAuthority> authorities; private Collection<? extends GrantedAuthority> authorities;
@Override @Override
public Collection<? extends GrantedAuthority> getAuthorities() { public String getUsername() {
return this.authorities; return this.email; // 🔥 FUNDAMENTAL
} }
@Override @Override
@ -33,15 +35,10 @@ public class UserDetailsDTO implements UserDetails {
} }
@Override @Override
public String getUsername() { public Collection<? extends GrantedAuthority> getAuthorities() {
return this.username; return this.authorities;
} }
public String getName() {
return this.name;
}
@Override @Override
public boolean isAccountNonExpired() { public boolean isAccountNonExpired() {
return true; return true;
@ -52,4 +49,13 @@ public class UserDetailsDTO implements UserDetails {
return true; return true;
} }
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
} }

View file

@ -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());
}
}

View file

@ -0,0 +1,5 @@
package br.com.rayankonecny.authserviceapi.services;
public class BadCredentialsExceptionion {
}

View file

@ -1,10 +1,8 @@
package br.com.rayankonecny.authserviceapi.services; package br.com.rayankonecny.authserviceapi.services;
import java.util.stream.Collector;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.security.core.authority.SimpleGrantedAuthority; 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.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -20,7 +18,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
private final UserRepository repository; private final UserRepository repository;
@Override @Override
public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException { public UserDetailsDTO loadUserByUsername(final String email) throws UsernameNotFoundException {
final var entity = repository.findByEmail(email) final var entity = repository.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("User not found: " + email)); .orElseThrow(() -> new UsernameNotFoundException("User not found: " + email));
@ -28,7 +26,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
return UserDetailsDTO.builder() return UserDetailsDTO.builder()
.id(entity.getId()) .id(entity.getId())
.name(entity.getName()) .name(entity.getName())
.username(entity.getEmail()) .email(entity.getEmail())
.password(entity.getPassword()) .password(entity.getPassword())
.authorities(entity.getProfiles().stream().map(x -> new SimpleGrantedAuthority(x.getDescription())).collect(Collectors.toSet())) .authorities(entity.getProfiles().stream().map(x -> new SimpleGrantedAuthority(x.getDescription())).collect(Collectors.toSet()))
.build(); .build();

View file

@ -19,12 +19,12 @@ public class JWTUtils {
@Value("${jwt.expiration}") @Value("${jwt.expiration}")
private Long expiration; private Long expiration;
public String generateToken(final UserDetailsDTO dto) { public String generateToken(final UserDetailsDTO user) {
return Jwts.builder() return Jwts.builder()
.claim("id", dto.getId()) .claim("id", user.getId())
.claim("name", dto.getName()) .claim("name", user.getName())
.claim("authorities", dto.getAuthorities()) .claim("authorities", user.getAuthorities())
.setSubject(dto.getUsername()) .setSubject(user.getUsername())
.signWith(SignatureAlgorithm.HS512, secret.getBytes()) .signWith(SignatureAlgorithm.HS512, secret.getBytes())
.setExpiration(new Date(System.currentTimeMillis()+ expiration)) .setExpiration(new Date(System.currentTimeMillis()+ expiration))
.compact(); .compact();

View file

@ -5,6 +5,7 @@ spring:
mongodb: mongodb:
uri: mongodb://175.15.15.6:27017/olympdb uri: mongodb://175.15.15.6:27017/olympdb
auto-index-creation: true auto-index-creation: true
aot:
enabled: false
jwt.secret: "IHf3Yua/byvtA+iIcGWmkrLvpKEXTb5ClkXaZ0VDmYbr/6b1otCs38x68bidvZLAOB7anUtVQlCid6YDULO5XA==" jwt.secret: "IHf3Yua/byvtA+iIcGWmkrLvpKEXTb5ClkXaZ0VDmYbr/6b1otCs38x68bidvZLAOB7anUtVQlCid6YDULO5XA=="
jwt.expiration: 120000 jwt.expiration: 120000