Conversation
LoginResponse/TokenRefreshResponse에 tokenType 필드 추가
- Auth-001 에러메시지가 다양해서 상수객체로 분리 - 에러코드&메시지&tatus를 한번에 매핑·국제화할 계획이면 enum/sealed class로 가는 게 좋지만, 그건아니라 일단 상수클래스 적용
- bearer 이중으로&공백포함 문제를 방지하기 위해 수신하위호환 지원 - 내부 파서에 접두사 제거 후 검증
There was a problem hiding this comment.
Pull Request Overview
Implements standard token response format and adds token type validation to enhance API security. The PR removes "Bearer" prefix from token generation, allows flexible token reception, and introduces strict token type validation with detailed error messages.
Key changes:
- Standard response format:
tokenType,accessToken,refreshTokenfields - Token type claim validation with specific error messages for type mismatches
/refresh-tokenendpoint now ignores Authorization header and only uses request body
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| JwtTokenProcessor.kt | Removes Bearer prefix from token generation, adds tokenType claim, implements flexible parsing |
| InvalidTokenMessages.kt | Adds centralized token error message constants |
| AuthenticationService.kt | Updates error messages to use constants, removes Bearer prefix normalization |
| AuthUserInfoArgumentResolver.kt | Updates to use centralized error message constants |
| TokenRefreshResponse.kt | Adds tokenType field to response structure |
| LoginResponse.kt | Adds tokenType field to response structure |
| AuthenticationController.kt | Removes Authorization header handling from refresh-token endpoint |
| JwtTokenProcessorTest.kt | Updates tests to verify new token behavior and type validation |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| val issueDate: Date = convertToDate(issueTime) | ||
| val key: String = jwtProperties.findTokenKey(tokenType) | ||
| val expiredHours: Long = jwtProperties.findExpiredHours(tokenType) | ||
| val claimsWithTokenType: Map<String, Any> = HashMap(privateClaims).plus("tokenType" to tokenType.name) |
There was a problem hiding this comment.
Creating a new HashMap and then calling plus() is inefficient. Consider using privateClaims + ("tokenType" to tokenType.name) or buildMap { putAll(privateClaims); put("tokenType", tokenType.name) } for better performance.
| val claimsWithTokenType: Map<String, Any> = HashMap(privateClaims).plus("tokenType" to tokenType.name) | |
| val claimsWithTokenType: Map<String, Any> = privateClaims + ("tokenType" to tokenType.name) |
| val requestedKey: String = jwtProperties.findTokenKey(tokenType) | ||
| parseWithKey(requestedKey, pureToken)?.let { claims -> | ||
| val actualType: String? = claims["tokenType"] as? String | ||
| if (actualType != null && !actualType.equals(tokenType.name, ignoreCase = true)) { |
There was a problem hiding this comment.
The ignoreCase comparison is inconsistent with the exact string comparison used when setting the tokenType claim. Since tokenType.name always produces uppercase strings, consider using exact equality comparison for consistency: actualType != tokenType.name.
| if (actualType != null && !actualType.equals(tokenType.name, ignoreCase = true)) { | |
| if (actualType != null && actualType != tokenType.name) { |
|
Claude finished @seulnan's task —— View job 🔍 PR 리뷰 완료📋 리뷰 체크리스트
📊 전체적인 평가표준 토큰 응답 형식을 도입하고 토큰 타입 검증을 강화한 좋은 개선사항입니다. Bearer 접두사 제거와 타입 클레임 추가로 API의 일관성과 보안성이 향상되었습니다. 전반적으로 잘 구현되었으나 몇 가지 개선 사항을 제안합니다. 🔍 주요 이슈1. [성능 개선 필요] JwtTokenProcessor.kt - Line 36-39Copilot이 지적한 대로, // 현재 코드
val claimsWithTokenType: Map<String, Any> = buildMap {
putAll(privateClaims)
put("tokenType", tokenType.name)
}
// 개선안 - 이미 올바르게 구현됨✅ 실제로 코드를 확인해보니 이미 2. [일관성 문제] JwtTokenProcessor.kt - Line 62타입 비교 시 // Line 62: 대소문자 무시 비교
if (actualType != null && !actualType.equals(tokenType.name, ignoreCase = true))
// Line 38: 항상 대문자로 저장
put("tokenType", tokenType.name) // TokenType.ACCESS.name = "ACCESS"제안: 일관성을 위해 정확한 비교를 사용하세요: if (actualType != null && actualType != tokenType.name)✅ 잘 구현된 부분1. 토큰 타입 검증 로직
2. 에러 메시지 상수화
3. Bearer 접두사 유연한 처리
4. 테스트 코드 보강
💡 추가 개선 제안1. 토큰 타입 enum 활용현재 // 현재: "ACCESS" (6 bytes) / "REFRESH" (7 bytes)
put("tokenType", tokenType.name)
// 제안: 0 or 1 (1 byte)
put("tt", tokenType.ordinal)2. 토큰 검증 실패 로깅보안 모니터링을 위해 토큰 타입 불일치나 검증 실패 시 로그를 남기는 것을 고려하세요: if (actualType != null && actualType != tokenType.name) {
logger.warn("Token type mismatch: expected={}, actual={}", tokenType.name, actualType)
// ...
}3. SwaggerConfiguration 버전 관리현재 하드코딩된 버전(v1.1.0)을 application.properties나 build.gradle에서 관리하면 더 좋을 것 같습니다: @Value("\${api.version}")
private lateinit var apiVersion: String🔒 보안 관련 검토✅ 긍정적인 부분
|
- tokenType.name(대문자)와 일치하도록 actualType == tokenType.name로 변경 - 비교 일관성 및 의도치 않은 값 통과 방지
원인 및 해결
📄 작업 내용 요약
그래서 이미 해결되었지만, 나중에 이런 오류가 났을때 원인파악을 빠르게 하기 위해 표준화방식으로 변경
BREAKING CHANGE:
그외:
구체적인 api변경사항 요약
공통POST /oauth2/loginPOST /refresh-tokenPOST /logoutGET /validate-token보호 API 전반📎 Issue 번호
closes #129