Skip to content

Commit

Permalink
feat: 카카오 인증인가 토큰 발급
Browse files Browse the repository at this point in the history
  • Loading branch information
DongGeon0908 committed Jul 29, 2024
1 parent 3aeac01 commit 135447b
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.hero.alignlab.client.kakao

import com.hero.alignlab.client.kakao.client.KaKaoOAuthClient
import com.hero.alignlab.client.kakao.config.KakaoOAuthClientConfig
import com.hero.alignlab.client.kakao.model.request.GenerateKakaoOAuthTokenRequest
import com.hero.alignlab.client.kakao.model.response.GenerateKakaoOAuthTokenResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.springframework.stereotype.Service

@Service
class KakaoOAuthService(
private val kaKaoOAuthClient: KaKaoOAuthClient,
private val config: KakaoOAuthClientConfig.Config
) {
suspend fun getOAuthAuthorizeCode(redirectUrl: String? = null) {
withContext(Dispatchers.IO) {
kaKaoOAuthClient.getOAuthAuthorizeCode()
}
}

suspend fun generateOAuthToken(code: String, redirectUri: String? = null): GenerateKakaoOAuthTokenResponse {
val request = GenerateKakaoOAuthTokenRequest(
clientId = config.clientSecretCode,
redirectUri = redirectUri ?: config.redirectUrl,
code = code,
)

return generateOAuthToken(request)
}

suspend fun generateOAuthToken(request: GenerateKakaoOAuthTokenRequest): GenerateKakaoOAuthTokenResponse {
return withContext(Dispatchers.IO) {
kaKaoOAuthClient.generateOAuthToken(request)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.hero.alignlab.client.kakao.client

import com.hero.alignlab.client.kakao.model.request.GenerateKakaoOAuthTokenRequest
import com.hero.alignlab.client.kakao.model.response.GenerateKakaoOAuthTokenResponse

interface KaKaoOAuthClient {
suspend fun getOAuthAuthorizeCode(redirectUrl: String? = null)

suspend fun generateOAuthToken(request: GenerateKakaoOAuthTokenRequest): GenerateKakaoOAuthTokenResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package com.hero.alignlab.client.kakao.client

import com.hero.alignlab.client.kakao.SuspendableClient
import com.hero.alignlab.client.kakao.config.KakaoOAuthClientConfig
import com.hero.alignlab.client.kakao.model.request.GenerateKakaoOAuthTokenRequest
import com.hero.alignlab.client.kakao.model.response.GenerateKakaoOAuthTokenResponse
import org.springframework.http.MediaType
import org.springframework.web.reactive.function.client.WebClient

class SuspendableKakaoOAuthClient(
Expand All @@ -19,4 +22,13 @@ class SuspendableKakaoOAuthClient(
.build()
}.requestOrNull<Any>()
}

override suspend fun generateOAuthToken(request: GenerateKakaoOAuthTokenRequest): GenerateKakaoOAuthTokenResponse {
return client
.post()
.uri("/token")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.bodyValue(request)
.request()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.hero.alignlab.client.kakao.model.request

import com.fasterxml.jackson.databind.PropertyNamingStrategies
import com.fasterxml.jackson.databind.annotation.JsonNaming

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class)
data class GenerateKakaoOAuthTokenRequest(
val grantType: String = "authorization_code",
val clientId: String,
val redirectUri: String,
val code: String,
val clientSecret: String? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.hero.alignlab.client.kakao.model.response

import com.fasterxml.jackson.databind.PropertyNamingStrategies
import com.fasterxml.jackson.databind.annotation.JsonNaming

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class)
data class GenerateKakaoOAuthTokenResponse(
val tokenType: String,
val accessToken: String,
val idToken: String?,
val expiresIn: Int,
val refreshToken: String,
val refreshTokenExpiresIn: Int,
val scope: String?
)
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
package com.hero.alignlab.domain.auth.application

import com.hero.alignlab.client.kakao.client.KaKaoOAuthClient
import com.hero.alignlab.client.kakao.KakaoOAuthService
import com.hero.alignlab.common.extension.toJson
import com.hero.alignlab.domain.auth.model.OAuthProvider
import com.hero.alignlab.domain.auth.model.request.OAuthAuthorizedRequest
import com.hero.alignlab.domain.auth.model.response.OAuthAuthorizeCodeResponse
import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.stereotype.Service

@Service
class OAuthFacade(
private val kaKaoOAuthClient: KaKaoOAuthClient,
private val kakaoOAuthService: KakaoOAuthService,
) {
private val logger = KotlinLogging.logger { }

suspend fun getOAuthAuthorizeCode(provider: OAuthProvider): OAuthAuthorizeCodeResponse {
when (provider) {
OAuthProvider.kakao -> kaKaoOAuthClient.getOAuthAuthorizeCode()
OAuthProvider.kakao -> kakaoOAuthService.getOAuthAuthorizeCode()
}

return OAuthAuthorizeCodeResponse(provider)
}

suspend fun resolveOAuth(provider: OAuthProvider, request: OAuthAuthorizedRequest) {
val response = when (provider) {
OAuthProvider.kakao -> kakaoOAuthService.generateOAuthToken(request.code)
}

println("response > " + response.toJson())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.hero.alignlab.domain.auth.model.request

data class OAuthAuthorizedRequest(
val code: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package com.hero.alignlab.domain.auth.resource
import com.hero.alignlab.common.extension.wrapOk
import com.hero.alignlab.domain.auth.application.OAuthFacade
import com.hero.alignlab.domain.auth.model.OAuthProvider
import com.hero.alignlab.domain.auth.model.request.OAuthAuthorizedRequest
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.*

/**
* - [Kakao Rest Auth](https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api)
*/
@Tag(name = "OAuth 인증 및 인가 관리")
@RestController
@RequestMapping(produces = [MediaType.APPLICATION_JSON_VALUE])
Expand All @@ -20,11 +21,17 @@ class OAuthResource(
/**
* OAuth로 인가코드를 부여받고, 이를 Redirect Url로 반환.
* - redirectUrl은 Client의 주소값, 만약 변경시 yml 및 각 클라이언트 구조 변경 필요.
* - [Kakao Rest Auth](https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api)
*/
@Operation(summary = "인가 코드 받기")
@GetMapping("/api/v1/oauth/{provider}/authorize")
@PostMapping("/api/v1/oauth/{provider}/authorize")
suspend fun getOAuthAuthorizeCode(
@RequestParam provider: OAuthProvider,
@PathVariable provider: OAuthProvider,
) = oAuthFacade.getOAuthAuthorizeCode(provider).wrapOk()

@Operation(summary = "회원가입 또는 로그인 진행")
@PostMapping("/api/v1/oauth/{provider}/authorized")
suspend fun resolveOAuth(
@PathVariable provider: OAuthProvider,
@RequestBody request: OAuthAuthorizedRequest,
) = oAuthFacade.resolveOAuth(provider, request).wrapOk()
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
package com.hero.alignlab.domain.dev.application

import com.hero.alignlab.client.kakao.KakaoOAuthService
import com.hero.alignlab.client.kakao.client.KaKaoOAuthClient
import com.hero.alignlab.client.kakao.config.KakaoOAuthClientConfig
import com.hero.alignlab.client.kakao.model.response.GenerateKakaoOAuthTokenResponse
import com.hero.alignlab.common.extension.toJson
import com.hero.alignlab.domain.auth.model.OAuthProvider
import com.hero.alignlab.domain.auth.model.request.OAuthAuthorizedRequest
import com.hero.alignlab.domain.dev.model.response.DevOAuthCodeResponse
import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.stereotype.Service

@Service
class DevOAuthService(
private val kaKaoOAuthClient: KaKaoOAuthClient,
private val kakaoOAuthService: KakaoOAuthService,
private val config: KakaoOAuthClientConfig.Config,
) {
private val logger = KotlinLogging.logger { }

suspend fun getOAuthAuthorizeCode(provider: OAuthProvider): DevOAuthCodeResponse {
when (provider) {
OAuthProvider.kakao -> kaKaoOAuthClient.getOAuthAuthorizeCode(config.devRedirectUrl)
OAuthProvider.kakao -> kakaoOAuthService.getOAuthAuthorizeCode(config.devRedirectUrl)
}

return DevOAuthCodeResponse(provider)
}

suspend fun resolveOAuth(
provider: OAuthProvider,
request: OAuthAuthorizedRequest
): GenerateKakaoOAuthTokenResponse {
return when (provider) {
OAuthProvider.kakao -> kakaoOAuthService.generateOAuthToken(request.code)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ package com.hero.alignlab.domain.dev.resource

import com.hero.alignlab.common.extension.wrapOk
import com.hero.alignlab.domain.auth.model.OAuthProvider
import com.hero.alignlab.domain.auth.model.request.OAuthAuthorizedRequest
import com.hero.alignlab.domain.dev.application.DevOAuthService
import com.hero.alignlab.domain.dev.model.request.DevRedirectedRequest
import com.hero.alignlab.domain.dev.model.response.DevRedirectedResponse
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springdoc.core.annotations.ParameterObject
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.*

@Tag(name = "Dev OAuth 인증 및 인가 관리")
@RestController
Expand All @@ -21,18 +19,25 @@ class DevOAuthResource(
private val devOAuthService: DevOAuthService,
) {
@Operation(summary = "인가 코드 받기")
@GetMapping("/api/dev/v1/oauth/{provider}/authorize")
@PostMapping("/api/dev/v1/oauth/{provider}/authorize")
suspend fun getDevOAuthAuthorizeCode(
@PathVariable provider: OAuthProvider,
) = devOAuthService.getOAuthAuthorizeCode(provider).wrapOk()

@Operation(summary = "OAuth Redirect Test")
@GetMapping("/api/dev/v1/oauth/{provider}/authorize/redirected")
@PostMapping("/api/dev/v1/oauth/{provider}/authorize/redirected")
suspend fun redirectedDevOAuthAuthorizeCode(
@PathVariable provider: OAuthProvider,
@ParameterObject request: DevRedirectedRequest,
) = DevRedirectedResponse(
provider = provider,
requestParams = request,
).wrapOk()

@Operation(summary = "OAuth Token Generate")
@PostMapping("/api/dev/v1/oauth/{provider}/token")
suspend fun redirectedDevOAuthAuthorizeCode(
@PathVariable provider: OAuthProvider,
@RequestBody request: OAuthAuthorizedRequest,
) = devOAuthService.resolveOAuth(provider, request).wrapOk()
}

0 comments on commit 135447b

Please sign in to comment.