-
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.
Merge pull request #51 from Shaderock/4-ub-02-sign-in-user-into-appli…
…cation #4-ub-02-sign-in-user-into-application
- Loading branch information
Showing
6 changed files
with
210 additions
and
0 deletions.
There are no files selected for viewing
44 changes: 44 additions & 0 deletions
44
backend/src/main/java/com/shaderock/backend/auth/login/AuthController.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,44 @@ | ||
package com.shaderock.backend.auth.login; | ||
|
||
import com.shaderock.backend.model.entity.user.AppUser; | ||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.authentication.AuthenticationManager; | ||
import org.springframework.security.authentication.BadCredentialsException; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
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; | ||
import org.springframework.web.server.ResponseStatusException; | ||
|
||
@RestController | ||
@RequestMapping("/api/login") | ||
@RequiredArgsConstructor | ||
public class AuthController { | ||
private final AuthenticationManager authenticationManager; | ||
private final JwtUserDetailsService jwtUserDetailsService; | ||
private final JwtTokenService jwtTokenService; | ||
|
||
@PostMapping | ||
public ResponseEntity<UserDTO> login(@RequestBody @Valid final LoginForm loginForm) { | ||
try { | ||
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginForm.getEmail(), | ||
loginForm.getPassword())); | ||
} catch (final BadCredentialsException ex) { | ||
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); | ||
} | ||
|
||
AppUser appUser = (AppUser) jwtUserDetailsService.loadUserByUsername(loginForm.getEmail()); | ||
UserDTO response = UserDTO.builder() | ||
.firstName(appUser.getFirstName()) | ||
.lastName(appUser.getLastName()) | ||
.token(jwtTokenService.generateToken(appUser)) | ||
.roles(appUser.getRoles()) | ||
.build(); | ||
|
||
return ResponseEntity.ok(response); | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
backend/src/main/java/com/shaderock/backend/auth/login/JWTRequestFilter.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,57 @@ | ||
package com.shaderock.backend.auth.login; | ||
|
||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
import java.io.IOException; | ||
import java.util.Optional; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class JWTRequestFilter extends OncePerRequestFilter { | ||
|
||
private final JwtTokenService jwtTokenService; | ||
private final JwtUserDetailsService jwtUserDetailsService; | ||
|
||
@Override | ||
|
||
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, | ||
final FilterChain chain) throws ServletException, IOException { | ||
final String header = request.getHeader(HttpHeaders.AUTHORIZATION); | ||
if (header == null || !header.startsWith("Bearer ")) { | ||
chain.doFilter(request, response); | ||
return; | ||
} | ||
|
||
final String token = header.substring(7); | ||
final Optional<String> optionalUsername = jwtTokenService.validateTokenAndGetUsername(token); | ||
if (optionalUsername.isEmpty()) { | ||
// validation failed or token expired | ||
chain.doFilter(request, response); | ||
return; | ||
} | ||
|
||
String username = optionalUsername.get(); | ||
|
||
// set user details on spring security context | ||
final UserDetails userDetails = jwtUserDetailsService.loadUserByUsername(username); | ||
final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( | ||
userDetails, null, userDetails.getAuthorities()); | ||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | ||
SecurityContextHolder.getContext().setAuthentication(authentication); | ||
|
||
// continue with authenticated user | ||
chain.doFilter(request, response); | ||
} | ||
|
||
} |
53 changes: 53 additions & 0 deletions
53
backend/src/main/java/com/shaderock/backend/auth/login/JwtTokenService.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,53 @@ | ||
package com.shaderock.backend.auth.login; | ||
|
||
import com.auth0.jwt.JWT; | ||
import com.auth0.jwt.JWTVerifier; | ||
import com.auth0.jwt.algorithms.Algorithm; | ||
import com.auth0.jwt.exceptions.JWTVerificationException; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.time.Instant; | ||
import java.time.LocalDate; | ||
import java.time.ZoneId; | ||
import java.util.Optional; | ||
|
||
@Service | ||
public class JwtTokenService { | ||
private final Algorithm hmac512; | ||
private final JWTVerifier verifier; | ||
|
||
public JwtTokenService(@Value("${jwt.secret}") final String secret) { | ||
this.hmac512 = Algorithm.HMAC512(secret); | ||
this.verifier = JWT.require(this.hmac512).build(); | ||
} | ||
|
||
public String generateToken(final UserDetails userDetails) { | ||
LocalDate date = LocalDate.now().plusMonths(1); | ||
|
||
ZoneId zoneId = ZoneId.systemDefault(); | ||
Instant instant = date.atStartOfDay(zoneId).toInstant(); | ||
|
||
return JWT.create() | ||
.withSubject(userDetails.getUsername()) | ||
.withExpiresAt(instant) | ||
.sign(this.hmac512); | ||
} | ||
|
||
public Optional<String> validateTokenAndGetUsername(final String token) { | ||
String result; | ||
|
||
try { | ||
result = verifier.verify(token).getSubject(); | ||
} catch (final JWTVerificationException verificationEx) { | ||
result = null; | ||
} | ||
|
||
if (result != null) { | ||
return Optional.of(result); | ||
} else { | ||
return Optional.empty(); | ||
} | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
backend/src/main/java/com/shaderock/backend/auth/login/JwtUserDetailsService.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.shaderock.backend.auth.login; | ||
|
||
import com.shaderock.backend.model.repository.AppUserRepository; | ||
import lombok.RequiredArgsConstructor; | ||
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; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class JwtUserDetailsService implements UserDetailsService { | ||
private final AppUserRepository appUserRepository; | ||
|
||
@Override | ||
public UserDetails loadUserByUsername(final String username) { | ||
return appUserRepository.findByEmail(username) | ||
.orElseThrow(() -> new UsernameNotFoundException(String.format("User with email=[%s} not found", username))); | ||
} | ||
|
||
} |
19 changes: 19 additions & 0 deletions
19
backend/src/main/java/com/shaderock/backend/auth/login/LoginForm.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,19 @@ | ||
package com.shaderock.backend.auth.login; | ||
|
||
import jakarta.validation.constraints.Email; | ||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.NotNull; | ||
import jakarta.validation.constraints.Size; | ||
import lombok.Data; | ||
|
||
@Data | ||
public class LoginForm { | ||
@NotNull(message = "Email is not provided") | ||
@NotBlank(message = "Email is empty") | ||
private String email; | ||
|
||
@NotNull(message = "Password is not provided") | ||
@Size(min = 8, max = 25, message = "Password is not between 8 and 25 characters length") | ||
private String password; | ||
} |
16 changes: 16 additions & 0 deletions
16
backend/src/main/java/com/shaderock/backend/auth/login/UserDTO.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 com.shaderock.backend.auth.login; | ||
|
||
import com.shaderock.backend.model.type.Role; | ||
import lombok.Builder; | ||
import lombok.Data; | ||
|
||
import java.util.Set; | ||
|
||
@Data | ||
@Builder | ||
public class UserDTO { | ||
private String token; | ||
private String firstName; | ||
private String lastName; | ||
private Set<Role> roles; | ||
} |