Repository navigation
Add security configs and a feign client for the User MS #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
15 changes: 15 additions & 0 deletions
15
src/main/java/com/javanauta/taskscheduler/business/dto/UserDTO.java
This file contains hidden or 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,15 @@ | ||
| package com.javanauta.taskscheduler.business.dto; | ||
|
|
||
| import lombok.*; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| @Getter | ||
| @Setter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Builder | ||
| public class UserDTO { | ||
| private String email; | ||
| private String password; | ||
| } |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/javanauta/taskscheduler/infrastructure/client/UserClient.java
This file contains hidden or 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,14 @@ | ||
| package com.javanauta.taskscheduler.infrastructure.client; | ||
|
|
||
| import com.javanauta.taskscheduler.business.dto.UserDTO; | ||
| import org.springframework.cloud.openfeign.FeignClient; | ||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.RequestHeader; | ||
| import org.springframework.web.bind.annotation.RequestParam; | ||
|
|
||
| @FeignClient(name = "user", url = "${user.url}") | ||
| public interface UserClient { | ||
|
|
||
| @GetMapping("/user") | ||
| UserDTO getUserByEmail(@RequestParam("email") String email, @RequestHeader("Authorization") String token); | ||
| } | ||
60 changes: 60 additions & 0 deletions
60
src/main/java/com/javanauta/taskscheduler/infrastructure/security/JwtRequestFilter.java
This file contains hidden or 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,60 @@ | ||
| package com.javanauta.taskscheduler.infrastructure.security; | ||
|
|
||
| import jakarta.servlet.FilterChain; | ||
| import jakarta.servlet.ServletException; | ||
| import jakarta.servlet.http.HttpServletRequest; | ||
| import jakarta.servlet.http.HttpServletResponse; | ||
| import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
| import org.springframework.security.core.context.SecurityContextHolder; | ||
| import org.springframework.security.core.userdetails.UserDetails; | ||
| import org.springframework.web.filter.OncePerRequestFilter; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| // Defines the JwtRequestFilter class, which extends OncePerRequestFilter | ||
| public class JwtRequestFilter extends OncePerRequestFilter { | ||
|
|
||
| // Defines properties to store instances of JwtUtil and UserDetailsService | ||
| private final JwtUtil jwtUtil; | ||
| private final UserDetailsServiceImpl userDetailsService; | ||
|
|
||
| // Constructor that initializes the properties with provided instances | ||
| public JwtRequestFilter(JwtUtil jwtUtil, UserDetailsServiceImpl userDetailsService) { | ||
| this.jwtUtil = jwtUtil; | ||
| this.userDetailsService = userDetailsService; | ||
| } | ||
|
|
||
| // Method called once per request to process the filter | ||
| @Override | ||
| protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) | ||
| throws ServletException, IOException { | ||
|
|
||
| // Gets the value of the "Authorization" header from the request | ||
| final String authorizationHeader = request.getHeader("Authorization"); | ||
|
|
||
| // Checks whether the header exists and starts with "Bearer " | ||
| if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { | ||
| // Extracts the JWT token from the header | ||
| final String token = authorizationHeader.substring(7); | ||
| // Extracts the username from the JWT token | ||
| final String username = jwtUtil.extractUsername(token); | ||
|
|
||
| // If the username is not null and the user is not yet authenticated | ||
| if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { | ||
| // Loads user details from the username | ||
| UserDetails userDetails = userDetailsService.loadUserDetails(username, token); | ||
| // Validates the JWT token | ||
| if (jwtUtil.validateToken(token, username)) { | ||
| // Creates an authentication object with user information | ||
| UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( | ||
| userDetails, null, userDetails.getAuthorities()); | ||
| // Sets authentication in the security context | ||
| SecurityContextHolder.getContext().setAuthentication(authentication); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Continues the filter chain, allowing the request to proceed | ||
| chain.doFilter(request, response); | ||
| } | ||
| } |
45 changes: 45 additions & 0 deletions
45
src/main/java/com/javanauta/taskscheduler/infrastructure/security/JwtUtil.java
This file contains hidden or 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,45 @@ | ||
| package com.javanauta.taskscheduler.infrastructure.security; | ||
|
|
||
| import io.jsonwebtoken.Claims; | ||
| import io.jsonwebtoken.Jwts; | ||
| import io.jsonwebtoken.security.Keys; | ||
| import org.springframework.stereotype.Service; | ||
|
|
||
| import java.nio.charset.StandardCharsets; | ||
| import java.util.Date; | ||
|
|
||
| @Service | ||
| public class JwtUtil { | ||
|
|
||
| // Secret key used to sign and verify JWT tokens | ||
| private final String secretKey = "your-super-long-secret-key-that-needs-to-be-very-difficult"; | ||
|
|
||
| // Extracts claims from the JWT token | ||
| public Claims extractClaims(String token) { | ||
| return Jwts.parser() | ||
| .setSigningKey(Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8))) // Sets secret key to validate signature | ||
| .build() | ||
| .parseClaimsJws(token) // Parses the JWT token and gets claims | ||
| .getBody(); // Returns claims body | ||
| } | ||
|
|
||
| // Extracts username from the JWT token | ||
| public String extractUsername(String token) { | ||
| // Gets the subject (username) from the claims | ||
| return extractClaims(token).getSubject(); | ||
| } | ||
|
|
||
| // Checks whether the JWT token is expired | ||
| public boolean isTokenExpired(String token) { | ||
| // Compares token expiration date with current date | ||
| return extractClaims(token).getExpiration().before(new Date()); | ||
| } | ||
|
|
||
| // Validates the JWT token by checking username match and expiration | ||
| public boolean validateToken(String token, String username) { | ||
| // Extracts username from the token | ||
| final String extractedUsername = extractUsername(token); | ||
| // Checks if username matches and token is not expired | ||
| return (extractedUsername.equals(username) && !isTokenExpired(token)); | ||
| } | ||
| } |
53 changes: 53 additions & 0 deletions
53
src/main/java/com/javanauta/taskscheduler/infrastructure/security/SecurityConfig.java
This file contains hidden or 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,53 @@ | ||
| package com.javanauta.taskscheduler.infrastructure.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.annotation.web.configurers.AbstractHttpConfigurer; | ||
| import org.springframework.security.config.http.SessionCreationPolicy; | ||
| import org.springframework.security.core.userdetails.UserDetailsService; | ||
| 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 { | ||
|
|
||
| // JwtUtil and UserDetailsService instances injected by Spring | ||
| private final JwtUtil jwtUtil; | ||
| private final UserDetailsServiceImpl userDetailsService; | ||
|
|
||
| // Constructor for dependency injection of JwtUtil and UserDetailsService | ||
| @Autowired | ||
| public SecurityConfig(JwtUtil jwtUtil, UserDetailsServiceImpl userDetailsService) { | ||
| this.jwtUtil = jwtUtil; | ||
| this.userDetailsService = userDetailsService; | ||
| } | ||
|
|
||
| // Security filter configuration | ||
| @Bean | ||
| public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { | ||
| // Creates a JwtRequestFilter instance using JwtUtil and UserDetailsService | ||
| JwtRequestFilter jwtRequestFilter = new JwtRequestFilter(jwtUtil, userDetailsService); | ||
|
|
||
| http | ||
| .csrf(AbstractHttpConfigurer::disable) // Disables CSRF protection for REST APIs (not needed in stateless APIs) | ||
| .authorizeHttpRequests(authorize -> authorize | ||
| .anyRequest().authenticated() // Requires authentication for all other requests | ||
| ) | ||
| .sessionManagement(session -> session | ||
| .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // Sets session policy to stateless | ||
| ) | ||
| .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); // Adds JWT filter before default authentication filter | ||
|
|
||
| // Returns the built security configuration | ||
| return http.build(); | ||
| } | ||
| } |
23 changes: 23 additions & 0 deletions
23
...main/java/com/javanauta/taskscheduler/infrastructure/security/UserDetailsServiceImpl.java
This file contains hidden or 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,23 @@ | ||
| package com.javanauta.taskscheduler.infrastructure.security; | ||
|
|
||
| import com.javanauta.taskscheduler.business.dto.UserDTO; | ||
| import com.javanauta.taskscheduler.infrastructure.client.UserClient; | ||
| import org.springframework.beans.factory.annotation.Autowired; | ||
| import org.springframework.security.core.userdetails.UserDetails; | ||
| import org.springframework.stereotype.Service; | ||
|
|
||
| @Service | ||
| public class UserDetailsServiceImpl { | ||
|
|
||
| @Autowired | ||
| private UserClient userClient; | ||
|
|
||
| public UserDetails loadUserDetails(String email, String token) { | ||
| UserDTO userDTO = userClient.getUserByEmail(email, token); | ||
|
|
||
| return org.springframework.security.core.userdetails.User | ||
| .withUsername(userDTO.getEmail()) // Sets the username as the email | ||
| .password(userDTO.getPassword()) // Sets the user's password | ||
| .build(); // Builds the UserDetails object | ||
| } | ||
| } |
This file contains hidden or 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 |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| spring.application.name=task-scheduler | ||
| user.url=localhost:8080 |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.