Skip to content
Merged
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
41 changes: 8 additions & 33 deletions src/main/kotlin/com/yapp2app/auth/api/controller/AuthController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ import com.yapp2app.auth.api.converter.AuthResultConverter
import com.yapp2app.auth.api.dto.CreateAuthRequest
import com.yapp2app.auth.api.dto.GetAuthResponse
import com.yapp2app.auth.api.dto.GetKakaoTokenResponse
import com.yapp2app.auth.api.dto.GetTokenResponse
import com.yapp2app.auth.api.dto.LoginRequest
import com.yapp2app.auth.api.dto.RefreshTokenRequest
import com.yapp2app.auth.application.usecase.KakaoRegisterUseCase
import com.yapp2app.auth.application.usecase.LoginUseCase
import com.yapp2app.auth.application.usecase.RefreshTokenUseCase
import com.yapp2app.common.api.dto.BaseResponse
import io.swagger.v3.oas.annotations.Hidden
Expand All @@ -36,7 +33,6 @@ import org.springframework.web.bind.annotation.RestController
@RestController
class AuthController(
private val kakaoRegisterUseCase: KakaoRegisterUseCase,
private val loginUseCase: LoginUseCase,
private val refreshTokenUseCase: RefreshTokenUseCase,
private val commandConverter: AuthCommandConverter,
private val resultConverter: AuthResultConverter,
Expand All @@ -62,26 +58,6 @@ class AuthController(
[staging] https://kauth.kakao.com/oauth/authorize?client_id=4db94315d17162e99b36029f6f9775c6&redirect_uri=https://dev-yapp.suitestudy.com:4641/api/auth/test/kakao/redirect&response_type=code&scope=openid,profile_nickname,profile_image

응답의 `id_token` 필드 값을 이 API의 `idToken`으로 사용하세요.
""",
)
@ApiResponses(
ApiResponse(responseCode = "200", description = "카카오 OIDC 엔드포인트가 정상적으로 작동합니다."),
)
@PostMapping("/kakao/register")
fun kakaoRegister(@RequestBody @Valid request: CreateAuthRequest): BaseResponse<GetAuthResponse> {
val command = commandConverter.toCreateAuthCommand(request)

val result = kakaoRegisterUseCase.execute(command)

val response = resultConverter.toCreateAuthResponse(result)

return BaseResponse(data = response)
}

@Operation(
summary = "로그인",
description = """
## 로그인 API

사용자의 OID와 ProviderType을 사용하여 로그인을 수행합니다.

Expand All @@ -107,16 +83,15 @@ class AuthController(
""",
)
@ApiResponses(
ApiResponse(responseCode = "200", description = "로그인 성공"),
ApiResponse(responseCode = "400", description = "인증 실패 - 가입되지 않은 사용자"),
ApiResponse(responseCode = "200", description = "카카오 OIDC 엔드포인트가 정상적으로 작동합니다."),
)
@PostMapping("/login")
fun login(@RequestBody @Valid request: LoginRequest): BaseResponse<GetTokenResponse> {
val command = commandConverter.toLoginAuthCommand(request)
@PostMapping("/kakao/login")
fun kakaoRegister(@RequestBody @Valid request: CreateAuthRequest): BaseResponse<GetAuthResponse> {
val command = commandConverter.toCreateAuthCommand(request)

val result = loginUseCase.execute(command)
val result = kakaoRegisterUseCase.execute(command)

val response = resultConverter.toLoginAuthResponse(result)
val response = resultConverter.toCreateAuthResponse(result)

return BaseResponse(data = response)
}
Expand Down Expand Up @@ -150,12 +125,12 @@ class AuthController(
),
)
@PostMapping("/refresh")
fun refreshToken(@RequestBody @Valid request: RefreshTokenRequest): BaseResponse<GetTokenResponse> {
fun refreshToken(@RequestBody @Valid request: RefreshTokenRequest): BaseResponse<GetAuthResponse> {
val command = commandConverter.toRefreshTokenCommand(request)

val result = refreshTokenUseCase.execute(command)

val response = resultConverter.toLoginAuthResponse(result)
val response = resultConverter.toCreateAuthResponse(result)

return BaseResponse(data = response)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package com.yapp2app.auth.api.converter

import com.yapp2app.auth.api.dto.CreateAuthRequest
import com.yapp2app.auth.api.dto.LoginRequest
import com.yapp2app.auth.api.dto.RefreshTokenRequest
import com.yapp2app.auth.application.command.LoginCommand
import com.yapp2app.auth.application.command.RefreshTokenCommand
import com.yapp2app.auth.application.command.RegisterKakaoUserCommand
import org.springframework.stereotype.Component
Expand All @@ -14,9 +12,6 @@ class AuthCommandConverter {
fun toCreateAuthCommand(request: CreateAuthRequest): RegisterKakaoUserCommand =
RegisterKakaoUserCommand(request.idToken)

fun toLoginAuthCommand(request: LoginRequest): LoginCommand =
LoginCommand(oid = request.oid, providerType = request.providerType)

fun toRefreshTokenCommand(request: RefreshTokenRequest): RefreshTokenCommand =
RefreshTokenCommand(request.refreshToken)
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
package com.yapp2app.auth.api.converter

import com.yapp2app.auth.api.dto.GetAuthResponse
import com.yapp2app.auth.api.dto.GetTokenResponse
import com.yapp2app.auth.application.result.GetAuthResult
import com.yapp2app.auth.application.result.GetTokenResult
import org.springframework.stereotype.Component

@Component
class AuthResultConverter {

fun toCreateAuthResponse(result: GetAuthResult): GetAuthResponse =
GetAuthResponse(oid = result.oid, providerType = result.providerType)

fun toLoginAuthResponse(result: GetTokenResult): GetTokenResponse =
GetTokenResponse(accessToken = result.accessToken, result.refreshToken)
GetAuthResponse(accessToken = result.accessToken, result.refreshToken)
}
6 changes: 1 addition & 5 deletions src/main/kotlin/com/yapp2app/auth/api/dto/AuthResponse.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package com.yapp2app.auth.api.dto

import com.yapp2app.user.domain.enums.ProviderType

/**
* fileName : AuthResponse
* author : darren
* date : 2025. 12. 26. 18:05
* description : Auth aggregate에 대한 응답
*/
data class GetAuthResponse(val oid: Long, val providerType: ProviderType)

data class GetTokenResponse(val accessToken: String, val refreshToken: String)
data class GetAuthResponse(val accessToken: String, val refreshToken: String)

/**
* REST_API TEST용 DTO
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package com.yapp2app.auth.application.result

import com.yapp2app.user.domain.enums.ProviderType

/**
* fileName : AuthResult
* author : darren
* date : 2025. 12. 29. 14:23
* description :
*/
data class GetAuthResult(val oid: Long, val providerType: ProviderType)

data class GetTokenResult(val accessToken: String, val refreshToken: String)
data class GetAuthResult(val accessToken: String, val refreshToken: String)
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.yapp2app.auth.application.port.OauthHelperPort
import com.yapp2app.auth.application.port.OidcPort
import com.yapp2app.auth.application.result.GetAuthResult
import com.yapp2app.auth.infra.security.properties.OauthProperties
import com.yapp2app.auth.infra.security.token.AuthTokenProvider
import com.yapp2app.common.annotation.UseCase
import com.yapp2app.common.transaction.TransactionRunner
import com.yapp2app.user.application.port.UserRepositoryPort
Expand All @@ -30,6 +31,7 @@ class KakaoRegisterUseCase(
@Qualifier("kakaoOidcAdapter") private val oidcPort: OidcPort,
@Qualifier("kakaoOauthHelper") private val oauthHelperPort: OauthHelperPort,
private val restClient: RestClient,
private val tokenProvider: AuthTokenProvider,
private val userRepositoryPort: UserRepositoryPort,
private val transactionRunner: TransactionRunner,
) {
Expand All @@ -51,7 +53,25 @@ class KakaoRegisterUseCase(

val user = transactionRunner.run { registerKakaoUserIfEmpty(oauthInfoResponse) }

return GetAuthResult(oid = user.oid, providerType = user.providerType)
// JWT 토큰 생성
val accessToken = tokenProvider.createAccessToken(
id = user.id.toString(),
roles = user.roles.split(","),
name = user.name,
providerType = user.providerType,
)

val refreshToken = tokenProvider.createRefreshToken(
id = user.id.toString(),
roles = user.roles.split(","),
name = user.name,
providerType = user.providerType,
)

return GetAuthResult(
accessToken = accessToken,
refreshToken = refreshToken,
)
}

private fun registerKakaoUserIfEmpty(oauthInfoResponse: OauthInfoResponse): User {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.yapp2app.auth.application.usecase

import com.yapp2app.auth.application.command.RefreshTokenCommand
import com.yapp2app.auth.application.result.GetTokenResult
import com.yapp2app.auth.application.result.GetAuthResult
import com.yapp2app.auth.infra.security.token.AuthTokenProvider
import com.yapp2app.auth.infra.security.token.UserPrincipal
import com.yapp2app.common.annotation.UseCase
Expand All @@ -17,7 +17,7 @@ import com.yapp2app.common.exception.BusinessException
@UseCase
class RefreshTokenUseCase(private val tokenProvider: AuthTokenProvider) {

fun execute(command: RefreshTokenCommand): GetTokenResult {
fun execute(command: RefreshTokenCommand): GetAuthResult {
// 1. RefreshToken 유효성 검증
if (!tokenProvider.validateRefreshToken(command.refreshToken)) {
throw BusinessException(ResultCode.INVALID_TOKEN_ERROR)
Expand All @@ -43,7 +43,7 @@ class RefreshTokenUseCase(private val tokenProvider: AuthTokenProvider) {
providerType = userPrincipal.providerType,
)

return GetTokenResult(
return GetAuthResult(
accessToken = newAccessToken,
refreshToken = newRefreshToken,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@ class JwtAuthenticationFilter(private val tokenProvider: AuthTokenProvider) : On
}
filterChain.doFilter(request, response)
} catch (ex: SignatureException) {
handleException(response, ResultCode.INVALID_TOKEN_ERROR)
handleException(response, ResultCode.INVALID_TOKEN_ERROR, HttpServletResponse.SC_FORBIDDEN)
} catch (ex: SecurityException) {
handleException(response, ResultCode.INVALID_TOKEN_ERROR)
handleException(response, ResultCode.INVALID_TOKEN_ERROR, HttpServletResponse.SC_FORBIDDEN)
} catch (ex: MalformedJwtException) {
handleException(response, ResultCode.INVALID_TOKEN_ERROR)
handleException(response, ResultCode.INVALID_TOKEN_ERROR, HttpServletResponse.SC_FORBIDDEN)
} catch (ex: ExpiredJwtException) {
handleException(response, ResultCode.EXPIRED_TOKEN_ERROR)
handleException(response, ResultCode.EXPIRED_TOKEN_ERROR, HttpServletResponse.SC_UNAUTHORIZED)
} catch (ex: UnsupportedJwtException) {
handleException(response, ResultCode.EXPIRED_TOKEN_ERROR)
handleException(response, ResultCode.EXPIRED_TOKEN_ERROR, HttpServletResponse.SC_UNAUTHORIZED)
} catch (ex: Exception) {
handleException(response, ResultCode.SECURITY_ERROR)
handleException(response, ResultCode.SECURITY_ERROR, HttpServletResponse.SC_FORBIDDEN)
}
}

Expand Down Expand Up @@ -88,12 +88,12 @@ class JwtAuthenticationFilter(private val tokenProvider: AuthTokenProvider) : On
* - **대응**: 재로그인이 필요합니다. `/api/auth/login` API를 호출하세요.
* - **재로그인 필요 여부**: 예
*/
private fun handleException(response: HttpServletResponse, resultCode: ResultCode) {
private fun handleException(response: HttpServletResponse, resultCode: ResultCode, status: Int) {
val jsonObject = JsonObject()

response.contentType = "application/json;charset=UTF-8"
response.characterEncoding = "utf-8"
response.status = HttpServletResponse.SC_UNAUTHORIZED
response.status = status

jsonObject.addProperty("resultCode", resultCode.code)
jsonObject.addProperty("message", resultCode.message)
Expand Down