-
Notifications
You must be signed in to change notification settings - Fork 0
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
Added JWT support #11
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
dd288fe
Added SecurityConfig class with PasswordEncoder and SecurityFilterCha…
nklimovych b2c7f65
Added JWT support
nklimovych 9ef8fb5
Added handling of JwtException and AuthenticationException in GlobalE…
nklimovych 8bb0b4b
Removed redundant Key to SecretKey cast in JwtUtil in lines 38 & 53
nklimovych b574464
Added swagger request matchers
nklimovych 6cd7419
Added SecurityConfig class with PasswordEncoder and SecurityFilterCha…
nklimovych d2e8e3c
Added JWT support
nklimovych 53077bb
Added handling of JwtException and AuthenticationException in GlobalE…
nklimovych 926837c
Removed redundant Key to SecretKey cast in JwtUtil in lines 38 & 53
nklimovych 6969d92
Added swagger request matchers
nklimovych 3e4736c
Merge remote-tracking branch 'origin/jwt-impl' into jwt-impl
nklimovych 242d1ad
Merge branch 'main' into jwt-impl
nklimovych 7603e5a
Merge remote-tracking branch 'origin/jwt-impl' into jwt-impl
nklimovych bcf91b9
Code refactored according to mentor suggestions. Added token prefix a…
nklimovych 4313a36
START_INDEX was deleted in JwtAuthenticationFilter.
nklimovych 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 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
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
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
16 changes: 16 additions & 0 deletions
16
src/main/java/mate/academy/bookstore/dto/user/UserLoginRequestDto.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,16 @@ | ||||||||
package mate.academy.bookstore.dto.user; | ||||||||
|
||||||||
import jakarta.validation.constraints.Email; | ||||||||
import jakarta.validation.constraints.NotBlank; | ||||||||
import jakarta.validation.constraints.Size; | ||||||||
|
||||||||
public record UserLoginRequestDto( | ||||||||
@NotBlank | ||||||||
@Size(min = 8, max = 20) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
String email, | ||||||||
@NotBlank | ||||||||
@Size(min = 8, max = 20, message = "Password must be at least 8 characters long") | ||||||||
String password | ||||||||
) { | ||||||||
} |
4 changes: 4 additions & 0 deletions
4
src/main/java/mate/academy/bookstore/dto/user/UserLoginResponseDto.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 mate.academy.bookstore.dto.user; | ||
|
||
public record UserLoginResponseDto(String token) { | ||
} |
2 changes: 1 addition & 1 deletion
2
...y/bookstore/dto/user/UserResponseDto.java → ...dto/user/UserRegistrationResponseDto.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
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
25 changes: 25 additions & 0 deletions
25
src/main/java/mate/academy/bookstore/security/AuthenticationService.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,25 @@ | ||
package mate.academy.bookstore.security; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import mate.academy.bookstore.dto.user.UserLoginRequestDto; | ||
import mate.academy.bookstore.dto.user.UserLoginResponseDto; | ||
import org.springframework.security.authentication.AuthenticationManager; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.stereotype.Service; | ||
|
||
@RequiredArgsConstructor | ||
@Service | ||
public class AuthenticationService { | ||
private final JwtUtil jwtUtil; | ||
private final AuthenticationManager authenticationManager; | ||
|
||
public UserLoginResponseDto authenticate(UserLoginRequestDto request) { | ||
final Authentication authentication = authenticationManager.authenticate( | ||
new UsernamePasswordAuthenticationToken(request.email(), request.password()) | ||
); | ||
|
||
String token = jwtUtil.generateToken(authentication.getName()); | ||
return new UserLoginResponseDto(token); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
src/main/java/mate/academy/bookstore/security/JwtAuthenticationFilter.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,51 @@ | ||
package mate.academy.bookstore.security; | ||
|
||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.io.IOException; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.security.core.userdetails.UserDetailsService; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
@RequiredArgsConstructor | ||
@Component | ||
public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||
private static final String BEARER_PREFIX = "Bearer "; | ||
private static final String AUTHORIZATION = "Authorization"; | ||
private final UserDetailsService userDetailsService; | ||
private final JwtUtil jwtUtil; | ||
|
||
@Override | ||
protected void doFilterInternal( | ||
HttpServletRequest request, | ||
HttpServletResponse response, | ||
FilterChain filterChain | ||
) throws ServletException, IOException { | ||
String token = getToken(request); | ||
|
||
if (token != null && jwtUtil.isValidToken(token)) { | ||
String username = jwtUtil.getUsername(token); | ||
UserDetails userDetails = userDetailsService.loadUserByUsername(username); | ||
Authentication authentication = new UsernamePasswordAuthenticationToken( | ||
userDetails, null, userDetails.getAuthorities() | ||
); | ||
SecurityContextHolder.getContext().setAuthentication(authentication); | ||
} | ||
filterChain.doFilter(request, response); | ||
} | ||
|
||
private String getToken(HttpServletRequest request) { | ||
String bearerToken = request.getHeader(AUTHORIZATION); | ||
if (bearerToken != null && bearerToken.startsWith(BEARER_PREFIX)) { | ||
return bearerToken.substring(BEARER_PREFIX.length()); | ||
} | ||
return null; | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
src/main/java/mate/academy/bookstore/security/JwtUtil.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,59 @@ | ||
package mate.academy.bookstore.security; | ||
|
||
import io.jsonwebtoken.Claims; | ||
import io.jsonwebtoken.Jws; | ||
import io.jsonwebtoken.JwtException; | ||
import io.jsonwebtoken.Jwts; | ||
import io.jsonwebtoken.security.Keys; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Date; | ||
import java.util.function.Function; | ||
import javax.crypto.SecretKey; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class JwtUtil { | ||
private final SecretKey secret; | ||
|
||
@Value("${jwt.expiration}") | ||
private Long expiration; | ||
|
||
public JwtUtil(@Value("${jwt.secret}") String secretKey) { | ||
secret = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); | ||
} | ||
|
||
public String generateToken(String username) { | ||
return Jwts.builder() | ||
.subject(username) | ||
.issuedAt(new Date(System.currentTimeMillis())) | ||
.expiration(new Date(System.currentTimeMillis() + expiration)) | ||
.signWith(secret) | ||
.compact(); | ||
} | ||
|
||
public boolean isValidToken(String token) { | ||
try { | ||
Jws<Claims> claimsJws = Jwts.parser() | ||
.verifyWith(secret) | ||
.build() | ||
.parseSignedClaims(token); | ||
return !claimsJws.getPayload().getExpiration().before(new Date()); | ||
} catch (JwtException | IllegalArgumentException e) { | ||
throw new JwtException("Expired or invalid JWT token"); | ||
} | ||
} | ||
|
||
public String getUsername(String token) { | ||
return getClaimsFromToken(token, Claims::getSubject); | ||
} | ||
|
||
private <T> T getClaimsFromToken(String token, Function<Claims, T> claimsResolver) { | ||
final Claims claims = Jwts.parser() | ||
.verifyWith(secret) | ||
.build() | ||
.parseSignedClaims(token) | ||
.getPayload(); | ||
return claimsResolver.apply(claims); | ||
} | ||
} |
5 changes: 3 additions & 2 deletions
5
src/main/java/mate/academy/bookstore/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 |
---|---|---|
@@ -1,9 +1,10 @@ | ||
package mate.academy.bookstore.service; | ||
|
||
import mate.academy.bookstore.dto.user.UserRegistrationRequestDto; | ||
import mate.academy.bookstore.dto.user.UserResponseDto; | ||
import mate.academy.bookstore.dto.user.UserRegistrationResponseDto; | ||
import mate.academy.bookstore.exception.RegistrationException; | ||
|
||
public interface UserService { | ||
UserResponseDto save(UserRegistrationRequestDto requestDto) throws RegistrationException; | ||
UserRegistrationResponseDto save(UserRegistrationRequestDto requestDto) | ||
throws RegistrationException; | ||
} |
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
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
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 |
---|---|---|
|
@@ -17,4 +17,4 @@ databaseChangeLog: | |
type: enum('USER', 'ADMIN') | ||
constraints: | ||
nullable: false | ||
unique: true | ||
unique: true |
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it necessary to add this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added it because Spring can't awtowire AuthenticationManager and app failed to start:
Could not autowire. No beans of 'AuthenticationManager' type found.