diff --git a/pom.xml b/pom.xml
index 65d0c8a..e0b00ac 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.boot
spring-boot-starter-parent
- 3.3.4
+ 3.4.0
@@ -18,12 +18,12 @@
21
- 1.5.5.Final
+ 1.6.3
3.13.0
- 2.5.0
+ 2.7.0
4.4.0
0.8.12
- 2023.0.3
+ 2024.0.0
diff --git a/src/main/java/com/alura/aluraflixapi/controller/authentication/AuthenticationController.java b/src/main/java/com/alura/aluraflixapi/controller/authentication/AuthenticationController.java
index ead70b9..de71f14 100644
--- a/src/main/java/com/alura/aluraflixapi/controller/authentication/AuthenticationController.java
+++ b/src/main/java/com/alura/aluraflixapi/controller/authentication/AuthenticationController.java
@@ -1,9 +1,11 @@
package com.alura.aluraflixapi.controller.authentication;
+import com.alura.aluraflixapi.controller.dto.token.RefreshTokenVO;
import com.alura.aluraflixapi.domain.user.User;
import com.alura.aluraflixapi.domain.user.dto.AuthenticationDto;
import com.alura.aluraflixapi.infraestructure.security.TokenService;
import com.alura.aluraflixapi.infraestructure.security.dto.TokenJwtDto;
+import com.alura.aluraflixapi.infraestructure.service.token.RefreshTokenService;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
@@ -21,10 +23,12 @@ public class AuthenticationController {
private final AuthenticationManager authenticationManager;
private final TokenService tokenService;
+ private final RefreshTokenService refreshTokenService;
- public AuthenticationController(AuthenticationManager authenticationManager, TokenService tokenService) {
+ public AuthenticationController(AuthenticationManager authenticationManager, TokenService tokenService, RefreshTokenService refreshTokenService) {
this.authenticationManager = authenticationManager;
this.tokenService = tokenService;
+ this.refreshTokenService = refreshTokenService;
}
@PostMapping
@@ -35,9 +39,17 @@ public ResponseEntity login(@RequestBody @Valid AuthenticationDto d
dto.password());
//authenticationManager compare the password of the request with the password from database.
final var authentication = this.authenticationManager.authenticate(authenticationToken);
- final var tokenJWT = tokenService.generateTokenJWT((User) authentication.getPrincipal());
+ final var tokenJwt = tokenService.generateTokenJwt((User) authentication.getPrincipal());
+ final var refreshToken = tokenService.generateRefreshToken(dto.username());
log.info("Token Generated with Success!");
- return ResponseEntity.ok().body(new TokenJwtDto(tokenJWT));
+ return ResponseEntity.ok().body(new TokenJwtDto(tokenJwt, refreshToken));
+ }
+
+ @PostMapping("/refresh")
+ public ResponseEntity refreshAccessToken(@RequestBody RefreshTokenVO refreshToken) {
+ log.info("Request to renew refresh accessToken");
+ final var tokenJwtDto = refreshTokenService.refreshAccessToken(refreshToken.refreshToken());
+ return ResponseEntity.ok(tokenJwtDto);
}
}
diff --git a/src/main/java/com/alura/aluraflixapi/controller/authentication/AuthenticationControllerAdvice.java b/src/main/java/com/alura/aluraflixapi/controller/authentication/AuthenticationControllerAdvice.java
index 60dc873..fb748f6 100644
--- a/src/main/java/com/alura/aluraflixapi/controller/authentication/AuthenticationControllerAdvice.java
+++ b/src/main/java/com/alura/aluraflixapi/controller/authentication/AuthenticationControllerAdvice.java
@@ -4,19 +4,26 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
-@RestControllerAdvice(assignableTypes = AuthenticationController.class)
+@RestControllerAdvice
public class AuthenticationControllerAdvice {
@ExceptionHandler(UsernameNotFoundException.class)
public ResponseEntity handlerAuthenticationException(UsernameNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorMessageVO(ex.getMessage(), HttpStatus.NOT_FOUND));
}
+
@ExceptionHandler(BadCredentialsException.class)
public ResponseEntity handleBadCredentialsException(BadCredentialsException ex) {
- return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorMessageVO(ex.getMessage(), HttpStatus.BAD_REQUEST));
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorMessageVO("Invalid username or password", HttpStatus.BAD_REQUEST));
+ }
+
+ @ExceptionHandler(AuthenticationException.class)
+ public ResponseEntity handleInvalidTokenException(AuthenticationException ex) {
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorMessageVO("Invalid token, please verify expiration", HttpStatus.BAD_REQUEST));
}
}
diff --git a/src/main/java/com/alura/aluraflixapi/controller/dto/token/RefreshTokenVO.java b/src/main/java/com/alura/aluraflixapi/controller/dto/token/RefreshTokenVO.java
new file mode 100644
index 0000000..abe93bd
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/controller/dto/token/RefreshTokenVO.java
@@ -0,0 +1,6 @@
+package com.alura.aluraflixapi.controller.dto.token;
+
+import jakarta.validation.constraints.NotBlank;
+
+public record RefreshTokenVO(@NotBlank String refreshToken) {
+}
diff --git a/src/main/java/com/alura/aluraflixapi/domain/token/RefreshToken.java b/src/main/java/com/alura/aluraflixapi/domain/token/RefreshToken.java
new file mode 100644
index 0000000..ddf2cdb
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/domain/token/RefreshToken.java
@@ -0,0 +1,31 @@
+package com.alura.aluraflixapi.domain.token;
+
+import com.alura.aluraflixapi.domain.user.User;
+import com.auth0.jwt.JWT;
+import lombok.*;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.time.Instant;
+
+@Document
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@Builder
+public class RefreshToken {
+ @Id
+ private String id;
+ private String token;
+ private String userName;
+ private Instant expiryDate;
+
+ public static RefreshToken buildRefreshTokenEntity(User user, String accessToken) {
+ return RefreshToken.builder()
+ .userName(user.getUsername())
+ .token(accessToken)
+ .expiryDate(JWT.decode(accessToken).getExpiresAtAsInstant())
+ .build();
+ }
+}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/exception/JwtRefreshTokenExpiredException.java b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/JwtRefreshTokenExpiredException.java
new file mode 100644
index 0000000..f297d88
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/exception/JwtRefreshTokenExpiredException.java
@@ -0,0 +1,7 @@
+package com.alura.aluraflixapi.infraestructure.exception;
+
+public class JwtRefreshTokenExpiredException extends RuntimeException {
+ public JwtRefreshTokenExpiredException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/repository/RefreshTokenRepository.java b/src/main/java/com/alura/aluraflixapi/infraestructure/repository/RefreshTokenRepository.java
new file mode 100644
index 0000000..b1f60bd
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/repository/RefreshTokenRepository.java
@@ -0,0 +1,7 @@
+package com.alura.aluraflixapi.infraestructure.repository;
+
+import com.alura.aluraflixapi.domain.token.RefreshToken;
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+public interface RefreshTokenRepository extends MongoRepository {
+}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/repository/UserRepository.java b/src/main/java/com/alura/aluraflixapi/infraestructure/repository/UserRepository.java
index 0082d5f..bb16824 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/repository/UserRepository.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/repository/UserRepository.java
@@ -6,5 +6,5 @@
public interface UserRepository extends MongoRepository {
- UserDetails findByUsername(String username);
+ User findByUsername(String username);
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/security/JwtAuthenticationEntryPoint.java b/src/main/java/com/alura/aluraflixapi/infraestructure/security/JwtAuthenticationEntryPoint.java
new file mode 100644
index 0000000..d0a6509
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/security/JwtAuthenticationEntryPoint.java
@@ -0,0 +1,29 @@
+package com.alura.aluraflixapi.infraestructure.security;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerExceptionResolver;
+
+/**
+ * This class handles unsuccessful JWT exceptions
+ */
+@Slf4j
+@Component
+public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
+ @Qualifier("handlerExceptionResolver")
+ private final HandlerExceptionResolver resolver;
+
+ public JwtAuthenticationEntryPoint(HandlerExceptionResolver handlerExceptionResolver) {
+ this.resolver = handlerExceptionResolver;
+ }
+
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
+ resolver.resolveException(request, response, null, authException);
+ }
+}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityConfigurations.java b/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityConfigurations.java
index 52275ef..83cf4b7 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityConfigurations.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityConfigurations.java
@@ -30,6 +30,7 @@
public class SecurityConfigurations {
private final SecurityFilter securityFilter;
+ private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
@@ -39,13 +40,16 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.sessionManagement(managementConfigurer ->
managementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(httpRequest -> httpRequest
- .requestMatchers(HttpMethod.POST, "/login").permitAll()
+ .requestMatchers(HttpMethod.POST, "/login/**").permitAll()
.requestMatchers("/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**").permitAll()
//any other request has to be authenticated
.anyRequest().authenticated()
)
- //tell to spring to user our filter SecurityFilter.class instead their
+ //tell to spring to use our filter SecurityFilter.class instead their
.addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class)
+ //tell to spring to use this filter to handle any exception about JWT exception
+ .exceptionHandling(exceptionHandler ->
+ exceptionHandler.authenticationEntryPoint(jwtAuthenticationEntryPoint))
.build();
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityFilter.java b/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityFilter.java
index 1450a75..268cfae 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityFilter.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/security/SecurityFilter.java
@@ -5,15 +5,16 @@
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.Objects;
-import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
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.Objects;
+import java.util.Optional;
+
/**
* Spring validate each request received only once
*/
@@ -21,46 +22,46 @@
@Component
public class SecurityFilter extends OncePerRequestFilter {
- private static final String PREFIX_LOGGING = "[SecurityFilter]";
- public static final String AUTHORIZATION = "Authorization";
- private final TokenService tokenService;
- private final UserRepository userRepository;
+ private static final String PREFIX_LOGGING = "[SecurityFilter]";
+ public static final String AUTHORIZATION = "Authorization";
+ private final TokenService tokenService;
+ private final UserRepository userRepository;
- public SecurityFilter(final TokenService tokenService, final UserRepository userRepository) {
- this.tokenService = tokenService;
- this.userRepository = userRepository;
- }
+ public SecurityFilter(final TokenService tokenService, final UserRepository userRepository) {
+ this.tokenService = tokenService;
+ this.userRepository = userRepository;
+ }
- //doFilterInternal is called for each request received
- //All request to endpoint/login don´t have token in theirs headers
- @Override
- protected void doFilterInternal(final HttpServletRequest request,
- final HttpServletResponse response,
- final FilterChain filterChain) throws ServletException, IOException {
+ //doFilterInternal is called for each request received
+ //All request to endpoint/login don´t have accessToken in theirs headers
+ @Override
+ protected void doFilterInternal(final HttpServletRequest request,
+ final HttpServletResponse response,
+ final FilterChain filterChain) throws ServletException, IOException {
- log.info("{} request received intercepted by Internal Filter", PREFIX_LOGGING);
- final var tokenJWT = this.getTokenJWT(request);
+ log.info("{} request received intercepted by Internal Filter", PREFIX_LOGGING);
+ final var tokenJWT = this.getTokenJWT(request);
- if (Objects.nonNull(tokenJWT)) {
- //Retrieve user from Token JWT
- final var subject = this.tokenService.getSubject(tokenJWT);
- var user = this.userRepository.findByUsername(subject);
+ if (Objects.nonNull(tokenJWT)) {
+ //Retrieve user from Token JWT
+ final var username = this.tokenService.verifyTokenJWT(tokenJWT);
+ final var user = this.userRepository.findByUsername(username);
- //after retrieve the user we need to tell to Spring framework to authenticate him in the context
- //this is done by calling UsernamePasswordAuthenticationToken and SecurityContextHolder methods
- log.info("{} Authenticating user: {} ", PREFIX_LOGGING, user.getUsername());
- var authentication = new UsernamePasswordAuthenticationToken(user, null,
- user.getAuthorities());
- SecurityContextHolder.getContext().setAuthentication(authentication);
- log.info("{} User authenticated: {}", PREFIX_LOGGING, authentication.getPrincipal());
+ //after retrieve the user we need to tell to Spring framework to authenticate him in the context
+ //this is done by calling UsernamePasswordAuthenticationToken and SecurityContextHolder methods
+ log.info("{} Authenticating user: {} ", PREFIX_LOGGING, user.getUsername());
+ var authentication = new UsernamePasswordAuthenticationToken(user, null,
+ user.getAuthorities());
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ log.info("{} User authenticated: {}", PREFIX_LOGGING, authentication.getPrincipal());
+ }
+ //continue the flow
+ filterChain.doFilter(request, response);
}
- //continue the flow
- filterChain.doFilter(request, response);
- }
- private String getTokenJWT(final HttpServletRequest request) {
- return Optional.ofNullable(request.getHeader(AUTHORIZATION))
- .map(token -> token.replace("Bearer", "").trim())
- .orElse(null);
- }
+ private String getTokenJWT(final HttpServletRequest request) {
+ return Optional.ofNullable(request.getHeader(AUTHORIZATION))
+ .map(token -> token.replace("Bearer", "").trim())
+ .orElse(null);
+ }
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/security/TokenService.java b/src/main/java/com/alura/aluraflixapi/infraestructure/security/TokenService.java
index b43cd43..6c30a32 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/security/TokenService.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/security/TokenService.java
@@ -3,66 +3,85 @@
import com.alura.aluraflixapi.domain.user.User;
import com.alura.aluraflixapi.domain.user.roles.Roles;
+import com.alura.aluraflixapi.infraestructure.exception.JwtRefreshTokenExpiredException;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.ZoneOffset;
-
-import com.auth0.jwt.exceptions.JWTDecodeException;
+import com.auth0.jwt.exceptions.JWTVerificationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
@Slf4j
@Service
public class TokenService {
- @Value("${api.security.api-issuer}")
- private String apiIssuer;
+ @Value("${api.security.api-issuer}")
+ private String apiIssuer;
- @Value("${api.security.token-jwt-secret}")
- public String secret;
+ @Value("${api.security.token-jwt-secret}")
+ public String secret;
- public String generateTokenJWT(User user) {
- try {
- log.info("Generating Token JWT ...");
- return JWT.create()
- .withIssuer(apiIssuer)
- //owner
- .withSubject(user.getUsername())
- .withClaim("id", user.getUsername())
- .withClaim("role", user.getRoles()
- .stream()
- .map(Roles::getRole)
- .map(Enum::name)
- .toList())
- // duration of JWT
- .withExpiresAt(getExpireDate())
- .sign(Algorithm.HMAC256(secret));
+ public String generateTokenJwt(User user) {
+ try {
+ log.info("Generating Token JWT ...");
+ return JWT.create()
+ .withIssuer(apiIssuer)
+ //owner
+ .withSubject(user.getUsername())
+ .withClaim("id", user.getUsername())
+ .withClaim("role", user.getRoles()
+ .stream()
+ .map(Roles::getRole)
+ .map(Enum::name)
+ .toList())
+ // duration of JWT
+ .withExpiresAt(getExpireDate())
+ .sign(Algorithm.HMAC256(secret));
- } catch (NullPointerException exception) {
- throw new JWTCreationException("Error to create JWT token", exception.getCause());
+ } catch (NullPointerException exception) {
+ throw new JWTCreationException("Error to create JWT accessToken", exception.getCause());
+ }
}
- }
- public String getSubject(String tokenJWT) {
- try {
- var algorithm = Algorithm.HMAC256(secret);
- return JWT.require(algorithm)
- .withIssuer(apiIssuer)
- .build()
- .verify(tokenJWT)
- .getSubject();
- } catch (JWTDecodeException ex) {
- throw new JWTDecodeException("Error verifying JWT Token", ex.getCause());
+ public String verifyTokenJWT(String tokenJWT) {
+ log.info("Verifying JWT accessToken ...");
+ try {
+ return JWT.require(Algorithm.HMAC256(secret))
+ .withIssuer(apiIssuer)
+ .build()
+ .verify(tokenJWT)
+ .getSubject();
+ } catch (JWTVerificationException ex) {
+ throw new JWTVerificationException("Error verifying JWT Token", ex.getCause());
+ }
}
- }
- //Create expire date of token, in this case is the current hour plus 10 minutes
- private Instant getExpireDate() {
- return LocalDateTime.now().plusMinutes(10).toInstant(ZoneOffset.UTC);
+ public void isRefreshTokenExpired(String tokenJWT) {
+ if (JWT.decode(tokenJWT).getExpiresAt().toInstant().compareTo(Instant.now()) < 0) {
+ throw new RuntimeException("Refresh token expired, please login again");
+ }
+ }
- }
+ //Create expire date of accessToken, in this case is the current hour plus 10 minutes
+ private Instant getExpireDate() {
+ return Instant.now().plus(1, ChronoUnit.MINUTES);
+
+ }
+
+ public String generateRefreshToken(String subject) {
+ try {
+ log.info("Generating Refresh Token JWT ...");
+ return JWT.create()
+ .withIssuer(apiIssuer)
+ .withExpiresAt(Instant.now().plus(5, ChronoUnit.MINUTES))
+ .withSubject(subject)
+ .sign(Algorithm.HMAC256(secret));
+ } catch (RuntimeException exception) {
+ throw new JWTCreationException("Error to create JWT refresh accessToken", exception.getCause());
+ }
+ }
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/security/dto/TokenJwtDto.java b/src/main/java/com/alura/aluraflixapi/infraestructure/security/dto/TokenJwtDto.java
index 68fb050..dacde0a 100644
--- a/src/main/java/com/alura/aluraflixapi/infraestructure/security/dto/TokenJwtDto.java
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/security/dto/TokenJwtDto.java
@@ -1,5 +1,5 @@
package com.alura.aluraflixapi.infraestructure.security.dto;
-public record TokenJwtDto(String token) {
+public record TokenJwtDto(String accessToken, String refreshToken) {
}
diff --git a/src/main/java/com/alura/aluraflixapi/infraestructure/service/token/RefreshTokenService.java b/src/main/java/com/alura/aluraflixapi/infraestructure/service/token/RefreshTokenService.java
new file mode 100644
index 0000000..5b83991
--- /dev/null
+++ b/src/main/java/com/alura/aluraflixapi/infraestructure/service/token/RefreshTokenService.java
@@ -0,0 +1,37 @@
+package com.alura.aluraflixapi.infraestructure.service.token;
+
+import com.alura.aluraflixapi.domain.token.RefreshToken;
+import com.alura.aluraflixapi.infraestructure.repository.RefreshTokenRepository;
+import com.alura.aluraflixapi.infraestructure.repository.UserRepository;
+import com.alura.aluraflixapi.infraestructure.security.TokenService;
+import com.alura.aluraflixapi.infraestructure.security.dto.TokenJwtDto;
+import com.auth0.jwt.JWT;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+public class RefreshTokenService {
+
+ private final TokenService tokenService;
+ private final RefreshTokenRepository refreshTokenRepository;
+ private final UserRepository userRepository;
+
+ public RefreshTokenService(RefreshTokenRepository refreshTokenRepository, TokenService tokenService, UserRepository userRepository) {
+ this.refreshTokenRepository = refreshTokenRepository;
+ this.tokenService = tokenService;
+ this.userRepository = userRepository;
+ }
+
+ public TokenJwtDto refreshAccessToken(final String refreshToken) {
+ log.info("[RefreshTokenService] - Generating new accessToken");
+ //valid if refresh token is expired
+ tokenService.isRefreshTokenExpired(refreshToken);
+ final var user = userRepository.findByUsername(JWT.decode(refreshToken).getSubject());
+ final var accessToken = tokenService.generateTokenJwt(user);
+ final var refreshTokenEntity = RefreshToken.buildRefreshTokenEntity(user, accessToken);
+ refreshTokenRepository.save(refreshTokenEntity);
+ return new TokenJwtDto(accessToken, refreshToken);
+ }
+
+}
diff --git a/src/test/java/com/alura/aluraflixapi/controller/AuthenticationControllerTest.java b/src/test/java/com/alura/aluraflixapi/controller/AuthenticationControllerTest.java
index c5db0a3..0b4bb3f 100644
--- a/src/test/java/com/alura/aluraflixapi/controller/AuthenticationControllerTest.java
+++ b/src/test/java/com/alura/aluraflixapi/controller/AuthenticationControllerTest.java
@@ -6,6 +6,7 @@
import com.alura.aluraflixapi.domain.user.roles.Roles;
import com.alura.aluraflixapi.domain.user.roles.RolesEnum;
import com.alura.aluraflixapi.infraestructure.security.TokenService;
+import com.alura.aluraflixapi.infraestructure.service.token.RefreshTokenService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
@@ -33,6 +34,8 @@ class AuthenticationControllerTest {
@MockBean
private TokenService tokenService;
+ @MockBean
+ private RefreshTokenService refreshTokenService;
@Test
void login_test() {
@@ -42,7 +45,7 @@ void login_test() {
Set.of(Roles.builder().id("1").role(RolesEnum.ROLE_ADMIN).build()));
final var testingAuthenticationToken = new TestingAuthenticationToken(userAdministrator, userAdministrator);
- when(this.tokenService.generateTokenJWT(Mockito.any())).thenReturn(tokenJwtFake);
+ when(this.tokenService.generateTokenJwt(Mockito.any())).thenReturn(tokenJwtFake);
when(this.manager.authenticate(Mockito.any())).thenReturn(testingAuthenticationToken);
//When
@@ -51,6 +54,6 @@ void login_test() {
//Then
assertThat(userAuthenticated).isNotNull();
assertThat(userAuthenticated.getBody()).isNotNull();
- assertThat(userAuthenticated.getBody().token()).isEqualTo(tokenJwtFake);
+ assertThat(userAuthenticated.getBody().accessToken()).isEqualTo(tokenJwtFake);
}
}
\ No newline at end of file
diff --git a/src/test/java/com/alura/aluraflixapi/infraestructure/repository/VideoRepositoryTest.java b/src/test/java/com/alura/aluraflixapi/infraestructure/repository/VideoRepositoryTest.java
index d1c7f17..523e9e3 100644
--- a/src/test/java/com/alura/aluraflixapi/infraestructure/repository/VideoRepositoryTest.java
+++ b/src/test/java/com/alura/aluraflixapi/infraestructure/repository/VideoRepositoryTest.java
@@ -26,7 +26,6 @@ class VideoRepositoryTest extends ParseJson {
@AfterEach
void after() {
- //TODO: search another way to delete all data without call this methods.
videoRepository.deleteAll();
categoryRepository.deleteAll();
}
diff --git a/src/test/java/com/alura/aluraflixapi/infraestructure/security/TokenServiceTest.java b/src/test/java/com/alura/aluraflixapi/infraestructure/security/TokenServiceTest.java
index 47174a8..8d7c298 100644
--- a/src/test/java/com/alura/aluraflixapi/infraestructure/security/TokenServiceTest.java
+++ b/src/test/java/com/alura/aluraflixapi/infraestructure/security/TokenServiceTest.java
@@ -4,13 +4,12 @@
import com.alura.aluraflixapi.domain.user.roles.Roles;
import com.alura.aluraflixapi.domain.user.roles.RolesEnum;
import com.auth0.jwt.exceptions.JWTCreationException;
-import com.auth0.jwt.exceptions.JWTDecodeException;
+import com.auth0.jwt.exceptions.JWTVerificationException;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.mock.mockito.SpyBean;
-import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.Set;
@@ -26,7 +25,7 @@ class TokenServiceTest {
@Test
@DisplayName("Should return a TokenJWT")
- void generateTokenJWT_test() {
+ void generateTokenJwt_test() {
//Given
final var user = User.builder().id(UUID.randomUUID().toString())
.username("admin@aluraflix.com")
@@ -37,7 +36,7 @@ void generateTokenJWT_test() {
.build()))
.build();
//When
- final var tokenJWT = this.tokenService.generateTokenJWT(user);
+ final var tokenJWT = this.tokenService.generateTokenJwt(user);
//Then
assertThat(tokenJWT)
.isNotBlank()
@@ -46,17 +45,17 @@ void generateTokenJWT_test() {
@Test
@DisplayName("Should return a JWTCreationException when is generating TokenJWT and some field is null")
- void generateTokenJWT_KO_test() {
+ void generateTokenJwt_KO_test() {
//Then
Assertions.assertThatExceptionOfType(JWTCreationException.class)
- .isThrownBy(() -> this.tokenService.generateTokenJWT(null))
- .withMessageContaining("Error to create JWT token");
+ .isThrownBy(() -> this.tokenService.generateTokenJwt(null))
+ .withMessageContaining("Error to create JWT accessToken");
}
@Test
@DisplayName("Should retrieve User Principal from TokenJWT passed")
- void getSubject_test() {
+ void verifyTokenJWT_test() {
//Given
final var user = User.builder().id(UUID.randomUUID().toString())
.username("admin@aluraflix.com")
@@ -66,22 +65,22 @@ void getSubject_test() {
.role(RolesEnum.ROLE_ADMIN)
.build()))
.build();
- final var tokenJWT = this.tokenService.generateTokenJWT(user);
+ final var tokenJWT = this.tokenService.generateTokenJwt(user);
//When
- final var userPrincipal = this.tokenService.getSubject(tokenJWT);
+ final var userPrincipal = this.tokenService.verifyTokenJWT(tokenJWT);
//Then
+
assertThat(userPrincipal)
- .isNotBlank()
.isNotNull()
.isEqualTo("admin@aluraflix.com");
}
@Test
@DisplayName("Should return a JWTDecodeException when is verifying TokenJWT and is null")
- void getSubject_KO_test() {
+ void verifyTokenJWT_KO_test() {
//Then
- Assertions.assertThatExceptionOfType(JWTDecodeException.class)
- .isThrownBy(() -> this.tokenService.getSubject(null))
+ Assertions.assertThatExceptionOfType(JWTVerificationException.class)
+ .isThrownBy(() -> this.tokenService.verifyTokenJWT(null))
.withMessageContaining("Error verifying JWT Token");
}
}
\ No newline at end of file
diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml
index 517acf5..6a6c4a6 100644
--- a/src/test/resources/application-test.yml
+++ b/src/test/resources/application-test.yml
@@ -8,4 +8,4 @@ spring:
mongodb:
database: alura-flix-test
# always commit the uri like this: ${DATABASE_TEST}
- uri: ${DATABASE_TEST:mongodb+srv://laurosilveira:283TlfZiOW4nNOnN@alura-flix-test.qixe2kd.mongodb.net/?retryWrites=true&w=majority&appName=alura-flix-test}
\ No newline at end of file
+ uri: ${DATABASE_TEST}
\ No newline at end of file