Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Deploy Auth to ECS

on:
push:
branches:
- main
workflow_dispatch:

env:
AWS_REGION: ap-northeast-2
AWS_ACCOUNT_ID: 727452759104
ECR_REPOSITORY: momentlit/auth
ECS_CLUSTER: default
ECS_SERVICE: momentlit-auth-service
IMAGE_TAG: latest

jobs:
deploy:
name: Build and Deploy Auth
runs-on: ubuntu-latest

steps:
- name: Checkout source code
uses: actions/checkout@v4
Comment on lines +17 to +24

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

보안 강화: permissions 블록 추가 및 persist-credentials: false 설정 필요

정적 분석에서 지적한 대로, 최소 권한 원칙을 위해 명시적 권한 블록을 추가하고, checkout 단계에서 자격 증명 지속을 비활성화해야 합니다.

🛡️ 권장 수정 사항
 jobs:
   deploy:
     name: Build and Deploy Auth
     runs-on: ubuntu-latest
+    permissions:
+      contents: read
+      id-token: write

     steps:
       - name: Checkout source code
         uses: actions/checkout@v4
+        with:
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
jobs:
deploy:
name: Build and Deploy Auth
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v4
jobs:
deploy:
name: Build and Deploy Auth
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout source code
uses: actions/checkout@v4
with:
persist-credentials: false
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 23-24: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 24-24: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/deploy.yml around lines 17 - 24, The GitHub Actions
workflow needs security hardening to follow the principle of least privilege.
Add a top-level permissions block to the workflow (at the same level as the jobs
section) to explicitly declare minimal required permissions, and then add
persist-credentials: false parameter to the checkout@v4 step to prevent Git
credentials from being stored in the runner environment. This ensures the
workflow only requests and retains the minimum permissions necessary for the
build and deploy operation.

Source: Linters/SAST tools


- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5
with:
aws-region: ${{ env.AWS_REGION }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and push Docker image
run: |
IMAGE_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPOSITORY}:${IMAGE_TAG}

docker buildx build \
--platform linux/amd64 \
--provenance=false \
-t $IMAGE_URI \
. \
--push

- name: Force new ECS deployment
run: |
aws ecs update-service \
--cluster $ECS_CLUSTER \
--service $ECS_SERVICE \
--force-new-deployment \
--region $AWS_REGION

- name: Wait for ECS service stable
run: |
aws ecs wait services-stable \
--cluster $ECS_CLUSTER \
--services $ECS_SERVICE \
--region $AWS_REGION
52 changes: 50 additions & 2 deletions API_SPEC.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,54 @@ servers:
tags: []
paths: {}
components:
schemas: {}
responses: {}
schemas:
ErrorResponse:
type: object
properties:
message:
type: string
example: "[ERROR: Request/BadRequest] Refresh Token을 입력해주세요."
data:
nullable: true
example: null
required:
- message
- data
Comment on lines +13 to +24

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

에러 응답 스키마가 코딩 가이드라인을 위반합니다.

코딩 가이드라인은 "API error responses should have a consistent format with 'code' and 'message' fields"를 요구하지만, 현재 ErrorResponse 스키마는 code 필드가 없고 messagedata 필드만 있습니다. 에러 코드가 메시지 문자열에 접두사로 포함되어 있어(예: "[ERROR: Request/BadRequest]") 클라이언트가 구조화된 데이터 대신 문자열 파싱을 해야 합니다.

다음과 같이 구조화된 스키마로 변경하는 것을 권장합니다:

ErrorResponse:
  type: object
  properties:
    code:
      type: string
      example: "REQUEST_BAD_REQUEST"
    message:
      type: string
      example: "Refresh Token을 입력해주세요."
    data:
      nullable: true
      example: null
  required:
    - code
    - message

이 변경은 ApiResponse DTO와 GlobalExceptionHandler의 응답 생성 로직도 함께 수정해야 합니다.

As per coding guidelines, "API error responses should have a consistent format with 'code' and 'message' fields."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@API_SPEC.yaml` around lines 13 - 24, The ErrorResponse schema in
API_SPEC.yaml violates the coding guideline requiring error responses to have
both 'code' and 'message' fields as separate properties. Currently, the error
code is embedded as a string prefix in the 'message' field (e.g., "[ERROR:
Request/BadRequest]"), forcing clients to parse strings instead of using
structured data. Add a new 'code' property to the ErrorResponse schema as a
string type, remove the error code prefix from the message example, and update
the 'required' array to include both 'code' and 'message'. Additionally, ensure
that the ApiResponse DTO class and GlobalExceptionHandler's response creation
logic are modified to populate the separate 'code' and 'message' fields
independently rather than combining them into a single message string.

Source: Coding guidelines

responses:
BadRequestError:
description: "Invalid request input."
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
message: "[ERROR: Request/BadRequest] Refresh Token을 입력해주세요."
data: null
UnauthorizedError:
description: "Authentication failed or token is invalid."
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
message: "[ERROR: Auth/Unauthorized] 유효하지 않은 Refresh Token입니다."
data: null
GoogleOauthError:
description: "Google OAuth request failed."
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
message: "[ERROR: Auth/Oauth/Google] Google Access Token을 발급받을 수 없습니다."
data: null
InternalServerError:
description: "Unexpected server error."
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
message: "[ERROR: ?/?] 서버 내부 오류가 발생했습니다."
data: null
Comment on lines +25 to +61

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

에러 응답 컴포넌트의 예시가 구조화되지 않은 에러 코드를 포함합니다.

각 에러 응답 예시의 message 필드에 "[ERROR: Request/BadRequest]" 같은 접두사가 포함되어 있습니다. 위에서 언급한 대로 code 필드를 별도로 분리하면, 예시도 다음과 같이 업데이트되어야 합니다:

BadRequestError:
  description: "Invalid request input."
  content:
    application/json:
      schema:
        $ref: "`#/components/schemas/ErrorResponse`"
      example:
        code: "REQUEST_BAD_REQUEST"
        message: "Refresh Token을 입력해주세요."
        data: null
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@API_SPEC.yaml` around lines 25 - 61, The error response examples in the
responses section (BadRequestError, UnauthorizedError, GoogleOauthError,
InternalServerError) contain error codes embedded in the message field as
prefixes like "[ERROR: Request/BadRequest]". Extract these error code prefixes
from the message field and create a separate `code` field for each error
response example. Update BadRequestError to have code "REQUEST_BAD_REQUEST",
UnauthorizedError to have code "AUTH_UNAUTHORIZED", GoogleOauthError to have
code "AUTH_OAUTH_GOOGLE", and InternalServerError to have an appropriate code
value. Keep only the Korean error message text (without the prefix) in the
message field for each example.

Source: Coding guidelines

securitySchemes: {}
3 changes: 2 additions & 1 deletion docs/service-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ No repository or persistence component is visible. Build dependencies include Sp

## Exception Handling

No project-specific exception handling is visible.
Project-specific exception handling is implemented under `com.example.auth.global.exception`.
Auth-specific exceptions extend `AuthException` and are handled by `GlobalExceptionHandler`.

## Test Structure

Expand Down
10 changes: 9 additions & 1 deletion docs/service-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@ State transitions are documented only where visible in entity or service methods

## Exception Cases

No project-specific exception handling is visible. HTTP status mapping for these exceptions is Needs confirmation unless explicitly handled in code.
Project-specific exception handling is visible under `com.example.auth.global.exception`.
Visible mappings:

- `BadRequestException`: `400 Bad Request`
- `UnauthorizedException`: `401 Unauthorized`
- `TokenNotFoundException`: `401 Unauthorized`
- `GoogleOauthException`: `502 Bad Gateway`
- Other `AuthException`: `500 Internal Server Error`
- Other `Exception`: `500 Internal Server Error`

## API Behavior Policy

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import com.example.auth.global.client.dto.response.GoogleUserInfoResponse;
import com.example.auth.global.client.dto.response.UserAuthResponse;
import com.example.auth.global.client.dto.request.UserGoogleOauthRequest;
import com.example.auth.global.exception.UnauthorizedException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClient;

@Component
Expand All @@ -22,11 +24,16 @@ public UserServiceClient(
}

public UserAuthResponse authenticate(SignInRequest request) {
return restClient.post()
.uri("/internal/users/authenticate")
.body(request)
.retrieve()
.body(UserAuthResponse.class);
try {
return restClient.post()
.uri("/internal/users/authenticate")
.body(request)
.retrieve()
.body(UserAuthResponse.class);

} catch (HttpClientErrorException.Unauthorized e) {
throw new UnauthorizedException("이메일 또는 비밀번호가 일치하지 않습니다.");
}
}

public UserAuthResponse authenticateGoogle(GoogleUserInfoResponse request) {
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/com/example/auth/global/dto/ApiResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@
public record ApiResponse<T> (
String message,
T data
){}
){
public static <T> ApiResponse<T> fail(String message) {
return new ApiResponse<>(message, null);
}
Comment on lines 3 to +9

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

에러 응답 포맷을 code/message 분리 구조로 맞춰주세요.

현재 fail(String message)messagedata=null만 반환해서, 에러 코드를 문자열 접두사로 붙이는 구현에 의존하게 됩니다. 이 구조는 전역 예외 응답의 계약을 불안정하게 만들고, 클라이언트가 code를 구조적으로 파싱할 수 없습니다.

변경 예시
-public record ApiResponse<T> (
-    String message,
-    T data
-){
-    public static <T> ApiResponse<T> fail(String message) {
-        return new ApiResponse<>(message, null);
-    }
+public record ApiResponse<T> (
+    String code,
+    String message,
+    T data
+){
+    public static <T> ApiResponse<T> fail(String code, String message) {
+        return new ApiResponse<>(code, message, null);
+    }
 }

As per coding guidelines, "API error responses should have a consistent format with 'code' and 'message' fields."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/example/auth/global/dto/ApiResponse.java` around lines 3 -
9, The ApiResponse record currently lacks a code field, and the fail method only
accepts a message parameter with error codes embedded as string prefixes. Add a
code field to the ApiResponse record to store error codes separately, then
update the fail method signature to accept both code and message as distinct
parameters. This will ensure error responses follow a consistent structure with
properly separated code and message fields, allowing clients to parse error
codes structurally rather than relying on string parsing.

Source: Coding guidelines

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.auth.global.exception;

public class AuthException extends RuntimeException {
public AuthException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.auth.global.exception;

public class BadRequestException extends AuthException {
public BadRequestException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.example.auth.global.exception;

import com.example.auth.global.dto.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(TokenNotFoundException.class)
public ResponseEntity<ApiResponse<String>> tokenNotFoundHandleException(TokenNotFoundException e) {
log.warn("TokenNotFoundException: {}", e.getMessage());

return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(ApiResponse.fail("[ERROR: Auth/Token/NotFound] " + e.getMessage()));
}

@ExceptionHandler(UnauthorizedException.class)
public ResponseEntity<ApiResponse<String>> unauthorizedHandleException(UnauthorizedException e) {
log.warn("UnauthorizedException: {}", e.getMessage());

return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(ApiResponse.fail("[ERROR: Auth/Unauthorized] " + e.getMessage()));
}

@ExceptionHandler(BadRequestException.class)
public ResponseEntity<ApiResponse<String>> badRequestHandleException(BadRequestException e) {
log.warn("BadRequestException: {}", e.getMessage());

return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(ApiResponse.fail("[ERROR: Request/BadRequest] " + e.getMessage()));
}

@ExceptionHandler(GoogleOauthException.class)
public ResponseEntity<ApiResponse<String>> googleOauthHandleException(GoogleOauthException e) {
log.error("GoogleOauthException", e);

return ResponseEntity.status(HttpStatus.BAD_GATEWAY)
.body(ApiResponse.fail("[ERROR: Auth/Oauth/Google] " + e.getMessage()));
}

@ExceptionHandler(AuthException.class)
public ResponseEntity<ApiResponse<String>> authHandleException(AuthException e) {
log.error("AuthException", e);

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponse.fail("[ERROR: Auth/?] " + e.getMessage()));
}

@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResponse<String>> globalHandleException(Exception e) {
log.error("Unhandled exception", e);

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponse.fail("[ERROR: ?/?] 서버 내부 오류가 발생했습니다."));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.auth.global.exception;

public class GoogleOauthException extends AuthException {
public GoogleOauthException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.auth.global.exception;

public class TokenNotFoundException extends AuthException {
public TokenNotFoundException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.auth.global.exception;

public class UnauthorizedException extends AuthException {
public UnauthorizedException(String message) {
super(message);
}
}
3 changes: 2 additions & 1 deletion src/main/java/com/example/auth/service/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.example.auth.global.client.dto.response.GoogleTokenResponse;
import com.example.auth.global.client.dto.response.GoogleUserInfoResponse;
import com.example.auth.global.client.dto.response.UserAuthResponse;
import com.example.auth.global.exception.GoogleOauthException;
import java.net.URI;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
Expand Down Expand Up @@ -80,7 +81,7 @@ public OauthGoogleCallbackResponse loginWithGoogle(String code, String state) {
googleOauthClient.requestToken(code);

if (googleToken == null || !StringUtils.hasText(googleToken.accessToken())) {
throw new IllegalArgumentException("Google Access Token을 발급받을 수 없습니다.");
throw new GoogleOauthException("Google Access Token을 발급받을 수 없습니다.");
}

GoogleUserInfoResponse googleUser =
Expand Down
12 changes: 7 additions & 5 deletions src/main/java/com/example/auth/service/AuthValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,40 @@
import com.example.auth.dto.request.SignInRequest;
import com.example.auth.dto.request.SignOutRequest;
import com.example.auth.global.client.dto.response.UserAuthResponse;
import com.example.auth.global.exception.BadRequestException;
import com.example.auth.global.exception.UnauthorizedException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Component
public class AuthValidator {
public void validateLoginRequest(SignInRequest request) {
if (request == null || !StringUtils.hasText(request.email()) || !StringUtils.hasText(request.password())) {
throw new IllegalArgumentException("아이디와 비밀번호를 입력해주세요.");
throw new BadRequestException("아이디와 비밀번호를 입력해주세요.");
}
}

public void validateRefreshRequest(RefreshRequest request) {
if (request == null || !StringUtils.hasText(request.refreshToken())) {
throw new IllegalArgumentException("Refresh Token을 입력해주세요.");
throw new BadRequestException("Refresh Token을 입력해주세요.");
}
}

public void validateGoogleAuthorizationCode(String code) {
if (!StringUtils.hasText(code)) {
throw new IllegalArgumentException("Google Authorization Code를 입력해주세요.");
throw new BadRequestException("Google Authorization Code를 입력해주세요.");
}
}

public void validateSignOutRequest(SignOutRequest request) {
if (request == null || !StringUtils.hasText(request.refresh_token())) {
throw new IllegalArgumentException("Refresh Token을 입력해주세요.");
throw new BadRequestException("Refresh Token을 입력해주세요.");
}
}

public void validateAuthenticatedUser(UserAuthResponse user) {
if (user == null || user.userId() == null) {
throw new IllegalArgumentException("사용자 인증 정보를 확인할 수 없습니다.");
throw new UnauthorizedException("사용자 인증 정보를 확인할 수 없습니다.");
}
}
}
11 changes: 9 additions & 2 deletions src/main/java/com/example/auth/service/TokenService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.example.auth.service;

import com.example.auth.global.security.JwtProvider;
import com.example.auth.global.exception.TokenNotFoundException;
import com.example.auth.global.exception.UnauthorizedException;
import com.example.auth.infra.RefreshTokenRepository;
import io.jsonwebtoken.JwtException;
import org.springframework.stereotype.Service;

@Service
Expand Down Expand Up @@ -46,12 +49,16 @@ public long accessTokenExpiresInSeconds() {
}

public String getValidRefreshTokenSubject(String refreshToken) {
jwtProvider.validateToken(refreshToken);
try {
jwtProvider.validateToken(refreshToken);
} catch (JwtException | IllegalArgumentException exception) {
throw new UnauthorizedException("유효하지 않은 Refresh Token입니다.");
}
Comment on lines +52 to +56

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# JwtProvider.validateToken() 메서드의 예외 선언 확인
rg -nP -A 10 'void\s+validateToken\s*\(' --type=java -g '*JwtProvider*'

Repository: MomentLit/Auth

Length of output: 40


🌐 Web query:

JJWT 0.12.6 JwtParser parseSignedClaims exceptions

💡 Result:

In JJWT 0.12.6, the JwtParser.parseSignedClaims(CharSequence) method is designed to parse and verify signed JWTs (JWS). Because this operation involves both parsing and cryptographic verification, it can throw various exceptions derived from the base io.jsonwebtoken.JwtException class [1][2]. Common exceptions include: 1. SignatureException: Thrown if the JWT signature verification fails [3]. 2. ExpiredJwtException: Thrown if the JWT has expired (e.g., the 'exp' claim is in the past) [4][3]. 3. UnsupportedJwtException: Thrown if the parsed JWT does not match the expected format or type (e.g., if you call parseSignedClaims on a token that is not a JWS) [1][2][3]. 4. MalformedJwtException: Thrown if the JWT string is not correctly formatted or is otherwise unparseable [1][2]. 5. MissingClaimException: Thrown if a required claim is missing. 6. PrematureJwtException: Thrown if the JWT is not yet valid (e.g., the 'nbf' claim is in the future). Since these exceptions all extend from JwtException, it is recommended to wrap the parseSignedClaims call in a try-catch block to handle authentication or validation failures [1][2][3]: try { Claims claims = Jwts.parser.verifyWith(secretKey).build.parseSignedClaims(token).getPayload; // Token is valid and trusted } catch (JwtException e) { // Token is invalid, expired, or failed signature verification } Note that in version 0.12.6, JwtParser is immutable, and you must use the Jwts.parser method to obtain a JwtParserBuilder, configure it, and call build before parsing [5][6][7]. Using the incorrect method for the token type (e.g., trying to parse an unsigned JWT with parseSignedClaims) will trigger an UnsupportedJwtException [1][2].

Citations:


🏁 Script executed:

fd -type f -name "*.java" | head -20

Repository: MomentLit/Auth

Length of output: 229


🏁 Script executed:

find . -type f -name "*JwtProvider*" 2>/dev/null

Repository: MomentLit/Auth

Length of output: 124


🏁 Script executed:

rg "class JwtProvider" --type=java -A 5

Repository: MomentLit/Auth

Length of output: 615


🏁 Script executed:

cat -n src/main/java/com/example/auth/service/TokenService.java | head -80

Repository: MomentLit/Auth

Length of output: 2958


🏁 Script executed:

cat -n src/main/java/com/example/auth/global/security/JwtProvider.java

Repository: MomentLit/Auth

Length of output: 4740


IllegalArgumentException 포착을 제거하세요.

JwtProvider.validateToken()은 JJWT의 parseSignedClaims()을 통해 오직 JwtException 및 그 하위 예외만 던집니다. IllegalArgumentException은 이 검증 과정에서 발생하지 않으므로, 이를 포착하는 것은 불필요하며 실제 버그를 은폐할 수 있습니다. catch (JwtException exception)으로 변경하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/example/auth/service/TokenService.java` around lines 52 -
56, Remove the unnecessary `IllegalArgumentException` from the catch block in
the TokenService token validation logic. The `jwtProvider.validateToken()`
method only throws `JwtException` and its subclasses through JJWT's
parseSignedClaims() method, so catching `IllegalArgumentException` is redundant
and can mask actual bugs. Change the catch clause to only catch `JwtException`,
keeping the same UnauthorizedException throw statement that handles the
validation failure.


String subject = jwtProvider.getSubject(refreshToken);

if (!refreshTokenRepository.existsBySubjectAndToken(subject, refreshToken)) {
throw new IllegalArgumentException(
throw new TokenNotFoundException(
"저장된 Refresh Token과 일치하지 않습니다."
);
}
Expand Down