From e2765c4a96887c538809417967c83b2ee5bce0f4 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Tue, 6 Aug 2024 21:54:53 -0500 Subject: [PATCH] Working on refresh auth flow. --- .../java/app/mealsmadeeasy/api/MvcConfiguration.java | 4 +++- .../app/mealsmadeeasy/api/auth/AuthController.java | 5 ++++- .../app/mealsmadeeasy/api/auth/AuthServiceImpl.java | 2 +- .../java/app/mealsmadeeasy/api/auth/LoginView.java | 10 +++++++++- .../java/app/mealsmadeeasy/api/auth/RefreshToken.java | 1 - .../mealsmadeeasy/api/auth/RefreshTokenEntity.java | 2 +- .../app/mealsmadeeasy/api/jwt/JwtServiceImpl.java | 11 +++++++++-- .../app/mealsmadeeasy/api/security/AuthToken.java | 3 +++ .../mealsmadeeasy/api/security/SimpleAuthToken.java | 11 ++++++++++- src/main/resources/application.properties | 2 +- 10 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/main/java/app/mealsmadeeasy/api/MvcConfiguration.java b/src/main/java/app/mealsmadeeasy/api/MvcConfiguration.java index 5ef1752..ca96ecd 100644 --- a/src/main/java/app/mealsmadeeasy/api/MvcConfiguration.java +++ b/src/main/java/app/mealsmadeeasy/api/MvcConfiguration.java @@ -14,7 +14,9 @@ public class MvcConfiguration { @Override public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**").allowedOrigins("http://localhost:5173"); + registry.addMapping("/**") + .allowedOrigins("http://localhost:5173") + .allowCredentials(true); } }; diff --git a/src/main/java/app/mealsmadeeasy/api/auth/AuthController.java b/src/main/java/app/mealsmadeeasy/api/auth/AuthController.java index ff6000c..f002e10 100644 --- a/src/main/java/app/mealsmadeeasy/api/auth/AuthController.java +++ b/src/main/java/app/mealsmadeeasy/api/auth/AuthController.java @@ -15,6 +15,7 @@ public final class AuthController { final ResponseCookie.ResponseCookieBuilder b = ResponseCookie.from("refresh-token") .httpOnly(true) .secure(true) + .sameSite("Lax") .maxAge(maxAge); if (token != null) { b.value(token); @@ -35,7 +36,9 @@ public final class AuthController { refreshToken.getLifetime() ); final var loginView = new LoginView( - loginDetails.getUsername(), loginDetails.getAccessToken().getToken() + loginDetails.getUsername(), + loginDetails.getAccessToken().getToken(), + loginDetails.getAccessToken().getExpires() ); return ResponseEntity.ok() .header(HttpHeaders.SET_COOKIE, refreshCookie.toString()) diff --git a/src/main/java/app/mealsmadeeasy/api/auth/AuthServiceImpl.java b/src/main/java/app/mealsmadeeasy/api/auth/AuthServiceImpl.java index 6d3bb1f..910ccb5 100644 --- a/src/main/java/app/mealsmadeeasy/api/auth/AuthServiceImpl.java +++ b/src/main/java/app/mealsmadeeasy/api/auth/AuthServiceImpl.java @@ -73,7 +73,7 @@ public final class AuthServiceImpl implements AuthService { if (old.isRevoked()) { throw new LoginException("RefreshToken is revoked."); } - if (old.getExpiration().isBefore(LocalDateTime.now())) { + if (old.getExpires().isBefore(LocalDateTime.now())) { throw new LoginException("RefreshToken is expired."); } final UserEntity principal = old.getOwner(); diff --git a/src/main/java/app/mealsmadeeasy/api/auth/LoginView.java b/src/main/java/app/mealsmadeeasy/api/auth/LoginView.java index b517385..0e0c8e4 100644 --- a/src/main/java/app/mealsmadeeasy/api/auth/LoginView.java +++ b/src/main/java/app/mealsmadeeasy/api/auth/LoginView.java @@ -1,13 +1,17 @@ package app.mealsmadeeasy.api.auth; +import java.time.LocalDateTime; + public final class LoginView { private final String username; private final String accessToken; + private final LocalDateTime expires; - public LoginView(String username, String accessToken) { + public LoginView(String username, String accessToken, LocalDateTime expires) { this.username = username; this.accessToken = accessToken; + this.expires = expires; } public String getUsername() { @@ -18,4 +22,8 @@ public final class LoginView { return this.accessToken; } + public LocalDateTime getExpires() { + return this.expires; + } + } diff --git a/src/main/java/app/mealsmadeeasy/api/auth/RefreshToken.java b/src/main/java/app/mealsmadeeasy/api/auth/RefreshToken.java index 9981290..ddad1f7 100644 --- a/src/main/java/app/mealsmadeeasy/api/auth/RefreshToken.java +++ b/src/main/java/app/mealsmadeeasy/api/auth/RefreshToken.java @@ -6,6 +6,5 @@ import java.time.LocalDateTime; public interface RefreshToken extends AuthToken { LocalDateTime getIssued(); - LocalDateTime getExpiration(); boolean isRevoked(); } diff --git a/src/main/java/app/mealsmadeeasy/api/auth/RefreshTokenEntity.java b/src/main/java/app/mealsmadeeasy/api/auth/RefreshTokenEntity.java index e7d8ebe..2e1c8be 100644 --- a/src/main/java/app/mealsmadeeasy/api/auth/RefreshTokenEntity.java +++ b/src/main/java/app/mealsmadeeasy/api/auth/RefreshTokenEntity.java @@ -45,7 +45,7 @@ public class RefreshTokenEntity implements RefreshToken { } @Override - public LocalDateTime getExpiration() { + public LocalDateTime getExpires() { return this.expiration; } diff --git a/src/main/java/app/mealsmadeeasy/api/jwt/JwtServiceImpl.java b/src/main/java/app/mealsmadeeasy/api/jwt/JwtServiceImpl.java index d083d2d..1a1c6d1 100644 --- a/src/main/java/app/mealsmadeeasy/api/jwt/JwtServiceImpl.java +++ b/src/main/java/app/mealsmadeeasy/api/jwt/JwtServiceImpl.java @@ -11,6 +11,8 @@ import org.springframework.stereotype.Service; import javax.crypto.SecretKey; import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.Date; import java.util.Map; @@ -33,14 +35,19 @@ public final class JwtServiceImpl implements JwtService { @Override public AuthToken generateAccessToken(String username) { final Instant now = Instant.now(); + final Instant expires = Instant.from(now.plusSeconds(accessTokenLifetime)); final String token = Jwts.builder() .subject(username) .issuedAt(Date.from(now)) - .expiration(Date.from(now.plusSeconds(this.accessTokenLifetime))) + .expiration(Date.from(expires)) .signWith(this.secretKey) .json(this.serializer) .compact(); - return new SimpleAuthToken(token, this.accessTokenLifetime); + return new SimpleAuthToken( + token, + this.accessTokenLifetime, + LocalDateTime.ofInstant(expires, ZoneId.systemDefault()) + ); } @Override diff --git a/src/main/java/app/mealsmadeeasy/api/security/AuthToken.java b/src/main/java/app/mealsmadeeasy/api/security/AuthToken.java index 10af099..a79dbf2 100644 --- a/src/main/java/app/mealsmadeeasy/api/security/AuthToken.java +++ b/src/main/java/app/mealsmadeeasy/api/security/AuthToken.java @@ -1,6 +1,9 @@ package app.mealsmadeeasy.api.security; +import java.time.LocalDateTime; + public interface AuthToken { String getToken(); long getLifetime(); + LocalDateTime getExpires(); } diff --git a/src/main/java/app/mealsmadeeasy/api/security/SimpleAuthToken.java b/src/main/java/app/mealsmadeeasy/api/security/SimpleAuthToken.java index f15d698..b418211 100644 --- a/src/main/java/app/mealsmadeeasy/api/security/SimpleAuthToken.java +++ b/src/main/java/app/mealsmadeeasy/api/security/SimpleAuthToken.java @@ -1,13 +1,17 @@ package app.mealsmadeeasy.api.security; +import java.time.LocalDateTime; + public final class SimpleAuthToken implements AuthToken { private final String token; private final long lifetime; + private LocalDateTime expires; - public SimpleAuthToken(String token, long lifetime) { + public SimpleAuthToken(String token, long lifetime, LocalDateTime expires) { this.token = token; this.lifetime = lifetime; + this.expires = expires; } @Override @@ -20,4 +24,9 @@ public final class SimpleAuthToken implements AuthToken { return this.lifetime; } + @Override + public LocalDateTime getExpires() { + return this.expires; + } + } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d795ca2..e1865f3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -5,7 +5,7 @@ spring.datasource.username=meals-made-easy-api-user spring.datasource.password=devpass spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver app.mealsmadeeasy.api.baseUrl=http://localhost:8080 -app.mealsmadeeasy.api.security.access-token-lifetime=60 +app.mealsmadeeasy.api.security.access-token-lifetime=10 app.mealsmadeeasy.api.security.refresh-token-lifetime=120 app.mealsmadeeasy.api.minio.endpoint=http://localhost:9000 app.mealsmadeeasy.api.minio.accessKey=minio-root