From 1ad9128fc3f46b0d87d685e8a81f1594c0ddcc3e Mon Sep 17 00:00:00 2001 From: ivyxjc Date: Thu, 5 Jun 2025 16:24:18 +0800 Subject: [PATCH 1/7] Revert "feat(example): setup mfa" This reverts commit 31580d9580897060c96d6efcb2e1ae517c2b5a49. --- .../springbootexample/AuthController.java | 7 ++-- .../springboot/springbootexample/Beans.java | 11 ++----- .../ChallengeSessionRepositoryAdapter.java | 8 ----- .../springbootexample/UserController.java | 33 ------------------- .../UserHmacSecretRepositoryAdapter.java | 11 ------- 5 files changed, 7 insertions(+), 63 deletions(-) delete mode 100644 examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/ChallengeSessionRepositoryAdapter.java delete mode 100644 examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserController.java delete mode 100644 examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserHmacSecretRepositoryAdapter.java diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java index e813433..2a7ae46 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java @@ -4,13 +4,14 @@ import com.auth0.jwt.interfaces.DecodedJWT; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.UserRegisterRequest; -import org.clevercastle.authforge.UserService; -import org.clevercastle.authforge.UserWithToken; import org.clevercastle.authforge.dto.OneTimePasswordDto; import org.clevercastle.authforge.exception.CastleException; +import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.model.User; import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.UserRegisterRequest; +import org.clevercastle.authforge.UserService; +import org.clevercastle.authforge.UserWithToken; import org.clevercastle.authforge.oauth2.Oauth2ClientConfig; import org.clevercastle.authforge.oauth2.github.GithubOauth2ExchangeService; import org.clevercastle.authforge.oauth2.oidc.OidcExchangeService; diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java index 0c60204..35d71b9 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java @@ -1,15 +1,12 @@ package org.clevercastle.authforge.examples.springboot.springbootexample; import com.auth0.jwt.algorithms.Algorithm; -import org.clevercastle.authforge.DummyCacheServiceImpl; import org.clevercastle.authforge.Config; import org.clevercastle.authforge.UserService; import org.clevercastle.authforge.UserServiceImpl; import org.clevercastle.authforge.repository.UserRepository; import org.clevercastle.authforge.repository.dynamodb.DynamodbUserRepositoryImpl; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaChallengeSessionRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaOneTimePasswordRepository; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserHmacSecretRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserLoginItemRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserModelRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserRefreshTokenMappingRepository; @@ -41,11 +38,9 @@ public class Beans { public UserRepository userRepository(RdsJpaUserModelRepository userModelRepository, RdsJpaUserLoginItemRepository userLoginItemRepository, RdsJpaUserRefreshTokenMappingRepository userRefreshTokenMappingRepository, - RdsJpaOneTimePasswordRepository oneTimePasswordRepository, - RdsJpaChallengeSessionRepository challengeSessionRepository, - RdsJpaUserHmacSecretRepository userHmacSecretRepository) { + RdsJpaOneTimePasswordRepository oneTimePasswordRepository) { return new RdsJpaUserRepositoryImpl(userModelRepository, userLoginItemRepository, - userRefreshTokenMappingRepository, oneTimePasswordRepository, challengeSessionRepository, userHmacSecretRepository); + userRefreshTokenMappingRepository, oneTimePasswordRepository); } @@ -85,7 +80,7 @@ public TokenService tokenService() throws NoSuchAlgorithmException, InvalidKeySp @Bean public UserService userService(UserRepository userRepository, TokenService tokenService) { - return new UserServiceImpl(Config.builder().build(), userRepository, tokenService, new DummyCodeSender(), new DummyCacheServiceImpl()); + return new UserServiceImpl(Config.builder().build(), userRepository, tokenService, new DummyCodeSender()); } diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/ChallengeSessionRepositoryAdapter.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/ChallengeSessionRepositoryAdapter.java deleted file mode 100644 index 24da352..0000000 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/ChallengeSessionRepositoryAdapter.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.clevercastle.authforge.examples.springboot.springbootexample; - -import org.clevercastle.authforge.model.ChallengeSession; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaChallengeSessionRepository; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface ChallengeSessionRepositoryAdapter extends RdsJpaChallengeSessionRepository, JpaRepository { -} diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserController.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserController.java deleted file mode 100644 index eff85fb..0000000 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserController.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.clevercastle.authforge.examples.springboot.springbootexample; - -import org.clevercastle.authforge.UserService; -import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.totp.RequestTotpResponse; -import org.clevercastle.authforge.totp.SetupTotpRequest; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class UserController { - - private final UserService userService; - - public UserController(UserService userService) { - this.userService = userService; - } - - @PostMapping("user/mfa/request") - public RequestTotpResponse requestTotp() throws CastleException { - User user = new User(); - return userService.requestTotp(user); - } - - @PostMapping("user/mfa/verify") - public void verifyTotp(@RequestBody SetupTotpRequest request) throws CastleException { - User user = new User(); - user.setUserId("user-01"); - userService.setupTotp(user, request); - } -} diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserHmacSecretRepositoryAdapter.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserHmacSecretRepositoryAdapter.java deleted file mode 100644 index 41d2c7f..0000000 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserHmacSecretRepositoryAdapter.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.clevercastle.authforge.examples.springboot.springbootexample; - -import org.clevercastle.authforge.model.ChallengeSession; -import org.clevercastle.authforge.model.UserHmacSecret; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaChallengeSessionRepository; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserHmacSecretId; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserHmacSecretRepository; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface UserHmacSecretRepositoryAdapter extends RdsJpaUserHmacSecretRepository, JpaRepository { -} From a07537cbf85bbb682d25c849fc125baec2060986 Mon Sep 17 00:00:00 2001 From: ivyxjc Date: Thu, 5 Jun 2025 16:24:18 +0800 Subject: [PATCH 2/7] Revert "feat(): setup mfa" This reverts commit ce64f8a76e32b5181ccedd35dd3540346534c9d3. --- docs/mfa.md | 18 ----- .../clevercastle/authforge/CacheService.java | 9 --- .../authforge/DummyCacheServiceImpl.java | 26 ------ .../clevercastle/authforge/UserService.java | 15 +--- .../authforge/UserServiceImpl.java | 52 +----------- .../authforge/model/ChallengeSession.java | 57 ------------- .../authforge/model/ResourceType.java | 7 -- .../authforge/model/UserHmacSecret.java | 79 ------------------- .../authforge/repository/UserRepository.java | 13 +-- .../dynamodb/DynamodbUserRepositoryImpl.java | 17 ---- .../RdsJpaChallengeSessionRepository.java | 9 --- .../rdsjpa/RdsJpaUserHmacSecretId.java | 24 ------ .../RdsJpaUserHmacSecretRepository.java | 11 --- .../rdsjpa/RdsJpaUserRepositoryImpl.java | 25 +----- .../authforge/totp/RequestTotpResponse.java | 22 ------ .../authforge/totp/SetupTotpRequest.java | 33 -------- .../totp/SetupTotpVerificationCode.java | 24 ------ .../clevercastle/authforge/util/IdUtil.java | 6 -- 18 files changed, 7 insertions(+), 440 deletions(-) delete mode 100644 docs/mfa.md delete mode 100644 src/main/java/org/clevercastle/authforge/CacheService.java delete mode 100644 src/main/java/org/clevercastle/authforge/DummyCacheServiceImpl.java delete mode 100644 src/main/java/org/clevercastle/authforge/model/ChallengeSession.java delete mode 100644 src/main/java/org/clevercastle/authforge/model/ResourceType.java delete mode 100644 src/main/java/org/clevercastle/authforge/model/UserHmacSecret.java delete mode 100644 src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaChallengeSessionRepository.java delete mode 100644 src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserHmacSecretId.java delete mode 100644 src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserHmacSecretRepository.java delete mode 100644 src/main/java/org/clevercastle/authforge/totp/RequestTotpResponse.java delete mode 100644 src/main/java/org/clevercastle/authforge/totp/SetupTotpRequest.java delete mode 100644 src/main/java/org/clevercastle/authforge/totp/SetupTotpVerificationCode.java diff --git a/docs/mfa.md b/docs/mfa.md deleted file mode 100644 index f602307..0000000 --- a/docs/mfa.md +++ /dev/null @@ -1,18 +0,0 @@ -# Mfa Flow - -```mermaid -flowchart TD - A[User login] --> B{Authenticated?} - B -- No --> Z[Fail to login] - B -- Yes --> C[Show the mfa setup options] - C --> D[User: Setup mfa] - D --> E[Server generate the secret key and return the QR code string and one session-id, save this secret key in the system with key session-id] - E --> F[Client: Show the QR code to the user,] - F --> G[User: user use authenticator app to scan the QR code] - G --> H[User: user input the first verification code] - H --> I[Client: pass the session-id and the verification code to the server] - I --> J[Server: get the secret key based on the session-id and verify the code] - J -- Success to verify --> K[Server: Notify the user to input the verification code again] - J -- Fail to verify --> L[Server: Save the secret key to the database and return success] - K --> I -``` \ No newline at end of file diff --git a/src/main/java/org/clevercastle/authforge/CacheService.java b/src/main/java/org/clevercastle/authforge/CacheService.java deleted file mode 100644 index 0a3f8ba..0000000 --- a/src/main/java/org/clevercastle/authforge/CacheService.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.clevercastle.authforge; - -public interface CacheService { - void set(String key, String value, long ttl); - - String get(String key); - - boolean delete(String key); -} diff --git a/src/main/java/org/clevercastle/authforge/DummyCacheServiceImpl.java b/src/main/java/org/clevercastle/authforge/DummyCacheServiceImpl.java deleted file mode 100644 index 54ad2fd..0000000 --- a/src/main/java/org/clevercastle/authforge/DummyCacheServiceImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.clevercastle.authforge; - -import org.apache.commons.lang3.StringUtils; - -import java.util.HashMap; -import java.util.Map; - -public class DummyCacheServiceImpl implements CacheService { - Map map = new HashMap<>(); - - @Override - public void set(String key, String value, long ttl) { - map.put(key, value); - } - - @Override - public String get(String key) { - return map.get(key); - } - - @Override - public boolean delete(String key) { - String value = map.remove(key); - return StringUtils.isNotBlank(value); - } -} diff --git a/src/main/java/org/clevercastle/authforge/UserService.java b/src/main/java/org/clevercastle/authforge/UserService.java index 5df10ab..6555474 100644 --- a/src/main/java/org/clevercastle/authforge/UserService.java +++ b/src/main/java/org/clevercastle/authforge/UserService.java @@ -2,13 +2,11 @@ import org.apache.commons.lang3.tuple.Pair; import org.clevercastle.authforge.dto.OneTimePasswordDto; -import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.ChallengeSession; import org.clevercastle.authforge.model.User; import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.exception.CastleException; +import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.oauth2.Oauth2ClientConfig; -import org.clevercastle.authforge.totp.RequestTotpResponse; -import org.clevercastle.authforge.totp.SetupTotpRequest; public interface UserService { // used for username/password, email/password, mobile/password @@ -29,16 +27,7 @@ public interface UserService { // used for sso login UserWithToken exchange(Oauth2ClientConfig clientConfig, String authorizationCode, String state, String redirectUrl) throws CastleException; - // one time password login OneTimePasswordDto requestOneTimePassword(String loginIdentifier) throws CastleException; UserWithToken verifyOneTimePassword(String loginIdentifier, String oneTimePassword) throws CastleException; - - // mfa challenge - ChallengeSession createChallenge(String userId, ChallengeSession.Type type); - - RequestTotpResponse requestTotp(User user) throws CastleException; - - // setup mfa - void setupTotp(User user, SetupTotpRequest request) throws CastleException; } diff --git a/src/main/java/org/clevercastle/authforge/UserServiceImpl.java b/src/main/java/org/clevercastle/authforge/UserServiceImpl.java index a142cad..51943b7 100644 --- a/src/main/java/org/clevercastle/authforge/UserServiceImpl.java +++ b/src/main/java/org/clevercastle/authforge/UserServiceImpl.java @@ -14,27 +14,22 @@ import jakarta.annotation.Nonnull; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.code.CodeSender; import org.clevercastle.authforge.dto.OneTimePasswordDto; import org.clevercastle.authforge.exception.CastleException; import org.clevercastle.authforge.exception.UserExistException; import org.clevercastle.authforge.exception.UserNotFoundException; -import org.clevercastle.authforge.model.ChallengeSession; import org.clevercastle.authforge.model.OneTimePassword; -import org.clevercastle.authforge.model.ResourceType; import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserHmacSecret; import org.clevercastle.authforge.model.UserLoginItem; import org.clevercastle.authforge.oauth2.Oauth2ClientConfig; import org.clevercastle.authforge.oauth2.Oauth2User; import org.clevercastle.authforge.repository.UserRepository; import org.clevercastle.authforge.token.TokenService; -import org.clevercastle.authforge.totp.RequestTotpResponse; -import org.clevercastle.authforge.totp.SetupTotpRequest; import org.clevercastle.authforge.util.CodeUtil; import org.clevercastle.authforge.util.HashUtil; import org.clevercastle.authforge.util.IdUtil; import org.clevercastle.authforge.util.TimeUtils; +import org.clevercastle.authforge.code.CodeSender; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,18 +47,15 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final TokenService tokenService; private final CodeSender codeSender; - private final CacheService cacheService; public UserServiceImpl(Config config, UserRepository userRepository, TokenService tokenService, - CodeSender codeSender, - CacheService cacheService) { + CodeSender codeSender) { this.config = config; this.userRepository = userRepository; this.tokenService = tokenService; this.codeSender = codeSender; - this.cacheService = cacheService; } @Override @@ -344,44 +336,4 @@ public UserWithToken verifyOneTimePassword(String loginIdentifier, String oneTim userRepository.addRefreshToken(pair.getLeft(), tokenHolder.getRefreshToken(), tokenHolder.getExpiresAt()); return new UserWithToken(pair.getLeft(), tokenHolder); } - - @Override - public ChallengeSession createChallenge(String userId, ChallengeSession.Type type) { - ChallengeSession.Type sessionType = null; - ChallengeSession session = new ChallengeSession(); - session.setId(IdUtil.genId(ResourceType.challengeSession)); - session.setType(type); - session.setUserId(userId); - session.setCreatedAt(TimeUtils.now()); - return session; - } - - @Override - public RequestTotpResponse requestTotp(User user) throws CastleException { - String key = UUID.randomUUID().toString(); - String secret = UUID.randomUUID().toString(); - cacheService.set(key, secret, 120); - RequestTotpResponse requestTotpDto = new RequestTotpResponse(); - requestTotpDto.setSessionId(key); - requestTotpDto.setSecret(secret); - return requestTotpDto; - } - - @Override - public void setupTotp(User user, SetupTotpRequest request) throws CastleException { - String secret = cacheService.get(request.getSessionId()); - if (StringUtils.isBlank(secret)) { - throw new CastleException(); - } - // todo verify the user input verification code - UserHmacSecret userHmacSecret = new UserHmacSecret(); - userHmacSecret.setUserId(user.getUserId()); - userHmacSecret.setId(IdUtil.genId(ResourceType.totp)); - userHmacSecret.setSecret(secret); - var now = TimeUtils.now(); - userHmacSecret.setCreatedAt(now); - userHmacSecret.setLastUsedAt(now); - userHmacSecret.setName(request.getName()); - userRepository.createHmacSecret(userHmacSecret); - } } diff --git a/src/main/java/org/clevercastle/authforge/model/ChallengeSession.java b/src/main/java/org/clevercastle/authforge/model/ChallengeSession.java deleted file mode 100644 index 18f3bd2..0000000 --- a/src/main/java/org/clevercastle/authforge/model/ChallengeSession.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.clevercastle.authforge.model; - -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - -import java.time.OffsetDateTime; - -@javax.persistence.Entity -@javax.persistence.Table(name = "challenge_session") -@Entity -@Table(name = "challenge_session") -public class ChallengeSession { - public enum Type { - mfa, - } - - @javax.persistence.Id - @Id - private String id; - private Type type; - - private String userId; - private OffsetDateTime createdAt; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public Type getType() { - return type; - } - - public void setType(Type type) { - this.type = type; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public OffsetDateTime getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(OffsetDateTime createdAt) { - this.createdAt = createdAt; - } -} diff --git a/src/main/java/org/clevercastle/authforge/model/ResourceType.java b/src/main/java/org/clevercastle/authforge/model/ResourceType.java deleted file mode 100644 index 1d56821..0000000 --- a/src/main/java/org/clevercastle/authforge/model/ResourceType.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.clevercastle.authforge.model; - -public enum ResourceType { - user, - challengeSession, - totp -} diff --git a/src/main/java/org/clevercastle/authforge/model/UserHmacSecret.java b/src/main/java/org/clevercastle/authforge/model/UserHmacSecret.java deleted file mode 100644 index 2a638c2..0000000 --- a/src/main/java/org/clevercastle/authforge/model/UserHmacSecret.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.clevercastle.authforge.model; - -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.IdClass; -import jakarta.persistence.Table; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserHmacSecretId; - -import java.time.OffsetDateTime; - -@javax.persistence.Entity -@javax.persistence.Table(name = "user_hmac_secret") -@Entity -@Table(name = "user_hmac_secret") -@javax.persistence.IdClass(RdsJpaUserHmacSecretId.class) -@IdClass(RdsJpaUserHmacSecretId.class) -public class UserHmacSecret { - @javax.persistence.Id - @Id - private String userId; - @javax.persistence.Id - @Id - private String id; - - private String secret; - private String name; - - private OffsetDateTime lastUsedAt; - - private OffsetDateTime createdAt; - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getSecret() { - return secret; - } - - public void setSecret(String secret) { - this.secret = secret; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public OffsetDateTime getLastUsedAt() { - return lastUsedAt; - } - - public void setLastUsedAt(OffsetDateTime lastUsedAt) { - this.lastUsedAt = lastUsedAt; - } - - public OffsetDateTime getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(OffsetDateTime createdAt) { - this.createdAt = createdAt; - } -} diff --git a/src/main/java/org/clevercastle/authforge/repository/UserRepository.java b/src/main/java/org/clevercastle/authforge/repository/UserRepository.java index b66e36c..f38cbc5 100644 --- a/src/main/java/org/clevercastle/authforge/repository/UserRepository.java +++ b/src/main/java/org/clevercastle/authforge/repository/UserRepository.java @@ -2,16 +2,13 @@ import jakarta.annotation.Nonnull; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.ChallengeSession; -import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserHmacSecret; import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.model.UserRefreshTokenMapping; +import org.clevercastle.authforge.exception.CastleException; import java.time.OffsetDateTime; -import java.util.List; public interface UserRepository { void save(User user, UserLoginItem userLoginItem) throws CastleException; @@ -31,10 +28,4 @@ public interface UserRepository { void saveOneTimePassword(OneTimePassword userOneTimePasswordMapping) throws CastleException; boolean verifyOneTimePassword(String loginIdentifier, String oneTimePassword) throws CastleException; - - void createHmacSecret(UserHmacSecret userHmacSecret) throws CastleException; - - List listHmacSecretByUserId(String userId) throws CastleException; - - void createChallenge(ChallengeSession session) throws CastleException; } \ No newline at end of file diff --git a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java index 119e46f..32f2b1b 100644 --- a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java +++ b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java @@ -5,10 +5,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.ChallengeSession; import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserHmacSecret; import org.clevercastle.authforge.model.UserLoginItem; import org.clevercastle.authforge.model.UserRefreshTokenMapping; import org.clevercastle.authforge.repository.UserRepository; @@ -177,19 +175,4 @@ public void saveOneTimePassword(OneTimePassword userOneTimePasswordMapping) thro public boolean verifyOneTimePassword(String loginIdentifier, String oneTimePassword) throws CastleException { throw new NotImplementedException(); } - - @Override - public void createHmacSecret(UserHmacSecret userHmacSecret) throws CastleException { - - } - - @Override - public List listHmacSecretByUserId(String userId) throws CastleException { - return List.of(); - } - - @Override - public void createChallenge(ChallengeSession session) throws CastleException { - - } } diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaChallengeSessionRepository.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaChallengeSessionRepository.java deleted file mode 100644 index f90d022..0000000 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaChallengeSessionRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.clevercastle.authforge.repository.rdsjpa; - -import org.clevercastle.authforge.model.ChallengeSession; - -public interface RdsJpaChallengeSessionRepository { - ChallengeSession save(ChallengeSession challengeSession); - - ChallengeSession getById(String id); -} diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserHmacSecretId.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserHmacSecretId.java deleted file mode 100644 index 04a5128..0000000 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserHmacSecretId.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.clevercastle.authforge.repository.rdsjpa; - -import java.io.Serializable; - -public class RdsJpaUserHmacSecretId implements Serializable { - private String userId; - private String id; - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } -} diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserHmacSecretRepository.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserHmacSecretRepository.java deleted file mode 100644 index b561fa0..0000000 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserHmacSecretRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.clevercastle.authforge.repository.rdsjpa; - -import org.clevercastle.authforge.model.UserHmacSecret; - -import java.util.List; - -public interface RdsJpaUserHmacSecretRepository { - UserHmacSecret save(UserHmacSecret userHmacSecret); - - List getByUserId(String userId); -} diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java index eda5c8b..45b3d4d 100644 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java +++ b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java @@ -4,9 +4,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.ChallengeSession; import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserHmacSecret; import org.clevercastle.authforge.model.UserLoginItem; import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.model.UserRefreshTokenMapping; @@ -21,21 +19,15 @@ public class RdsJpaUserRepositoryImpl implements UserRepository { private final RdsJpaUserLoginItemRepository userLoginItemRepository; private final RdsJpaUserRefreshTokenMappingRepository userRefreshTokenMappingRepository; private final RdsJpaOneTimePasswordRepository oneTimePasswordRepository; - private final RdsJpaChallengeSessionRepository challengeSessionRepository; - private final RdsJpaUserHmacSecretRepository userHmacSecretRepository; public RdsJpaUserRepositoryImpl(RdsJpaUserModelRepository userModelRepository, RdsJpaUserLoginItemRepository userLoginItemRepository, RdsJpaUserRefreshTokenMappingRepository userRefreshTokenMappingRepository, - RdsJpaOneTimePasswordRepository oneTimePasswordRepository, - RdsJpaChallengeSessionRepository challengeSessionRepository, - RdsJpaUserHmacSecretRepository userHmacSecretRepository) { + RdsJpaOneTimePasswordRepository oneTimePasswordRepository) { this.userModelRepository = userModelRepository; this.userLoginItemRepository = userLoginItemRepository; this.userRefreshTokenMappingRepository = userRefreshTokenMappingRepository; this.oneTimePasswordRepository = oneTimePasswordRepository; - this.challengeSessionRepository = challengeSessionRepository; - this.userHmacSecretRepository = userHmacSecretRepository; } @Override @@ -115,19 +107,4 @@ public boolean verifyOneTimePassword(String loginIdentifier, String oneTimePassw } return false; } - - @Override - public void createHmacSecret(UserHmacSecret userHmacSecret) throws CastleException { - this.userHmacSecretRepository.save(userHmacSecret); - } - - @Override - public List listHmacSecretByUserId(String userId) throws CastleException { - return this.userHmacSecretRepository.getByUserId(userId); - } - - @Override - public void createChallenge(ChallengeSession session) throws CastleException { - this.challengeSessionRepository.save(session); - } } diff --git a/src/main/java/org/clevercastle/authforge/totp/RequestTotpResponse.java b/src/main/java/org/clevercastle/authforge/totp/RequestTotpResponse.java deleted file mode 100644 index 26032a0..0000000 --- a/src/main/java/org/clevercastle/authforge/totp/RequestTotpResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.clevercastle.authforge.totp; - -public class RequestTotpResponse { - private String sessionId; - private String secret; - - public String getSessionId() { - return sessionId; - } - - public void setSessionId(String sessionId) { - this.sessionId = sessionId; - } - - public String getSecret() { - return secret; - } - - public void setSecret(String secret) { - this.secret = secret; - } -} diff --git a/src/main/java/org/clevercastle/authforge/totp/SetupTotpRequest.java b/src/main/java/org/clevercastle/authforge/totp/SetupTotpRequest.java deleted file mode 100644 index 9a54383..0000000 --- a/src/main/java/org/clevercastle/authforge/totp/SetupTotpRequest.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.clevercastle.authforge.totp; - -import java.util.List; - -public class SetupTotpRequest { - private String sessionId; - private String name; - private List codes; - - public String getSessionId() { - return sessionId; - } - - public void setSessionId(String sessionId) { - this.sessionId = sessionId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public List getCodes() { - return codes; - } - - public void setCodes(List codes) { - this.codes = codes; - } -} diff --git a/src/main/java/org/clevercastle/authforge/totp/SetupTotpVerificationCode.java b/src/main/java/org/clevercastle/authforge/totp/SetupTotpVerificationCode.java deleted file mode 100644 index 575ac12..0000000 --- a/src/main/java/org/clevercastle/authforge/totp/SetupTotpVerificationCode.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.clevercastle.authforge.totp; - -import java.time.OffsetDateTime; - -public class SetupTotpVerificationCode { - private OffsetDateTime inputTime; - private String code; - - public OffsetDateTime getInputTime() { - return inputTime; - } - - public void setInputTime(OffsetDateTime inputTime) { - this.inputTime = inputTime; - } - - public String getCode() { - return code; - } - - public void setCode(String code) { - this.code = code; - } -} diff --git a/src/main/java/org/clevercastle/authforge/util/IdUtil.java b/src/main/java/org/clevercastle/authforge/util/IdUtil.java index f05bbe9..de12e12 100644 --- a/src/main/java/org/clevercastle/authforge/util/IdUtil.java +++ b/src/main/java/org/clevercastle/authforge/util/IdUtil.java @@ -1,15 +1,9 @@ package org.clevercastle.authforge.util; -import org.clevercastle.authforge.model.ResourceType; - import java.util.UUID; public class IdUtil { public static String genUserId() { return "user-" + UUID.randomUUID(); } - - public static String genId(ResourceType resourceType) { - return UUID.randomUUID().toString(); - } } From 8cd8ff1b00e48d2f67992f2bc58f88941d9942c6 Mon Sep 17 00:00:00 2001 From: ivyxjc Date: Thu, 5 Jun 2025 16:24:18 +0800 Subject: [PATCH 3/7] Revert "feat(example): login with one time password" This reverts commit 4cc3ec92f105593c12231937cf2376a429dea1a5. --- .../springbootexample/AuthController.java | 16 ++------------ .../springboot/springbootexample/Beans.java | 14 +++++------- .../OneTimePasswordRepositoryAdapter.java | 9 -------- .../springbootexample/SendOneTimeRequest.java | 13 ----------- .../VerifyOneTimeRequest.java | 22 ------------------- 5 files changed, 8 insertions(+), 66 deletions(-) delete mode 100644 examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/OneTimePasswordRepositoryAdapter.java delete mode 100644 examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/SendOneTimeRequest.java delete mode 100644 examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/VerifyOneTimeRequest.java diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java index 2a7ae46..3c51a83 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java @@ -4,9 +4,7 @@ import com.auth0.jwt.interfaces.DecodedJWT; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.dto.OneTimePasswordDto; import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.model.User; import org.clevercastle.authforge.model.UserLoginItem; import org.clevercastle.authforge.UserRegisterRequest; @@ -88,8 +86,8 @@ public User register(@RequestBody RegisterRequest request) throws CastleExceptio @GetMapping("auth/verify") - public UserWithToken verify(@RequestParam String email, @RequestParam String verificationCode) throws CastleException { - userService.verify("email#" + email, verificationCode); + public UserWithToken verify(@RequestParam String loginIdentifier, @RequestParam String verificationCode) throws CastleException { + userService.verify("email#" + loginIdentifier, verificationCode); return null; } @@ -143,14 +141,4 @@ public UserWithToken exchange(@RequestParam SsoType ssoType, @RequestParam Strin } return null; } - - @GetMapping("auth/one-time-password") - public OneTimePasswordDto requestOneTimePassword(@RequestParam String email) throws CastleException { - return userService.requestOneTimePassword("email#" + email); - } - - @PostMapping("auth/one-time-password") - public UserWithToken verifyOneTimePassword(@RequestBody VerifyOneTimeRequest request) throws CastleException { - return userService.verifyOneTimePassword("email#" + request.getEmail(), request.getOneTimePassword()); - } } diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java index 35d71b9..5aa8f63 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java @@ -5,15 +5,15 @@ import org.clevercastle.authforge.UserService; import org.clevercastle.authforge.UserServiceImpl; import org.clevercastle.authforge.repository.UserRepository; +import org.clevercastle.authforge.repository.dynamodb.DynamodbUser; import org.clevercastle.authforge.repository.dynamodb.DynamodbUserRepositoryImpl; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaOneTimePasswordRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserLoginItemRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserModelRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserRefreshTokenMappingRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserRepositoryImpl; import org.clevercastle.authforge.token.TokenService; import org.clevercastle.authforge.token.jwt.JwtTokenService; -import org.clevercastle.authforge.code.DummyCodeSender; +import org.clevercastle.authforge.verification.DummyVerificationService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; @@ -37,10 +37,8 @@ public class Beans { @Bean public UserRepository userRepository(RdsJpaUserModelRepository userModelRepository, RdsJpaUserLoginItemRepository userLoginItemRepository, - RdsJpaUserRefreshTokenMappingRepository userRefreshTokenMappingRepository, - RdsJpaOneTimePasswordRepository oneTimePasswordRepository) { - return new RdsJpaUserRepositoryImpl(userModelRepository, userLoginItemRepository, - userRefreshTokenMappingRepository, oneTimePasswordRepository); + RdsJpaUserRefreshTokenMappingRepository userRefreshTokenMappingRepository) { + return new RdsJpaUserRepositoryImpl(userModelRepository, userLoginItemRepository, userRefreshTokenMappingRepository); } @@ -79,8 +77,8 @@ public TokenService tokenService() throws NoSuchAlgorithmException, InvalidKeySp } @Bean - public UserService userService(UserRepository userRepository, TokenService tokenService) { - return new UserServiceImpl(Config.builder().build(), userRepository, tokenService, new DummyCodeSender()); + public UserService userService(UserRepository dynamodbUserRepository, TokenService tokenService) { + return new UserServiceImpl(Config.builder().build(), dynamodbUserRepository, tokenService, new DummyVerificationService(dynamodbUserRepository)); } diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/OneTimePasswordRepositoryAdapter.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/OneTimePasswordRepositoryAdapter.java deleted file mode 100644 index e180bbd..0000000 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/OneTimePasswordRepositoryAdapter.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.clevercastle.authforge.examples.springboot.springbootexample; - -import org.clevercastle.authforge.model.OneTimePassword; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaOneTimePasswordId; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaOneTimePasswordRepository; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface OneTimePasswordRepositoryAdapter extends RdsJpaOneTimePasswordRepository, JpaRepository { -} diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/SendOneTimeRequest.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/SendOneTimeRequest.java deleted file mode 100644 index b678839..0000000 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/SendOneTimeRequest.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.clevercastle.authforge.examples.springboot.springbootexample; - -public class SendOneTimeRequest { - private String email; - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } -} diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/VerifyOneTimeRequest.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/VerifyOneTimeRequest.java deleted file mode 100644 index 267247d..0000000 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/VerifyOneTimeRequest.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.clevercastle.authforge.examples.springboot.springbootexample; - -public class VerifyOneTimeRequest { - private String email; - private String oneTimePassword; - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getOneTimePassword() { - return oneTimePassword; - } - - public void setOneTimePassword(String oneTimePassword) { - this.oneTimePassword = oneTimePassword; - } -} From 9a3cb6ee13d1970d9335e59d6797e054e75e4586 Mon Sep 17 00:00:00 2001 From: ivyxjc Date: Thu, 5 Jun 2025 16:24:18 +0800 Subject: [PATCH 4/7] Revert "feat(): login in with one time password" This reverts commit 695a5c3fbf293ba3bbd2d7288ee0e19e0171ea50. --- .../org/clevercastle/authforge/Config.java | 26 +++---- .../clevercastle/authforge/UserService.java | 6 -- .../authforge/UserServiceImpl.java | 74 ++----------------- .../authforge/code/CodeSender.java | 9 --- .../authforge/code/DummyCodeSender.java | 23 ------ .../authforge/dto/OneTimePasswordDto.java | 33 --------- .../authforge/model/OneTimePassword.java | 60 --------------- .../authforge/repository/UserRepository.java | 5 -- .../dynamodb/DynamodbUserRepositoryImpl.java | 14 +--- .../rdsjpa/RdsJpaOneTimePasswordId.java | 32 -------- .../RdsJpaOneTimePasswordRepository.java | 13 ---- .../rdsjpa/RdsJpaUserRepositoryImpl.java | 26 +------ .../clevercastle/authforge/util/CodeUtil.java | 27 ++++--- .../AbstractVerificationService.java | 41 ++++++++++ .../DummyVerificationService.java | 20 +++++ .../SendVerificationCodeResponse.java} | 6 +- .../verification/VerificationService.java | 9 +++ 17 files changed, 107 insertions(+), 317 deletions(-) delete mode 100644 src/main/java/org/clevercastle/authforge/code/CodeSender.java delete mode 100644 src/main/java/org/clevercastle/authforge/code/DummyCodeSender.java delete mode 100644 src/main/java/org/clevercastle/authforge/dto/OneTimePasswordDto.java delete mode 100644 src/main/java/org/clevercastle/authforge/model/OneTimePassword.java delete mode 100644 src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaOneTimePasswordId.java delete mode 100644 src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaOneTimePasswordRepository.java create mode 100644 src/main/java/org/clevercastle/authforge/verification/AbstractVerificationService.java create mode 100644 src/main/java/org/clevercastle/authforge/verification/DummyVerificationService.java rename src/main/java/org/clevercastle/authforge/{code/SendCodeResponse.java => verification/SendVerificationCodeResponse.java} (52%) create mode 100644 src/main/java/org/clevercastle/authforge/verification/VerificationService.java diff --git a/src/main/java/org/clevercastle/authforge/Config.java b/src/main/java/org/clevercastle/authforge/Config.java index c06ec4a..44e2822 100644 --- a/src/main/java/org/clevercastle/authforge/Config.java +++ b/src/main/java/org/clevercastle/authforge/Config.java @@ -1,12 +1,10 @@ package org.clevercastle.authforge; public class Config { - // in second + // in seconds private int verificationCodeExpireTime; - // in second + // in seconds private int tokenExpireTime; - // in second - private int oneTimePasswordExpireTime; public int getVerificationCodeExpireTime() { return verificationCodeExpireTime; @@ -16,22 +14,22 @@ public int getTokenExpireTime() { return tokenExpireTime; } - public int getOneTimePasswordExpireTime() { - return oneTimePasswordExpireTime; - } public static ConfigBuilder builder() { return new ConfigBuilder(); } public static final class ConfigBuilder { - private int verificationCodeExpireTime; - private int tokenExpireTime; - private int oneTimePasswordExpireTime; + private int verificationCodeExpireTime = 300; + private int tokenExpireTime = 28400; private ConfigBuilder() { } + public static ConfigBuilder aConfig() { + return new ConfigBuilder(); + } + public ConfigBuilder verificationCodeExpireTime(int verificationCodeExpireTime) { this.verificationCodeExpireTime = verificationCodeExpireTime; return this; @@ -42,16 +40,10 @@ public ConfigBuilder tokenExpireTime(int tokenExpireTime) { return this; } - public ConfigBuilder oneTimePasswordExpireTime(int oneTimePasswordExpireTime) { - this.oneTimePasswordExpireTime = oneTimePasswordExpireTime; - return this; - } - public Config build() { Config config = new Config(); - config.tokenExpireTime = this.tokenExpireTime; - config.oneTimePasswordExpireTime = this.oneTimePasswordExpireTime; config.verificationCodeExpireTime = this.verificationCodeExpireTime; + config.tokenExpireTime = this.tokenExpireTime; return config; } } diff --git a/src/main/java/org/clevercastle/authforge/UserService.java b/src/main/java/org/clevercastle/authforge/UserService.java index 6555474..b6276ad 100644 --- a/src/main/java/org/clevercastle/authforge/UserService.java +++ b/src/main/java/org/clevercastle/authforge/UserService.java @@ -1,11 +1,9 @@ package org.clevercastle.authforge; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.dto.OneTimePasswordDto; import org.clevercastle.authforge.model.User; import org.clevercastle.authforge.model.UserLoginItem; import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.oauth2.Oauth2ClientConfig; public interface UserService { @@ -26,8 +24,4 @@ public interface UserService { // used for sso login UserWithToken exchange(Oauth2ClientConfig clientConfig, String authorizationCode, String state, String redirectUrl) throws CastleException; - - OneTimePasswordDto requestOneTimePassword(String loginIdentifier) throws CastleException; - - UserWithToken verifyOneTimePassword(String loginIdentifier, String oneTimePassword) throws CastleException; } diff --git a/src/main/java/org/clevercastle/authforge/UserServiceImpl.java b/src/main/java/org/clevercastle/authforge/UserServiceImpl.java index 51943b7..b9a79d6 100644 --- a/src/main/java/org/clevercastle/authforge/UserServiceImpl.java +++ b/src/main/java/org/clevercastle/authforge/UserServiceImpl.java @@ -14,11 +14,9 @@ import jakarta.annotation.Nonnull; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.dto.OneTimePasswordDto; import org.clevercastle.authforge.exception.CastleException; import org.clevercastle.authforge.exception.UserExistException; import org.clevercastle.authforge.exception.UserNotFoundException; -import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.model.User; import org.clevercastle.authforge.model.UserLoginItem; import org.clevercastle.authforge.oauth2.Oauth2ClientConfig; @@ -29,7 +27,7 @@ import org.clevercastle.authforge.util.HashUtil; import org.clevercastle.authforge.util.IdUtil; import org.clevercastle.authforge.util.TimeUtils; -import org.clevercastle.authforge.code.CodeSender; +import org.clevercastle.authforge.verification.VerificationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,16 +44,16 @@ public class UserServiceImpl implements UserService { private final Config config; private final UserRepository userRepository; private final TokenService tokenService; - private final CodeSender codeSender; + private final VerificationService verificationService; public UserServiceImpl(Config config, UserRepository userRepository, TokenService tokenService, - CodeSender codeSender) { + VerificationService verificationService) { this.config = config; this.userRepository = userRepository; this.tokenService = tokenService; - this.codeSender = codeSender; + this.verificationService = verificationService; } @Override @@ -92,7 +90,7 @@ public User register(UserRegisterRequest userRegisterRequest) throws CastleExcep userLoginItem.setCreatedAt(now); userLoginItem.setUpdatedAt(now); this.userRepository.save(user, userLoginItem); - this.codeSender.sendVerificationCode(userLoginItem.getLoginIdentifier(), userLoginItem.getVerificationCode()); + this.verificationService.sendVerificationCode(userLoginItem.getLoginIdentifier(), userLoginItem.getVerificationCode()); return user; } @@ -110,18 +108,7 @@ public void verify(String loginIdentifier, String verificationCode) throws Castl if (!StringUtils.equals(verificationCode, userLoginItem.getVerificationCode())) { throw new CastleException(); } - if (StringUtils.isBlank(verificationCode)) { - throw new CastleException(); - } - if (StringUtils.isBlank(userLoginItem.getVerificationCode()) || userLoginItem.getVerificationCodeExpiredAt() == null) { - throw new CastleException(); - } - if (userLoginItem.getVerificationCodeExpiredAt().isBefore(TimeUtils.now())) { - throw new CastleException(); - } - if (verificationCode.equals(userLoginItem.getVerificationCode())) { - userRepository.confirmLoginItem(loginIdentifier); - } + this.verificationService.verify(loginIdentifier, verificationCode); } @Override @@ -287,53 +274,4 @@ public Pair getByLoginIdentifier(String loginIdentifier) th public Pair getByUserSub(String userSub) throws CastleException { return userRepository.getByUserSub(userSub); } - - @Transactional - @Override - public OneTimePasswordDto requestOneTimePassword(String loginIdentifier) throws CastleException { - Pair pair = getByLoginIdentifier(loginIdentifier); - if (pair.getLeft() == null || pair.getRight() == null) { - throw new UserNotFoundException(); - } - if (UserLoginItem.State.ACTIVE != pair.getRight().getState()) { - throw new CastleException("Current login is not confirmed"); - } - if (UserState.ACTIVE != pair.getLeft().getUserState()) { - throw new CastleException("The user is not confirmed"); - } - OneTimePassword oneTimePassword = new OneTimePassword(); - oneTimePassword.setLoginIdentifier(loginIdentifier); - oneTimePassword.setOneTimePassword(CodeUtil.generateCode(6, CodeUtil.UPPER_CHARS)); - oneTimePassword.setExpiredAt(TimeUtils.now().plusSeconds(config.getOneTimePasswordExpireTime())); - oneTimePassword.setCreatedAt(TimeUtils.now()); - userRepository.saveOneTimePassword(oneTimePassword); - this.codeSender.sendOneTimePassword(loginIdentifier, oneTimePassword.getOneTimePassword()); - OneTimePasswordDto oneTimePasswordDto = new OneTimePasswordDto(); - oneTimePasswordDto.setLoginIdentifier(loginIdentifier); - oneTimePasswordDto.setExpiredAt(oneTimePassword.getExpiredAt()); - oneTimePasswordDto.setCreatedAt(oneTimePassword.getCreatedAt()); - return oneTimePasswordDto; - } - - @Transactional - @Override - public UserWithToken verifyOneTimePassword(String loginIdentifier, String oneTimePassword) throws CastleException { - boolean success = userRepository.verifyOneTimePassword(loginIdentifier, oneTimePassword); - if (!success) { - throw new CastleException(); - } - Pair pair = getByLoginIdentifier(loginIdentifier); - if (pair.getLeft() == null || pair.getRight() == null) { - throw new UserNotFoundException(); - } - if (UserLoginItem.State.ACTIVE != pair.getRight().getState()) { - throw new CastleException("Current login is not confirmed"); - } - if (UserState.ACTIVE != pair.getLeft().getUserState()) { - throw new CastleException("The user is not confirmed"); - } - TokenHolder tokenHolder = tokenService.generateToken(pair.getLeft(), pair.getRight()); - userRepository.addRefreshToken(pair.getLeft(), tokenHolder.getRefreshToken(), tokenHolder.getExpiresAt()); - return new UserWithToken(pair.getLeft(), tokenHolder); - } } diff --git a/src/main/java/org/clevercastle/authforge/code/CodeSender.java b/src/main/java/org/clevercastle/authforge/code/CodeSender.java deleted file mode 100644 index f7df037..0000000 --- a/src/main/java/org/clevercastle/authforge/code/CodeSender.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.clevercastle.authforge.code; - -import org.clevercastle.authforge.exception.CastleException; - -public interface CodeSender { - void sendVerificationCode(String loginIdentifier, String verificationCode) throws CastleException; - - void sendOneTimePassword(String loginIdentifier, String oneTimePasswordService) throws CastleException; -} diff --git a/src/main/java/org/clevercastle/authforge/code/DummyCodeSender.java b/src/main/java/org/clevercastle/authforge/code/DummyCodeSender.java deleted file mode 100644 index b9302bc..0000000 --- a/src/main/java/org/clevercastle/authforge/code/DummyCodeSender.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.clevercastle.authforge.code; - -import org.clevercastle.authforge.exception.CastleException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DummyCodeSender implements CodeSender { - private final Logger logger = LoggerFactory.getLogger(DummyCodeSender.class); - - public DummyCodeSender() { - } - - @Override - public void sendVerificationCode(String loginIdentifier, String verificationCode) throws CastleException { - logger.info("verification code is: {}", verificationCode); - - } - - @Override - public void sendOneTimePassword(String loginIdentifier, String verificationCode) throws CastleException { - logger.info("one time password is: {}", verificationCode); - } -} diff --git a/src/main/java/org/clevercastle/authforge/dto/OneTimePasswordDto.java b/src/main/java/org/clevercastle/authforge/dto/OneTimePasswordDto.java deleted file mode 100644 index e8f6e0d..0000000 --- a/src/main/java/org/clevercastle/authforge/dto/OneTimePasswordDto.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.clevercastle.authforge.dto; - -import java.time.OffsetDateTime; - -public class OneTimePasswordDto { - private String loginIdentifier; - private OffsetDateTime expiredAt; - private OffsetDateTime createdAt; - - public String getLoginIdentifier() { - return loginIdentifier; - } - - public void setLoginIdentifier(String loginIdentifier) { - this.loginIdentifier = loginIdentifier; - } - - public OffsetDateTime getExpiredAt() { - return expiredAt; - } - - public void setExpiredAt(OffsetDateTime expiredAt) { - this.expiredAt = expiredAt; - } - - public OffsetDateTime getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(OffsetDateTime createdAt) { - this.createdAt = createdAt; - } -} diff --git a/src/main/java/org/clevercastle/authforge/model/OneTimePassword.java b/src/main/java/org/clevercastle/authforge/model/OneTimePassword.java deleted file mode 100644 index ef96e24..0000000 --- a/src/main/java/org/clevercastle/authforge/model/OneTimePassword.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.clevercastle.authforge.model; - -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.IdClass; -import jakarta.persistence.Table; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaOneTimePasswordId; -import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserRefreshTokenMappingId; - -import java.time.OffsetDateTime; - -@javax.persistence.Entity -@javax.persistence.Table(name = "one_time_password") -@Entity -@Table(name = "one_time_password") -@javax.persistence.IdClass(RdsJpaOneTimePasswordId.class) -@IdClass(RdsJpaUserRefreshTokenMappingId.class) -public class OneTimePassword { - @javax.persistence.Id - @Id - private String loginIdentifier; - @javax.persistence.Id - @Id - private String oneTimePassword; - - private OffsetDateTime expiredAt; - private OffsetDateTime createdAt; - - public String getLoginIdentifier() { - return loginIdentifier; - } - - public void setLoginIdentifier(String loginIdentifier) { - this.loginIdentifier = loginIdentifier; - } - - public String getOneTimePassword() { - return oneTimePassword; - } - - public void setOneTimePassword(String oneTimePassword) { - this.oneTimePassword = oneTimePassword; - } - - public OffsetDateTime getExpiredAt() { - return expiredAt; - } - - public void setExpiredAt(OffsetDateTime expiredAt) { - this.expiredAt = expiredAt; - } - - public OffsetDateTime getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(OffsetDateTime createdAt) { - this.createdAt = createdAt; - } -} diff --git a/src/main/java/org/clevercastle/authforge/repository/UserRepository.java b/src/main/java/org/clevercastle/authforge/repository/UserRepository.java index f38cbc5..27c680b 100644 --- a/src/main/java/org/clevercastle/authforge/repository/UserRepository.java +++ b/src/main/java/org/clevercastle/authforge/repository/UserRepository.java @@ -4,7 +4,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.clevercastle.authforge.model.User; import org.clevercastle.authforge.model.UserLoginItem; -import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.model.UserRefreshTokenMapping; import org.clevercastle.authforge.exception.CastleException; @@ -24,8 +23,4 @@ public interface UserRepository { UserRefreshTokenMapping addRefreshToken(User user, String refreshToken, OffsetDateTime expiredAt) throws CastleException; boolean verifyRefreshToken(User user, String refreshToken) throws CastleException; - - void saveOneTimePassword(OneTimePassword userOneTimePasswordMapping) throws CastleException; - - boolean verifyOneTimePassword(String loginIdentifier, String oneTimePassword) throws CastleException; } \ No newline at end of file diff --git a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java index 32f2b1b..8c6a551 100644 --- a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java +++ b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java @@ -1,14 +1,12 @@ package org.clevercastle.authforge.repository.dynamodb; import jakarta.annotation.Nonnull; -import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.model.User; import org.clevercastle.authforge.model.UserLoginItem; import org.clevercastle.authforge.model.UserRefreshTokenMapping; +import org.clevercastle.authforge.exception.CastleException; import org.clevercastle.authforge.repository.UserRepository; import org.clevercastle.authforge.util.TimeUtils; import org.slf4j.Logger; @@ -165,14 +163,4 @@ private DynamoDbTable getTable() { } return table; } - - @Override - public void saveOneTimePassword(OneTimePassword userOneTimePasswordMapping) throws CastleException { - throw new NotImplementedException(); - } - - @Override - public boolean verifyOneTimePassword(String loginIdentifier, String oneTimePassword) throws CastleException { - throw new NotImplementedException(); - } } diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaOneTimePasswordId.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaOneTimePasswordId.java deleted file mode 100644 index dc15b1d..0000000 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaOneTimePasswordId.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.clevercastle.authforge.repository.rdsjpa; - -import java.io.Serializable; - -public class RdsJpaOneTimePasswordId implements Serializable { - private String loginIdentifier; - private String oneTimePassword; - - public RdsJpaOneTimePasswordId() { - } - - public RdsJpaOneTimePasswordId(String loginIdentifier, String oneTimePassword) { - this.loginIdentifier = loginIdentifier; - this.oneTimePassword = oneTimePassword; - } - - public String getLoginIdentifier() { - return loginIdentifier; - } - - public void setLoginIdentifier(String loginIdentifier) { - this.loginIdentifier = loginIdentifier; - } - - public String getOneTimePassword() { - return oneTimePassword; - } - - public void setOneTimePassword(String oneTimePassword) { - this.oneTimePassword = oneTimePassword; - } -} diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaOneTimePasswordRepository.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaOneTimePasswordRepository.java deleted file mode 100644 index 8d7cf30..0000000 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaOneTimePasswordRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.clevercastle.authforge.repository.rdsjpa; - -import org.clevercastle.authforge.model.OneTimePassword; - -import java.util.List; - -public interface RdsJpaOneTimePasswordRepository { - OneTimePassword save(OneTimePassword oneTimePassword); - - void deleteByLoginIdentifier(String loginIdentifier); - - List getByLoginIdentifier(String loginIdentifier); -} diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java index 45b3d4d..9ae1d22 100644 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java +++ b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java @@ -6,28 +6,23 @@ import org.clevercastle.authforge.exception.CastleException; import org.clevercastle.authforge.model.User; import org.clevercastle.authforge.model.UserLoginItem; -import org.clevercastle.authforge.model.OneTimePassword; import org.clevercastle.authforge.model.UserRefreshTokenMapping; import org.clevercastle.authforge.repository.UserRepository; import org.clevercastle.authforge.util.TimeUtils; import java.time.OffsetDateTime; -import java.util.List; public class RdsJpaUserRepositoryImpl implements UserRepository { private final RdsJpaUserModelRepository userModelRepository; private final RdsJpaUserLoginItemRepository userLoginItemRepository; private final RdsJpaUserRefreshTokenMappingRepository userRefreshTokenMappingRepository; - private final RdsJpaOneTimePasswordRepository oneTimePasswordRepository; public RdsJpaUserRepositoryImpl(RdsJpaUserModelRepository userModelRepository, RdsJpaUserLoginItemRepository userLoginItemRepository, - RdsJpaUserRefreshTokenMappingRepository userRefreshTokenMappingRepository, - RdsJpaOneTimePasswordRepository oneTimePasswordRepository) { + RdsJpaUserRefreshTokenMappingRepository userRefreshTokenMappingRepository) { this.userModelRepository = userModelRepository; this.userLoginItemRepository = userLoginItemRepository; this.userRefreshTokenMappingRepository = userRefreshTokenMappingRepository; - this.oneTimePasswordRepository = oneTimePasswordRepository; } @Override @@ -88,23 +83,4 @@ public Pair getByUserSub(String userSub) { } return Pair.of(null, null); } - - @Override - public void saveOneTimePassword(OneTimePassword oneTimePassword) throws CastleException { - oneTimePasswordRepository.deleteByLoginIdentifier(oneTimePassword.getLoginIdentifier()); - oneTimePasswordRepository.save(oneTimePassword); - } - - @Override - public boolean verifyOneTimePassword(String loginIdentifier, String oneTimePassword) throws CastleException { - // the result's size should be one - List oneTimePasswords = oneTimePasswordRepository.getByLoginIdentifier(loginIdentifier); - for (OneTimePassword otp : oneTimePasswords) { - if (StringUtils.equals(otp.getOneTimePassword(), oneTimePassword)) { - oneTimePasswordRepository.deleteByLoginIdentifier(loginIdentifier); - return true; - } - } - return false; - } } diff --git a/src/main/java/org/clevercastle/authforge/util/CodeUtil.java b/src/main/java/org/clevercastle/authforge/util/CodeUtil.java index 3c51ddc..3720c1d 100644 --- a/src/main/java/org/clevercastle/authforge/util/CodeUtil.java +++ b/src/main/java/org/clevercastle/authforge/util/CodeUtil.java @@ -3,23 +3,30 @@ import java.util.Random; public class CodeUtil { - public static final String UPPER_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - public static final String FULL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; + private static final String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + private static final String REFERRAL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; private static final Random RANDOM = new Random(); - private CodeUtil() { - } + private CodeUtil(){} - public static String generateCode(int length, String chars) { + public static String generateCode(int length) { StringBuilder code = new StringBuilder(); for (int i = 0; i < length; i++) { - int index = RANDOM.nextInt(chars.length()); - code.append(chars.charAt(index)); + int index = RANDOM.nextInt(CHARS.length()); + code.append(CHARS.charAt(index)); } return code.toString(); } - public static String generateCode(int length) { - return generateCode(length, FULL_CHARS); + + public static String generateReferralCode(int length) { + StringBuilder code = new StringBuilder(); + for (int i = 0; i < length; i++) { + int index = RANDOM.nextInt(REFERRAL_CHARS.length()); + code.append(REFERRAL_CHARS.charAt(index)); + } + return code.toString(); } -} \ No newline at end of file + + +} diff --git a/src/main/java/org/clevercastle/authforge/verification/AbstractVerificationService.java b/src/main/java/org/clevercastle/authforge/verification/AbstractVerificationService.java new file mode 100644 index 0000000..5328990 --- /dev/null +++ b/src/main/java/org/clevercastle/authforge/verification/AbstractVerificationService.java @@ -0,0 +1,41 @@ +package org.clevercastle.authforge.verification; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.clevercastle.authforge.exception.CastleException; +import org.clevercastle.authforge.model.User; +import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.repository.UserRepository; +import org.clevercastle.authforge.util.TimeUtils; + +public abstract class AbstractVerificationService implements VerificationService { + private final UserRepository userRepository; + + protected AbstractVerificationService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + public void verify(String loginIdentifier, String verificationCode) throws CastleException { + if (StringUtils.isBlank(verificationCode)) { + throw new CastleException(); + } + Pair pair = userRepository.getByLoginIdentifier(loginIdentifier); + UserLoginItem userLoginItem = pair.getRight(); + if (userLoginItem == null) { + throw new CastleException(); + } + if (StringUtils.isBlank(verificationCode)) { + throw new CastleException(); + } + if (StringUtils.isBlank(userLoginItem.getVerificationCode()) || userLoginItem.getVerificationCodeExpiredAt() == null) { + throw new CastleException(); + } + if (userLoginItem.getVerificationCodeExpiredAt().isBefore(TimeUtils.now())) { + throw new CastleException(); + } + if (verificationCode.equals(userLoginItem.getVerificationCode())) { + userRepository.confirmLoginItem(loginIdentifier); + } + } +} diff --git a/src/main/java/org/clevercastle/authforge/verification/DummyVerificationService.java b/src/main/java/org/clevercastle/authforge/verification/DummyVerificationService.java new file mode 100644 index 0000000..2f12575 --- /dev/null +++ b/src/main/java/org/clevercastle/authforge/verification/DummyVerificationService.java @@ -0,0 +1,20 @@ +package org.clevercastle.authforge.verification; + +import org.clevercastle.authforge.exception.CastleException; +import org.clevercastle.authforge.repository.UserRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DummyVerificationService extends AbstractVerificationService { + private final Logger logger = LoggerFactory.getLogger(DummyVerificationService.class); + + public DummyVerificationService(UserRepository userRepository) { + super(userRepository); + } + + @Override + public void sendVerificationCode(String loginIdentifier, String verificationCode) throws CastleException { + logger.info("verification code is: {}", verificationCode); + + } +} diff --git a/src/main/java/org/clevercastle/authforge/code/SendCodeResponse.java b/src/main/java/org/clevercastle/authforge/verification/SendVerificationCodeResponse.java similarity index 52% rename from src/main/java/org/clevercastle/authforge/code/SendCodeResponse.java rename to src/main/java/org/clevercastle/authforge/verification/SendVerificationCodeResponse.java index dd99109..e070c68 100644 --- a/src/main/java/org/clevercastle/authforge/code/SendCodeResponse.java +++ b/src/main/java/org/clevercastle/authforge/verification/SendVerificationCodeResponse.java @@ -1,6 +1,6 @@ -package org.clevercastle.authforge.code; +package org.clevercastle.authforge.verification; -public class SendCodeResponse { +public class SendVerificationCodeResponse { public enum Type { success, error @@ -9,7 +9,7 @@ public enum Type { public Type type; public String message; - public SendCodeResponse(Type type, String message) { + public SendVerificationCodeResponse(Type type, String message) { this.type = type; this.message = message; } diff --git a/src/main/java/org/clevercastle/authforge/verification/VerificationService.java b/src/main/java/org/clevercastle/authforge/verification/VerificationService.java new file mode 100644 index 0000000..01ba06c --- /dev/null +++ b/src/main/java/org/clevercastle/authforge/verification/VerificationService.java @@ -0,0 +1,9 @@ +package org.clevercastle.authforge.verification; + +import org.clevercastle.authforge.exception.CastleException; + +public interface VerificationService { + void sendVerificationCode(String loginIdentifier, String verificationCode) throws CastleException; + + void verify(String loginIdentifier, String verificationCode) throws CastleException; +} From 8fb534863996d5996270fe4ba51f004a8e47ec02 Mon Sep 17 00:00:00 2001 From: ivyxjc Date: Thu, 5 Jun 2025 16:24:18 +0800 Subject: [PATCH 5/7] Revert "refactor(example): refactor package structure" This reverts commit 08504c9e943f2463cea9835ca64ba6d1f33a3f75. --- .../springboot/springbootexample/AuthController.java | 5 ++--- .../springbootexample/SpringBootExampleApplication.java | 2 +- .../springbootexample/UserLoginItemRepositoryAdapter.java | 2 +- .../springbootexample/UserModelRepositoryAdapter.java | 2 +- .../UserRefreshTokenMappingRepositoryAdapter.java | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java index 3c51a83..ffa9351 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java @@ -5,8 +5,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; import org.clevercastle.authforge.UserRegisterRequest; import org.clevercastle.authforge.UserService; import org.clevercastle.authforge.UserWithToken; @@ -84,7 +84,6 @@ public User register(@RequestBody RegisterRequest request) throws CastleExceptio return userService.register(userRegisterRequest); } - @GetMapping("auth/verify") public UserWithToken verify(@RequestParam String loginIdentifier, @RequestParam String verificationCode) throws CastleException { userService.verify("email#" + loginIdentifier, verificationCode); diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/SpringBootExampleApplication.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/SpringBootExampleApplication.java index dd4c668..d2ada9d 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/SpringBootExampleApplication.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/SpringBootExampleApplication.java @@ -1,6 +1,6 @@ package org.clevercastle.authforge.examples.springboot.springbootexample; -import org.clevercastle.authforge.model.User; +import org.clevercastle.authforge.entity.User; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserLoginItemRepositoryAdapter.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserLoginItemRepositoryAdapter.java index c0a3b17..10176e1 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserLoginItemRepositoryAdapter.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserLoginItemRepositoryAdapter.java @@ -1,6 +1,6 @@ package org.clevercastle.authforge.examples.springboot.springbootexample; -import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.entity.UserLoginItem; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserLoginItemRepository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserModelRepositoryAdapter.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserModelRepositoryAdapter.java index 6ee6bdf..f038048 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserModelRepositoryAdapter.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserModelRepositoryAdapter.java @@ -1,6 +1,6 @@ package org.clevercastle.authforge.examples.springboot.springbootexample; -import org.clevercastle.authforge.model.User; +import org.clevercastle.authforge.entity.User; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserModelRepository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserRefreshTokenMappingRepositoryAdapter.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserRefreshTokenMappingRepositoryAdapter.java index 259bba7..2692ed9 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserRefreshTokenMappingRepositoryAdapter.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/UserRefreshTokenMappingRepositoryAdapter.java @@ -1,6 +1,6 @@ package org.clevercastle.authforge.examples.springboot.springbootexample; -import org.clevercastle.authforge.model.UserRefreshTokenMapping; +import org.clevercastle.authforge.entity.UserRefreshTokenMapping; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserRefreshTokenMappingRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserRefreshTokenMappingId; import org.springframework.data.jpa.repository.JpaRepository; From 2afaacfa3f79eead462601d5c8fdede08f2d5d4e Mon Sep 17 00:00:00 2001 From: ivyxjc Date: Thu, 5 Jun 2025 16:24:18 +0800 Subject: [PATCH 6/7] Revert "refactor(): refactor package structure" This reverts commit a410407e866a2f6756dea7c9378f3af7bc693ba9. --- .../java/org/clevercastle/authforge/UserService.java | 4 ++-- .../org/clevercastle/authforge/UserServiceImpl.java | 4 ++-- .../org/clevercastle/authforge/UserWithToken.java | 2 +- .../authforge/{model => entity}/User.java | 2 +- .../authforge/{model => entity}/UserLoginItem.java | 2 +- .../{model => entity}/UserRefreshTokenMapping.java | 2 +- .../authforge/repository/UserRepository.java | 6 +++--- .../authforge/repository/dynamodb/DynamodbUser.java | 12 +----------- .../dynamodb/DynamodbUserRepositoryImpl.java | 6 +++--- .../repository/dynamodb/DynamodbUserUtil.java | 6 +++--- .../rdsjpa/RdsJpaUserLoginItemRepository.java | 2 +- .../repository/rdsjpa/RdsJpaUserModelRepository.java | 2 +- .../RdsJpaUserRefreshTokenMappingRepository.java | 2 +- .../repository/rdsjpa/RdsJpaUserRepositoryImpl.java | 6 +++--- .../clevercastle/authforge/token/TokenService.java | 4 ++-- .../authforge/token/jwt/JwtTokenService.java | 4 ++-- .../verification/AbstractVerificationService.java | 4 ++-- 17 files changed, 30 insertions(+), 40 deletions(-) rename src/main/java/org/clevercastle/authforge/{model => entity}/User.java (98%) rename src/main/java/org/clevercastle/authforge/{model => entity}/UserLoginItem.java (98%) rename src/main/java/org/clevercastle/authforge/{model => entity}/UserRefreshTokenMapping.java (97%) diff --git a/src/main/java/org/clevercastle/authforge/UserService.java b/src/main/java/org/clevercastle/authforge/UserService.java index b6276ad..c522827 100644 --- a/src/main/java/org/clevercastle/authforge/UserService.java +++ b/src/main/java/org/clevercastle/authforge/UserService.java @@ -1,8 +1,8 @@ package org.clevercastle.authforge; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; import org.clevercastle.authforge.exception.CastleException; import org.clevercastle.authforge.oauth2.Oauth2ClientConfig; diff --git a/src/main/java/org/clevercastle/authforge/UserServiceImpl.java b/src/main/java/org/clevercastle/authforge/UserServiceImpl.java index b9a79d6..7a03431 100644 --- a/src/main/java/org/clevercastle/authforge/UserServiceImpl.java +++ b/src/main/java/org/clevercastle/authforge/UserServiceImpl.java @@ -17,8 +17,8 @@ import org.clevercastle.authforge.exception.CastleException; import org.clevercastle.authforge.exception.UserExistException; import org.clevercastle.authforge.exception.UserNotFoundException; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; import org.clevercastle.authforge.oauth2.Oauth2ClientConfig; import org.clevercastle.authforge.oauth2.Oauth2User; import org.clevercastle.authforge.repository.UserRepository; diff --git a/src/main/java/org/clevercastle/authforge/UserWithToken.java b/src/main/java/org/clevercastle/authforge/UserWithToken.java index 73f9e2a..71a4c7e 100644 --- a/src/main/java/org/clevercastle/authforge/UserWithToken.java +++ b/src/main/java/org/clevercastle/authforge/UserWithToken.java @@ -1,6 +1,6 @@ package org.clevercastle.authforge; -import org.clevercastle.authforge.model.User; +import org.clevercastle.authforge.entity.User; public class UserWithToken { private final User user; diff --git a/src/main/java/org/clevercastle/authforge/model/User.java b/src/main/java/org/clevercastle/authforge/entity/User.java similarity index 98% rename from src/main/java/org/clevercastle/authforge/model/User.java rename to src/main/java/org/clevercastle/authforge/entity/User.java index c7bdb00..503a5b7 100644 --- a/src/main/java/org/clevercastle/authforge/model/User.java +++ b/src/main/java/org/clevercastle/authforge/entity/User.java @@ -1,4 +1,4 @@ -package org.clevercastle.authforge.model; +package org.clevercastle.authforge.entity; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; diff --git a/src/main/java/org/clevercastle/authforge/model/UserLoginItem.java b/src/main/java/org/clevercastle/authforge/entity/UserLoginItem.java similarity index 98% rename from src/main/java/org/clevercastle/authforge/model/UserLoginItem.java rename to src/main/java/org/clevercastle/authforge/entity/UserLoginItem.java index 8b5754c..27bfe1b 100644 --- a/src/main/java/org/clevercastle/authforge/model/UserLoginItem.java +++ b/src/main/java/org/clevercastle/authforge/entity/UserLoginItem.java @@ -1,4 +1,4 @@ -package org.clevercastle.authforge.model; +package org.clevercastle.authforge.entity; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; diff --git a/src/main/java/org/clevercastle/authforge/model/UserRefreshTokenMapping.java b/src/main/java/org/clevercastle/authforge/entity/UserRefreshTokenMapping.java similarity index 97% rename from src/main/java/org/clevercastle/authforge/model/UserRefreshTokenMapping.java rename to src/main/java/org/clevercastle/authforge/entity/UserRefreshTokenMapping.java index 91e3ee7..68be72e 100644 --- a/src/main/java/org/clevercastle/authforge/model/UserRefreshTokenMapping.java +++ b/src/main/java/org/clevercastle/authforge/entity/UserRefreshTokenMapping.java @@ -1,4 +1,4 @@ -package org.clevercastle.authforge.model; +package org.clevercastle.authforge.entity; import jakarta.persistence.Entity; import jakarta.persistence.Id; diff --git a/src/main/java/org/clevercastle/authforge/repository/UserRepository.java b/src/main/java/org/clevercastle/authforge/repository/UserRepository.java index 27c680b..166e3a6 100644 --- a/src/main/java/org/clevercastle/authforge/repository/UserRepository.java +++ b/src/main/java/org/clevercastle/authforge/repository/UserRepository.java @@ -2,9 +2,9 @@ import jakarta.annotation.Nonnull; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserLoginItem; -import org.clevercastle.authforge.model.UserRefreshTokenMapping; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; +import org.clevercastle.authforge.entity.UserRefreshTokenMapping; import org.clevercastle.authforge.exception.CastleException; import java.time.OffsetDateTime; diff --git a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUser.java b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUser.java index d51b11c..57fcb60 100644 --- a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUser.java +++ b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUser.java @@ -1,7 +1,7 @@ package org.clevercastle.authforge.repository.dynamodb; import org.clevercastle.authforge.UserState; -import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.entity.UserLoginItem; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey; @@ -29,8 +29,6 @@ public enum Type { private String pk; private String sk; - private Type type; - // region from user table private UserState userState; private String userHashedPassword; @@ -71,14 +69,6 @@ public void setSk(String sk) { this.sk = sk; } - public Type getType() { - return type; - } - - public void setType(Type type) { - this.type = type; - } - public UserState getUserState() { return userState; } diff --git a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java index 8c6a551..192ee42 100644 --- a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java +++ b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java @@ -3,9 +3,9 @@ import jakarta.annotation.Nonnull; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserLoginItem; -import org.clevercastle.authforge.model.UserRefreshTokenMapping; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; +import org.clevercastle.authforge.entity.UserRefreshTokenMapping; import org.clevercastle.authforge.exception.CastleException; import org.clevercastle.authforge.repository.UserRepository; import org.clevercastle.authforge.util.TimeUtils; diff --git a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserUtil.java b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserUtil.java index 8349aa0..37c6e8f 100644 --- a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserUtil.java +++ b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserUtil.java @@ -1,8 +1,8 @@ package org.clevercastle.authforge.repository.dynamodb; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserLoginItem; -import org.clevercastle.authforge.model.UserRefreshTokenMapping; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; +import org.clevercastle.authforge.entity.UserRefreshTokenMapping; public class DynamodbUserUtil { diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserLoginItemRepository.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserLoginItemRepository.java index 4401354..e636d2f 100644 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserLoginItemRepository.java +++ b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserLoginItemRepository.java @@ -1,6 +1,6 @@ package org.clevercastle.authforge.repository.rdsjpa; -import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.entity.UserLoginItem; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserModelRepository.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserModelRepository.java index 1b5c8cb..55b65a3 100644 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserModelRepository.java +++ b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserModelRepository.java @@ -1,6 +1,6 @@ package org.clevercastle.authforge.repository.rdsjpa; -import org.clevercastle.authforge.model.User; +import org.clevercastle.authforge.entity.User; public interface RdsJpaUserModelRepository { User save(User user); diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRefreshTokenMappingRepository.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRefreshTokenMappingRepository.java index 661e8dd..5ba0413 100644 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRefreshTokenMappingRepository.java +++ b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRefreshTokenMappingRepository.java @@ -1,6 +1,6 @@ package org.clevercastle.authforge.repository.rdsjpa; -import org.clevercastle.authforge.model.UserRefreshTokenMapping; +import org.clevercastle.authforge.entity.UserRefreshTokenMapping; public interface RdsJpaUserRefreshTokenMappingRepository { UserRefreshTokenMapping getByUserIdAndRefreshToken(String userIed, String refreshToken); diff --git a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java index 9ae1d22..19f21ab 100644 --- a/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java +++ b/src/main/java/org/clevercastle/authforge/repository/rdsjpa/RdsJpaUserRepositoryImpl.java @@ -4,9 +4,9 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserLoginItem; -import org.clevercastle.authforge.model.UserRefreshTokenMapping; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; +import org.clevercastle.authforge.entity.UserRefreshTokenMapping; import org.clevercastle.authforge.repository.UserRepository; import org.clevercastle.authforge.util.TimeUtils; diff --git a/src/main/java/org/clevercastle/authforge/token/TokenService.java b/src/main/java/org/clevercastle/authforge/token/TokenService.java index 496e2a7..8bce300 100644 --- a/src/main/java/org/clevercastle/authforge/token/TokenService.java +++ b/src/main/java/org/clevercastle/authforge/token/TokenService.java @@ -2,8 +2,8 @@ import org.clevercastle.authforge.exception.CastleException; import org.clevercastle.authforge.TokenHolder; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; public interface TokenService { enum Scope { diff --git a/src/main/java/org/clevercastle/authforge/token/jwt/JwtTokenService.java b/src/main/java/org/clevercastle/authforge/token/jwt/JwtTokenService.java index 40e9fc2..e0b8d92 100644 --- a/src/main/java/org/clevercastle/authforge/token/jwt/JwtTokenService.java +++ b/src/main/java/org/clevercastle/authforge/token/jwt/JwtTokenService.java @@ -4,8 +4,8 @@ import org.clevercastle.authforge.exception.CastleException; import org.clevercastle.authforge.Config; import org.clevercastle.authforge.TokenHolder; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; import org.clevercastle.authforge.token.TokenService; import org.clevercastle.authforge.util.JsonUtil; import org.clevercastle.authforge.util.TimeUtils; diff --git a/src/main/java/org/clevercastle/authforge/verification/AbstractVerificationService.java b/src/main/java/org/clevercastle/authforge/verification/AbstractVerificationService.java index 5328990..38d21da 100644 --- a/src/main/java/org/clevercastle/authforge/verification/AbstractVerificationService.java +++ b/src/main/java/org/clevercastle/authforge/verification/AbstractVerificationService.java @@ -3,8 +3,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.clevercastle.authforge.exception.CastleException; -import org.clevercastle.authforge.model.User; -import org.clevercastle.authforge.model.UserLoginItem; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; import org.clevercastle.authforge.repository.UserRepository; import org.clevercastle.authforge.util.TimeUtils; From 186a71b061fd81b658277f00953ceeda50c05f9c Mon Sep 17 00:00:00 2001 From: ivyxjc Date: Thu, 5 Jun 2025 16:24:18 +0800 Subject: [PATCH 7/7] Revert "fix(): oauth2 user still use customize user sub" This reverts commit c6de8bd00ee8017085e0114cd69a99d33757f987. --- src/main/java/org/clevercastle/authforge/UserServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/clevercastle/authforge/UserServiceImpl.java b/src/main/java/org/clevercastle/authforge/UserServiceImpl.java index 7a03431..22fc8ba 100644 --- a/src/main/java/org/clevercastle/authforge/UserServiceImpl.java +++ b/src/main/java/org/clevercastle/authforge/UserServiceImpl.java @@ -152,7 +152,7 @@ public UserWithToken exchange(Oauth2ClientConfig clientConfig, String authorizat userLoginItem = new UserLoginItem(); userLoginItem.setUserId(userId); userLoginItem.setLoginIdentifier(oauth2User.getLoginIdentifier()); - userLoginItem.setUserSub(UUID.randomUUID().toString()); + userLoginItem.setUserSub(oauth2User.getUserSub()); userLoginItem.setCreatedAt(now); userLoginItem.setUpdatedAt(now); this.userRepository.save(user, userLoginItem);