Skip to content

[Feat/apple user withdraw]#52

Merged
ekgns33 merged 6 commits intomainfrom
feat/apple-user-withdraw
Apr 14, 2025
Merged

[Feat/apple user withdraw]#52
ekgns33 merged 6 commits intomainfrom
feat/apple-user-withdraw

Conversation

@ekgns33
Copy link
Copy Markdown
Contributor

@ekgns33 ekgns33 commented Apr 13, 2025

작업내역

  • 애플의 경우 회원 탈퇴 시, 인증에 발급되었던 refresh_token을 사용하여 revoke 해야합니다.

ref)

1. generate-validate-token은 #27에서 애플로그인을 구현하면서 적용했습니다.

  • 기존에는 인증에 필요한 id_token 만을 이용했지만, refresh_token 저장 필요에 따라 TokenPair 을 만들어 서비스로 반환하도록
    src/main/java/org/runimo/runimo/auth/service/apple/AppleTokenVerifier.javagetAccessTokenFromAuthCode 를 변경했습니다.

2. revoke를 위해서는 refresh_token 이 필요합니다.

  • 이는 Runimo에서 배포한 것이 아닌, 애플에서 유저마다 영구적인 값으로 발급됩니다. 민감한 정보이기에 암호화를 하여 데이터베이스에 저장하는 로직을 작성했습니다.

  • 또한 해당 정보는 revoke 이후에는 폐기되야 하므로 HARD-DELETE합니다.

Summary by CodeRabbit

  • New Features

    • Enhanced Apple authentication with improved access and refresh token handling, including support for secure token revocation.
    • Introduced encryption utilities that strengthen the protection of sensitive data, improving overall login and withdrawal processes.
    • Added a new database table for storing Apple user tokens.
  • Chores

    • Updated security configurations to securely manage encryption parameters.
    • Added database schema changes to support new token storage for Apple users.

@ekgns33 ekgns33 self-assigned this Apr 13, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 13, 2025

Walkthrough

This update introduces a new encryption utility along with several modifications to improve Apple authentication and user withdrawal handling. A new EncryptUtil class provides AES encryption and decryption methods using properties from the configuration. The Apple authentication flow is enhanced within AppleLoginHandler and AppleTokenVerifier by integrating token pairs, encrypted refresh tokens, and revocation of tokens. Additionally, a new entity and repository for storing Apple user tokens have been added, and both application and test configurations now include security parameters. The SQL schema is updated to support persistent storage of Apple tokens.

Changes

File(s) Change Summary
src/main/java/org/runimo/runimo/auth/service/EncryptUtil.java New class added with encrypt and decrypt methods using AES/CBC mode and PKCS5 padding; injects secret key and IV from configuration.
src/main/java/org/runimo/runimo/auth/service/apple/AppleLoginHandler.java
src/main/java/org/runimo/runimo/auth/service/apple/AppleTokenVerifier.java
src/main/java/org/runimo/runimo/user/service/WithdrawService.java
Apple authentication flow enhancements: updated token handling with TokenPair, new methods for retrieving user info, saving/revoking encrypted refresh tokens, and modifications to support write operations in transactional contexts.
src/main/java/org/runimo/runimo/user/domain/AppleUserToken.java
src/main/java/org/runimo/runimo/user/repository/AppleUserTokenRepository.java
New entity AppleUserToken and repository interface added for persisting and retrieving Apple refresh tokens.
src/main/resources/application.yml
src/test/resources/application.yml
New configuration section added under runimo.security to include secret-key and iv properties using environment variables.
src/main/resources/sql/schema.sql
src/test/resources/sql/schema.sql
New SQL table apple_user_token introduced with appropriate columns and constraints; includes a DROP statement to replace any existing table.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AppleLoginHandler
    participant AppleTokenVerifier
    participant EncryptUtil
    participant AppleUserTokenRepository

    Client->>AppleLoginHandler: Login request with Apple token
    AppleLoginHandler->>AppleTokenVerifier: getAccessTokenFromAuthCode(authCode, codeVerifier)
    AppleTokenVerifier-->>AppleLoginHandler: Return TokenPair (access, refresh)
    AppleLoginHandler->>EncryptUtil: encrypt(refreshToken)
    EncryptUtil-->>AppleLoginHandler: Return encryptedRefreshToken
    AppleLoginHandler->>AppleUserTokenRepository: Save encrypted refresh token
    AppleLoginHandler-->>Client: Return successful login response
Loading
sequenceDiagram
    participant User
    participant WithdrawService
    participant AppleUserTokenRepository
    participant EncryptUtil
    participant AppleTokenVerifier
 
    User->>WithdrawService: Initiate withdrawal
    WithdrawService->>AppleUserTokenRepository: Fetch AppleUserToken for user
    AppleUserTokenRepository-->>WithdrawService: Return encrypted token
    WithdrawService->>EncryptUtil: getDecryptedToken(encrypted token)
    EncryptUtil-->>WithdrawService: Return decrypted token
    WithdrawService->>AppleTokenVerifier: revoke(decrypted token)
    AppleTokenVerifier-->>WithdrawService: Acknowledge revocation
    WithdrawService->>AppleUserTokenRepository: Delete AppleUserToken record
    WithdrawService-->>User: Confirm withdrawal completion
Loading

Poem

I’m a little rabbit, hopping with glee,
Encrypting secrets like a mystery tree 🍃.
Apple tokens now dance in secure delight,
Revoked and stored, all perfectly right.
With every code change, my heart skips a beat,
In a meadow of updates, oh so sweet!
Hop on, my friends, in our secure rabbit retreat.

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ekgns33 ekgns33 added the enhancement New feature or request label Apr 13, 2025
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (5)
src/main/java/org/runimo/runimo/user/repository/AppleUserTokenRepository.java (1)

7-10: Consider adding explicit deleteByUserId method for withdrawal flow

The repository implementation looks good and follows Spring Data JPA conventions. Since this PR focuses on user withdrawal functionality, consider adding an explicit deleteByUserId(Long userId) method to make the withdrawal flow more readable and intentional in the service layer.

void deleteByUserId(Long userId);

This would better document the withdrawal use case in the repository interface itself.

src/main/java/org/runimo/runimo/user/domain/AppleUserToken.java (1)

14-15: Include NotNull constraints for required fields

Consider adding validation constraints to ensure data integrity:

@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class AppleUserToken extends BaseEntity {

    @NotNull
    @Column(name = "user_id", unique = true)
    private Long userId;
    
    @NotNull
    @Column(name = "refresh_token")
    private String refreshToken;
    
    // Constructor remains the same
}

This ensures that both fields are always populated, preventing null values in the database.

src/main/java/org/runimo/runimo/auth/service/EncryptUtil.java (1)

1-44: Add more specific exception handling for encryption operations.

The current implementation throws a generic Exception, which doesn't provide enough information for troubleshooting specific encryption/decryption failures.

Consider wrapping specific exceptions with a custom EncryptionException:

public class EncryptionException extends RuntimeException {
    public EncryptionException(String message, Throwable cause) {
        super(message, cause);
    }
}

Then update the methods to catch and wrap specific exceptions:

-public String encrypt(String plainText) throws Exception {
+public String encrypt(String plainText) {
+    try {
         // Encryption code
+    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+        throw new EncryptionException("Encryption algorithm not available", e);
+    } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
+        throw new EncryptionException("Invalid encryption key or parameters", e);
+    } catch (IllegalBlockSizeException | BadPaddingException e) {
+        throw new EncryptionException("Encryption failed", e);
+    }
}
🧰 Tools
🪛 ast-grep (0.31.1)

[warning] 22-22: Triple DES (3DES or DESede) is considered deprecated. AES is the recommended cipher. Upgrade to use AES.
Context: Cipher.getInstance(CIPHER_TRANS)
Note: [CWE-326]: Inadequate Encryption Strength [OWASP A03:2017]: Sensitive Data Exposure [OWASP A02:2021]: Cryptographic Failures [REFERENCES]
- https://find-sec-bugs.github.io/bugs.htm#TDES_USAGE
- https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA

(desede-is-deprecated-java)


[warning] 33-33: Triple DES (3DES or DESede) is considered deprecated. AES is the recommended cipher. Upgrade to use AES.
Context: Cipher.getInstance(CIPHER_TRANS)
Note: [CWE-326]: Inadequate Encryption Strength [OWASP A03:2017]: Sensitive Data Exposure [OWASP A02:2021]: Cryptographic Failures [REFERENCES]
- https://find-sec-bugs.github.io/bugs.htm#TDES_USAGE
- https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA

(desede-is-deprecated-java)


[warning] 22-22: Use of AES with ECB mode detected. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.
Context: Cipher.getInstance(CIPHER_TRANS)
Note: [CWE-327]: Use of a Broken or Risky Cryptographic Algorithm [OWASP A03:2017]: Sensitive Data Exposure [OWASP A02:2021]: Cryptographic Failures [REFERENCES]
- https://owasp.org/Top10/A02_2021-Cryptographic_Failures
- https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html

(use-of-aes-ecb-java)


[warning] 33-33: Use of AES with ECB mode detected. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.
Context: Cipher.getInstance(CIPHER_TRANS)
Note: [CWE-327]: Use of a Broken or Risky Cryptographic Algorithm [OWASP A03:2017]: Sensitive Data Exposure [OWASP A02:2021]: Cryptographic Failures [REFERENCES]
- https://owasp.org/Top10/A02_2021-Cryptographic_Failures
- https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html

(use-of-aes-ecb-java)

src/main/java/org/runimo/runimo/auth/service/apple/AppleTokenVerifier.java (1)

124-147: Consider improving error handling in the revoke method.

The revoke method throws the same generic RuntimeException for different error cases, which limits troubleshooting capabilities.

Consider implementing more specific exception handling to differentiate between different failure scenarios:

public void revoke(final String appleRefreshToken) {
    String clientSecret = generateAppleClientSecret(); // JWT 생성

    MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
    params.add("client_id", clientId);
    params.add("client_secret", clientSecret);
    params.add("token", appleRefreshToken);
    params.add("token_type_hint", "refresh_token");

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

    HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
    try {
        ResponseEntity<String> response = restTemplate.postForEntity(REVOKE_URL, entity,
            String.class);
        if (!response.getStatusCode().is2xxSuccessful()) {
-           throw new RuntimeException("Failed to revoke Apple refresh token");
+           log.error("Failed to revoke Apple refresh token. Status: {}, Body: {}", 
+               response.getStatusCode(), response.getBody());
+           throw new AppleApiException("Failed to revoke Apple refresh token", 
+               response.getStatusCode());
        }
    } catch (RestClientException e) {
-       log.error("Failed to revoke Apple refresh token", e);
-       throw new RuntimeException("Failed to revoke Apple refresh token", e);
+       log.error("Network error while revoking Apple refresh token", e);
+       throw new AppleApiException("Network error while revoking Apple refresh token", e);
+   } catch (Exception e) {
+       log.error("Unexpected error while revoking Apple refresh token", e);
+       throw new AppleApiException("Unexpected error while revoking Apple refresh token", e);
    }
}
src/main/java/org/runimo/runimo/user/service/WithdrawService.java (1)

48-54: Consider narrowing the exception catch block

Catching Exception is broad. For better maintainability, catch a more specific exception type or create a custom exception to handle decryption issues.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 573e3fc and d2f5c9e.

📒 Files selected for processing (10)
  • src/main/java/org/runimo/runimo/auth/service/EncryptUtil.java (1 hunks)
  • src/main/java/org/runimo/runimo/auth/service/apple/AppleLoginHandler.java (3 hunks)
  • src/main/java/org/runimo/runimo/auth/service/apple/AppleTokenVerifier.java (4 hunks)
  • src/main/java/org/runimo/runimo/user/domain/AppleUserToken.java (1 hunks)
  • src/main/java/org/runimo/runimo/user/repository/AppleUserTokenRepository.java (1 hunks)
  • src/main/java/org/runimo/runimo/user/service/WithdrawService.java (2 hunks)
  • src/main/resources/application.yml (1 hunks)
  • src/main/resources/sql/schema.sql (2 hunks)
  • src/test/resources/application.yml (1 hunks)
  • src/test/resources/sql/schema.sql (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/main/java/org/runimo/runimo/user/domain/AppleUserToken.java (1)
src/main/java/org/runimo/runimo/common/GlobalConsts.java (1)
  • NoArgsConstructor (8-21)
src/main/java/org/runimo/runimo/auth/service/EncryptUtil.java (1)
src/main/java/org/runimo/runimo/auth/service/apple/AppleLoginHandler.java (1)
  • Component (23-79)
src/main/java/org/runimo/runimo/auth/service/apple/AppleTokenVerifier.java (1)
src/main/java/org/runimo/runimo/auth/exceptions/UserJwtException.java (1)
  • UserJwtException (6-19)
🪛 ast-grep (0.31.1)
src/main/java/org/runimo/runimo/auth/service/EncryptUtil.java

[warning] 22-22: Triple DES (3DES or DESede) is considered deprecated. AES is the recommended cipher. Upgrade to use AES.
Context: Cipher.getInstance(CIPHER_TRANS)
Note: [CWE-326]: Inadequate Encryption Strength [OWASP A03:2017]: Sensitive Data Exposure [OWASP A02:2021]: Cryptographic Failures [REFERENCES]
- https://find-sec-bugs.github.io/bugs.htm#TDES_USAGE
- https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA

(desede-is-deprecated-java)


[warning] 33-33: Triple DES (3DES or DESede) is considered deprecated. AES is the recommended cipher. Upgrade to use AES.
Context: Cipher.getInstance(CIPHER_TRANS)
Note: [CWE-326]: Inadequate Encryption Strength [OWASP A03:2017]: Sensitive Data Exposure [OWASP A02:2021]: Cryptographic Failures [REFERENCES]
- https://find-sec-bugs.github.io/bugs.htm#TDES_USAGE
- https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA

(desede-is-deprecated-java)


[warning] 22-22: Use of AES with ECB mode detected. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.
Context: Cipher.getInstance(CIPHER_TRANS)
Note: [CWE-327]: Use of a Broken or Risky Cryptographic Algorithm [OWASP A03:2017]: Sensitive Data Exposure [OWASP A02:2021]: Cryptographic Failures [REFERENCES]
- https://owasp.org/Top10/A02_2021-Cryptographic_Failures
- https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html

(use-of-aes-ecb-java)


[warning] 33-33: Use of AES with ECB mode detected. ECB doesn't provide message confidentiality and is not semantically secure so should not be used. Instead, use a strong, secure cipher: Cipher.getInstance("AES/CBC/PKCS7PADDING"). See https://owasp.org/www-community/Using_the_Java_Cryptographic_Extensions for more information.
Context: Cipher.getInstance(CIPHER_TRANS)
Note: [CWE-327]: Use of a Broken or Risky Cryptographic Algorithm [OWASP A03:2017]: Sensitive Data Exposure [OWASP A02:2021]: Cryptographic Failures [REFERENCES]
- https://owasp.org/Top10/A02_2021-Cryptographic_Failures
- https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html

(use-of-aes-ecb-java)

🔇 Additional comments (18)
src/main/resources/sql/schema.sql (2)

3-3: LGTM - Table drop statement in correct order.

The drop statement for the new table is properly placed before other drops to maintain dependency order.


45-54: LGTM - Properly structured table creation.

The apple_user_token table is properly defined with appropriate columns, constraints, and foreign key relationships.

src/test/resources/sql/schema.sql (2)

3-3: LGTM - Consistent test schema table drop.

The test schema's drop statement mirrors the production schema, which is good practice.


68-77: LGTM - Test schema table creation matches production.

The table definition in the test schema correctly matches the production schema, ensuring consistent behavior across environments.

src/main/java/org/runimo/runimo/auth/service/apple/AppleTokenVerifier.java (4)

25-25: LGTM - Adding TokenPair import for enhanced token management.

Good addition to support returning both access and refresh tokens together.


64-65: LGTM - Well-defined constant for Apple revocation endpoint.

Using a constant for the revocation URL improves maintainability.


98-98: LGTM - Updated method signature to return TokenPair.

Good change to return both tokens needed for the user withdrawal feature.


117-117: LGTM - Properly creating TokenPair with both tokens.

Correctly extracts both id_token and refresh_token from Apple's response.

src/main/java/org/runimo/runimo/user/service/WithdrawService.java (3)

5-11: Imports appear correct and consistent

These newly introduced imports appropriately reference Apple token logic and encryption utilities.


23-25: Good injection of additional dependencies

The added final fields for AppleTokenVerifier, AppleUserTokenRepository, and EncryptUtil cohesively integrate Apple token revocation and encryption logic into the withdrawal process.


32-34: Conditional withdrawal for Apple users looks correct

Checking the provider before invoking withdrawAppleUser ensures that Apple-specific logic is only applied to Apple users.

src/main/java/org/runimo/runimo/auth/service/apple/AppleLoginHandler.java (7)

10-18: Imports correctly align with the new encryption and Apple token repository

These imports facilitate storing the encrypted refresh token and managing Apple user tokens.


30-31: Dependency injection for Apple-related services is well-structured

Injecting AppleUserTokenRepository and EncryptUtil in the constructor supports persisting and securing the refresh token.


33-33: Switching from read-only transaction is appropriate

Since token data is now saved or updated in this flow, removing readOnly = true is a valid change.


35-38: Access token retrieval and decoding

Obtaining the token pair and decoding the access token using JWT.decode is reasonable, with proper exception handling for invalid tokens.


43-44: Saving the Apple refresh token immediately after user lookup

This maintains up-to-date token records in the database for Apple users.


49-60: Conditional registration logic is clearly structured

Throwing an UnRegisteredUserException and generating a temporal token for new users is a sound approach.


70-78: Refresh token encryption logic is sound

Returning a new AppleUserToken with an encrypted refresh token aligns with best practices for sensitive data storage.

Comment thread src/main/resources/application.yml
Comment thread src/test/resources/application.yml
Comment thread src/main/java/org/runimo/runimo/user/domain/AppleUserToken.java
Comment thread src/main/java/org/runimo/runimo/auth/service/EncryptUtil.java
Comment thread src/main/java/org/runimo/runimo/auth/service/EncryptUtil.java
Comment thread src/main/java/org/runimo/runimo/auth/service/EncryptUtil.java
Comment thread src/main/java/org/runimo/runimo/user/service/WithdrawService.java
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/main/java/org/runimo/runimo/user/service/WithdrawService.java (1)

48-54: Parameter name mismatch with its actual usage

The parameter name encryptedIdToken suggests it's an ID token, but it's actually used for a refresh token. This could cause confusion for future developers.

-private String getDecryptedToken(String encryptedIdToken) {
+private String getDecryptedToken(String encryptedRefreshToken) {
    try {
-        return encryptUtil.decrypt(encryptedIdToken);
+        return encryptUtil.decrypt(encryptedRefreshToken);
    } catch (Exception e) {
-        throw new RuntimeException("Failed to decrypt ID token", e);
+        throw new RuntimeException("Failed to decrypt refresh token", e);
    }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2f5c9e and e7ee464.

📒 Files selected for processing (2)
  • src/main/java/org/runimo/runimo/auth/service/apple/AppleLoginHandler.java (3 hunks)
  • src/main/java/org/runimo/runimo/user/service/WithdrawService.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/org/runimo/runimo/auth/service/apple/AppleLoginHandler.java
🔇 Additional comments (6)
src/main/java/org/runimo/runimo/user/service/WithdrawService.java (6)

5-9: Good organization of imports

The imports are well-organized and properly include all necessary classes for Apple user withdrawal functionality.


23-25: Good dependency injection setup

The new dependencies are properly declared as private final fields, which will be automatically injected through the constructor thanks to the @RequiredArgsConstructor annotation.


32-34: Good separation of concerns for Apple user withdrawal

The implementation correctly checks for Apple provider and delegates to a specialized method, maintaining clean code organization.


39-46: Well-structured Apple user withdrawal implementation

The method follows a clear sequence: fetch the token, decrypt it, revoke it, and then delete it from the database. This aligns with the PR objectives for secure user withdrawal.


43-44: Correct variable naming

Good use of a descriptive variable name that accurately reflects that this is a decrypted refresh token.


27-37: Robust transaction handling

The @Transactional annotation ensures that the entire withdrawal process, including the Apple-specific operations, is executed atomically. This prevents partial withdrawals that could leave the system in an inconsistent state.

@ekgns33 ekgns33 force-pushed the feat/apple-user-withdraw branch from e7ee464 to 8d2d465 Compare April 13, 2025 17:28
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/main/java/org/runimo/runimo/user/service/WithdrawService.java (2)

52-53: Error message doesn't match the token type being decrypted.

The error message incorrectly references "ID token" when the method is actually decrypting a refresh token.

-            throw new RuntimeException("Failed to decrypt ID token", e);
+            throw new RuntimeException("Failed to decrypt refresh token", e);

48-54: Consider using a more specific exception type.

The method currently throws a generic RuntimeException. Consider creating a domain-specific exception class for token-related errors to provide better error handling and clarity.

-    private String getDecryptedToken(String encryptedRefreshToken) {
-        try {
-            return encryptUtil.decrypt(encryptedRefreshToken);
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to decrypt refresh token", e);
-        }
-    }
+    private String getDecryptedToken(String encryptedRefreshToken) {
+        try {
+            return encryptUtil.decrypt(encryptedRefreshToken);
+        } catch (Exception e) {
+            throw new TokenDecryptionException("Failed to decrypt refresh token", e);
+        }
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7ee464 and 8d2d465.

📒 Files selected for processing (2)
  • src/main/java/org/runimo/runimo/auth/service/apple/AppleLoginHandler.java (3 hunks)
  • src/main/java/org/runimo/runimo/user/service/WithdrawService.java (2 hunks)
🔇 Additional comments (11)
src/main/java/org/runimo/runimo/user/service/WithdrawService.java (4)

5-7: Appropriate imports added for new functionality.

The import statements are correctly added to support the new Apple user withdrawal functionality, including EncryptUtil, AppleTokenVerifier, and related domain classes.

Also applies to: 9-9, 11-11


23-25: Dependencies properly configured with constructor injection.

The new dependencies are properly defined as private final fields which will be automatically injected via the @RequiredArgsConstructor annotation. This follows Spring best practices for dependency injection.


32-34: Well-structured conditional for handling Apple users.

The conditional logic for identifying and handling Apple users is cleanly implemented, separating the Apple-specific withdrawal logic into a dedicated method.


39-46: Apple user withdrawal implementation is comprehensive.

The withdrawAppleUser method properly handles all necessary steps: retrieving the token, decrypting it, revoking it via Apple, and cleaning up the database record.

src/main/java/org/runimo/runimo/auth/service/apple/AppleLoginHandler.java (7)

10-10: Required imports added for token handling functionality.

The imports for EncryptUtil, AppleUserToken, and AppleUserTokenRepository are correctly added to support the new functionality.

Also applies to: 14-14, 18-18


30-31: Dependencies properly configured with constructor injection.

The new dependencies are properly defined as private final fields which will be automatically injected via the @RequiredArgsConstructor annotation.


33-33: Appropriate transaction annotation modification.

The @Transactional annotation has been appropriately modified to allow write operations, which is necessary for saving the refresh token.


35-35: TokenPair integration enhances the authentication process.

The method now correctly uses TokenPair to handle both access and refresh tokens, improving the structure and clarity of the authentication process.

Also applies to: 43-46


49-60: Refactoring improves code organization.

The extraction of user retrieval logic into a separate method improves code organization and readability.

Consider translating the Korean comment to English to maintain consistency with the rest of the codebase:

-    // 사용자 정보가 있으면 반환하고 없다면, 회원가입을 위한 토큰을 생성하여 예외를 던진다.
+    // Returns user information if it exists, otherwise throws an exception with a registration token

62-68: Correct implementation of token storage.

The method correctly saves or updates Apple refresh tokens, and the user ID is properly referenced as noted in previous review comments.

Consider translating the Korean comment to English for consistency:

-    // 애플에서 발급한 refresh token을 DB에 저장한다.
+    // Saves the refresh token issued by Apple to the database

70-78: Token encryption is properly implemented.

The token encryption is properly implemented with appropriate error handling for encryption failures.

Consider using a more specific exception type instead of a generic RuntimeException:

-            throw new RuntimeException("Failed to encrypt refresh token", e);
+            throw new TokenEncryptionException("Failed to encrypt refresh token", e);

@ekgns33 ekgns33 requested a review from jeeheaG April 14, 2025 07:16
Copy link
Copy Markdown
Contributor

@jeeheaG jeeheaG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다! 애플로그인이 신경쓸 게 많군요..

@ekgns33 ekgns33 merged commit 52cde81 into main Apr 14, 2025
3 checks passed
@ekgns33 ekgns33 deleted the feat/apple-user-withdraw branch April 14, 2025 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants