-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
89c6500
commit f2f7574
Showing
17 changed files
with
456 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...ucasmoraist/gateway/RestClientConfig.java → ...gateway/config/rest/RestClientConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
gateway/src/main/java/com/lucasmoraist/gateway/config/security/SecurityConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.lucasmoraist.gateway.config.security; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.http.HttpMethod; | ||
import org.springframework.security.authentication.AuthenticationManager; | ||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; | ||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||
import org.springframework.security.config.http.SessionCreationPolicy; | ||
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.authentication.UsernamePasswordAuthenticationFilter; | ||
|
||
@Configuration | ||
@EnableWebSecurity | ||
public class SecurityConfig { | ||
|
||
@Autowired | ||
SecurityFilter securityFilter; | ||
|
||
@Bean | ||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { | ||
http | ||
.csrf(csrf -> csrf.disable()) | ||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) | ||
.authorizeHttpRequests(authorize -> authorize | ||
.requestMatchers(HttpMethod.POST, "/auth/login").permitAll() | ||
.requestMatchers(HttpMethod.POST, "/auth/register").permitAll() | ||
.anyRequest().authenticated() | ||
) | ||
.addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class); | ||
return http.build(); | ||
} | ||
|
||
@Bean | ||
public PasswordEncoder passwordEncoder() { | ||
return new BCryptPasswordEncoder(); | ||
} | ||
|
||
@Bean | ||
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { | ||
return authenticationConfiguration.getAuthenticationManager(); | ||
} | ||
|
||
} |
47 changes: 47 additions & 0 deletions
47
gateway/src/main/java/com/lucasmoraist/gateway/config/security/SecurityFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package com.lucasmoraist.gateway.config.security; | ||
|
||
import com.lucasmoraist.gateway.domain.entity.User; | ||
import com.lucasmoraist.gateway.repository.UserRepository; | ||
import com.lucasmoraist.gateway.service.TokenService; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import java.io.IOException; | ||
import java.util.Collections; | ||
|
||
@Component | ||
public class SecurityFilter extends OncePerRequestFilter { | ||
|
||
@Autowired | ||
private TokenService tokenService; | ||
@Autowired | ||
private UserRepository userRepository; | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) throws ServletException, IOException { | ||
var token = this.recoverToken(req); | ||
var login = tokenService.validateToken(token); | ||
if(login != null){ | ||
User user = userRepository.findByEmail(login).orElseThrow(() -> new RuntimeException("User Not Found")); | ||
var authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")); | ||
var authentication = new UsernamePasswordAuthenticationToken(user, null, authorities); | ||
SecurityContextHolder.getContext().setAuthentication(authentication); | ||
} | ||
filterChain.doFilter(req, res); | ||
} | ||
|
||
private String recoverToken(HttpServletRequest request){ | ||
var authHeader = request.getHeader("Authorization"); | ||
if(authHeader == null) return null; | ||
return authHeader.replace("Bearer ", ""); | ||
} | ||
|
||
} |
38 changes: 38 additions & 0 deletions
38
gateway/src/main/java/com/lucasmoraist/gateway/controller/UserController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.lucasmoraist.gateway.controller; | ||
|
||
import com.lucasmoraist.gateway.domain.dto.TokenDTO; | ||
import com.lucasmoraist.gateway.domain.model.LoginRequest; | ||
import com.lucasmoraist.gateway.domain.model.RegisterRequest; | ||
import com.lucasmoraist.gateway.service.UserService; | ||
import jakarta.validation.Valid; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@Slf4j | ||
@RestController | ||
@RequestMapping("/auth") | ||
public class UserController { | ||
|
||
@Autowired | ||
private UserService service; | ||
|
||
@PostMapping("register") | ||
public ResponseEntity<TokenDTO> register(@Valid @RequestBody RegisterRequest request) throws Exception { | ||
this.service.register(request); | ||
log.info("Registering"); | ||
return ResponseEntity.ok().build(); | ||
} | ||
|
||
@PostMapping("login") | ||
public ResponseEntity<TokenDTO> login(@Valid @RequestBody LoginRequest request) throws Exception { | ||
var response = this.service.login(request); | ||
log.info("Logging in"); | ||
return ResponseEntity.ok().body(response); | ||
} | ||
|
||
} |
4 changes: 4 additions & 0 deletions
4
gateway/src/main/java/com/lucasmoraist/gateway/domain/dto/TokenDTO.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package com.lucasmoraist.gateway.domain.dto; | ||
|
||
public record TokenDTO(String token) { | ||
} |
42 changes: 42 additions & 0 deletions
42
gateway/src/main/java/com/lucasmoraist/gateway/domain/entity/User.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.lucasmoraist.gateway.domain.entity; | ||
|
||
import com.lucasmoraist.gateway.domain.model.LoginRequest; | ||
import com.lucasmoraist.gateway.domain.model.RegisterRequest; | ||
import jakarta.persistence.*; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Data | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@Builder | ||
@Entity(name = "t_user") | ||
@Table(name = "t_user") | ||
public class User { | ||
|
||
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(nullable = false, length = 80) | ||
private String name; | ||
|
||
@Column(nullable = false, length = 255, unique = true) | ||
private String email; | ||
|
||
@Column(nullable = false, length = 20) | ||
private String password; | ||
|
||
public User(RegisterRequest request) { | ||
this.name = request.getName(); | ||
this.email = request.getEmail(); | ||
this.password = request.getPassword(); | ||
} | ||
|
||
public User(LoginRequest request) { | ||
this.email = request.getEmail(); | ||
this.password = request.getPassword(); | ||
} | ||
|
||
} |
21 changes: 21 additions & 0 deletions
21
gateway/src/main/java/com/lucasmoraist/gateway/domain/model/LoginRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.lucasmoraist.gateway.domain.model; | ||
|
||
import jakarta.validation.constraints.Email; | ||
import jakarta.validation.constraints.NotBlank; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Data | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class LoginRequest { | ||
|
||
@NotBlank | ||
private String email; | ||
|
||
@NotBlank | ||
private String password; | ||
|
||
} |
30 changes: 30 additions & 0 deletions
30
gateway/src/main/java/com/lucasmoraist/gateway/domain/model/RegisterRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.lucasmoraist.gateway.domain.model; | ||
|
||
import jakarta.validation.constraints.Email; | ||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.Pattern; | ||
import jakarta.validation.constraints.Size; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Data | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class RegisterRequest { | ||
|
||
@Size(min = 3, max = 80) | ||
private String name; | ||
|
||
@NotBlank | ||
@Email(message = "Invalid email") | ||
@Size(max = 255) | ||
private String email; | ||
|
||
@NotBlank | ||
@Size(min = 8, max = 20) | ||
@Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).*$", | ||
message = "Password must contain at least one uppercase letter, one lowercase letter and one digit") | ||
private String password; | ||
|
||
} |
10 changes: 10 additions & 0 deletions
10
gateway/src/main/java/com/lucasmoraist/gateway/repository/UserRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.lucasmoraist.gateway.repository; | ||
|
||
import com.lucasmoraist.gateway.domain.entity.User; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
import java.util.Optional; | ||
|
||
public interface UserRepository extends JpaRepository<User, Long> { | ||
Optional<User> findByEmail(String email); | ||
} |
8 changes: 8 additions & 0 deletions
8
gateway/src/main/java/com/lucasmoraist/gateway/service/TokenService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.lucasmoraist.gateway.service; | ||
|
||
import com.lucasmoraist.gateway.domain.entity.User; | ||
|
||
public interface TokenService { | ||
String generateToken(User user); | ||
String validateToken(String token); | ||
} |
8 changes: 8 additions & 0 deletions
8
gateway/src/main/java/com/lucasmoraist/gateway/service/UserDetailsService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.lucasmoraist.gateway.service; | ||
|
||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||
|
||
public interface UserDetailsService { | ||
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; | ||
} |
10 changes: 10 additions & 0 deletions
10
gateway/src/main/java/com/lucasmoraist/gateway/service/UserService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.lucasmoraist.gateway.service; | ||
|
||
import com.lucasmoraist.gateway.domain.dto.TokenDTO; | ||
import com.lucasmoraist.gateway.domain.model.LoginRequest; | ||
import com.lucasmoraist.gateway.domain.model.RegisterRequest; | ||
|
||
public interface UserService { | ||
void register(RegisterRequest request) throws Exception; | ||
TokenDTO login(LoginRequest request) throws Exception; | ||
} |
54 changes: 54 additions & 0 deletions
54
gateway/src/main/java/com/lucasmoraist/gateway/service/impl/TokenServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.lucasmoraist.gateway.service.impl; | ||
|
||
import com.auth0.jwt.JWT; | ||
import com.auth0.jwt.algorithms.Algorithm; | ||
import com.auth0.jwt.exceptions.JWTCreationException; | ||
import com.auth0.jwt.exceptions.JWTVerificationException; | ||
import com.lucasmoraist.gateway.domain.entity.User; | ||
import com.lucasmoraist.gateway.service.TokenService; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.time.Instant; | ||
import java.time.LocalDateTime; | ||
import java.time.ZoneOffset; | ||
|
||
@Service | ||
public class TokenServiceImpl implements TokenService { | ||
|
||
@Value("${jwt.secret}") | ||
private String secret; | ||
|
||
@Override | ||
public String generateToken(User user) { | ||
try { | ||
Algorithm algorithm = Algorithm.HMAC256(secret); | ||
|
||
return JWT.create() | ||
.withIssuer("task-list") | ||
.withSubject(user.getEmail()) | ||
.withExpiresAt(this.generateExpirationDate()) | ||
.sign(algorithm); | ||
} catch(JWTCreationException e){ | ||
throw new RuntimeException("Error while authentication"); | ||
} | ||
} | ||
|
||
@Override | ||
public String validateToken(String token) { | ||
try { | ||
Algorithm algorithm = Algorithm.HMAC256(secret); | ||
return JWT.require(algorithm) | ||
.withIssuer("task-list") | ||
.build() | ||
.verify(token) | ||
.getSubject(); | ||
} catch(JWTVerificationException e) { | ||
return null; | ||
} | ||
} | ||
|
||
private Instant generateExpirationDate(){ | ||
return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00")); | ||
} | ||
} |
Oops, something went wrong.