Skip to content
This repository was archived by the owner on Jul 7, 2025. It is now read-only.

Commit 7f01df5

Browse files
committed
ASAP-445 네이버 OAuth 상태(state) 파라미터 추가 및 토큰 요청 로직 리팩토링
1 parent 4bd4c97 commit 7f01df5

10 files changed

Lines changed: 71 additions & 44 deletions

File tree

Application-Module/src/main/kotlin/com/asap/application/user/port/out/AuthInfoRetrievePort.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ interface AuthInfoRetrievePort {
1414
fun getAccessToken(
1515
provider: SocialLoginProvider,
1616
code: String,
17+
state: String,
1718
): String
1819
}

Bootstrap-Module/src/main/kotlin/com/asap/bootstrap/web/auth/controller/AuthController.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,12 @@ class AuthController(
5959
provider: String,
6060
request: OAuthAccessTokenRequest,
6161
): OAuthAccessTokenResponse {
62-
val accessToken = authInfoRetrievePort.getAccessToken(
63-
provider = SocialLoginProvider.valueOf(provider),
64-
code = request.code,
65-
)
62+
val accessToken =
63+
authInfoRetrievePort.getAccessToken(
64+
provider = SocialLoginProvider.valueOf(provider),
65+
code = request.code,
66+
state = request.state,
67+
)
6668
return OAuthAccessTokenResponse(
6769
accessToken = accessToken,
6870
)

Bootstrap-Module/src/main/kotlin/com/asap/bootstrap/web/auth/dto/OAuthAccessTokenRequest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ package com.asap.bootstrap.web.auth.dto
22

33
data class OAuthAccessTokenRequest(
44
val code: String,
5+
val state: String,
56
)

Bootstrap-Module/src/test/kotlin/com/asap/bootstrap/acceptance/auth/controller/AuthControllerTest.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,12 @@ class AuthControllerTest : AcceptanceSupporter() {
124124
// given
125125
val provider = "KAKAO"
126126
val code = "authorization_code"
127-
val request = OAuthAccessTokenRequest(code)
127+
val state = "state"
128+
val request = OAuthAccessTokenRequest(code, state)
128129
val expectedAccessToken = "access_token"
129130

130131
BDDMockito
131-
.given(authInfoRetrievePort.getAccessToken(SocialLoginProvider.valueOf(provider), code))
132+
.given(authInfoRetrievePort.getAccessToken(SocialLoginProvider.valueOf(provider), code, state))
132133
.willReturn(expectedAccessToken)
133134

134135
// when

Infrastructure-Module/Client/src/main/kotlin/com/asap/client/ClientProperties.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ package com.asap.client
33
import org.springframework.boot.context.properties.ConfigurationProperties
44

55
@ConfigurationProperties(prefix = "client")
6-
class ClientProperties {
7-
var oauth: OAuthProperties = OAuthProperties()
8-
}
6+
class ClientProperties(
7+
var oauth: OAuthProperties = OAuthProperties(),
8+
)
99

10-
class OAuthProperties {
11-
var naver: NaverOAuthProperties = NaverOAuthProperties()
12-
}
10+
class OAuthProperties(
11+
var naver: NaverOAuthProperties = NaverOAuthProperties(),
12+
)
1313

14-
class NaverOAuthProperties {
15-
var clientId: String = ""
16-
var clientSecret: String = ""
17-
}
14+
class NaverOAuthProperties(
15+
var clientId: String = "",
16+
var clientSecret: String = "",
17+
)

Infrastructure-Module/Client/src/main/kotlin/com/asap/client/oauth/OAuthInfoRetrieveAdapter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ class OAuthInfoRetrieveAdapter(
3434
override fun getAccessToken(
3535
provider: SocialLoginProvider,
3636
code: String,
37+
state: String,
3738
): String {
3839
val accessTokenResponse =
39-
oAuthRetrieveHandlers[provider]?.getAccessToken(OAuthRetrieveHandler.OAuthGetAccessTokenRequest(code))
40+
oAuthRetrieveHandlers[provider]?.getAccessToken(OAuthRetrieveHandler.OAuthGetAccessTokenRequest(code, state))
4041
?: throw OAuthException.OAuthRetrieveFailedException("OAuth Access Token을 가져오는 핸들러가 존재하지 않습니다.")
4142

4243
return accessTokenResponse.accessToken

Infrastructure-Module/Client/src/main/kotlin/com/asap/client/oauth/OAuthRetrieveHandler.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface OAuthRetrieveHandler {
1919

2020
data class OAuthGetAccessTokenRequest(
2121
val code: String,
22+
val state: String,
2223
)
2324

2425
data class OAuthAccessTokenResponse(

Infrastructure-Module/Client/src/main/kotlin/com/asap/client/oauth/OAuthWebClientConfig.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,13 @@ class OAuthWebClientConfig {
3434
.baseUrl("https://openapi.naver.com")
3535
.defaultHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
3636
.build()
37+
38+
@Bean
39+
@Qualifier("getNaverAccessTokenWebClient")
40+
fun getNaverAccessTokenWebClient(): WebClient =
41+
WebClient
42+
.builder()
43+
.baseUrl("https://nid.naver.com")
44+
.defaultHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
45+
.build()
3746
}

Infrastructure-Module/Client/src/main/kotlin/com/asap/client/oauth/platform/NaverOAuthRetrieveHandler.kt

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,33 @@ import org.springframework.web.util.UriComponentsBuilder
1212
@Component
1313
class NaverOAuthRetrieveHandler(
1414
@Qualifier("naverWebClient") naverWebClient: WebClient,
15+
@Qualifier("getNaverAccessTokenWebClient") val getNaverAccessTokenWebClient: WebClient,
1516
private val clientProperties: ClientProperties,
1617
) : AbstractOAuthRetrieveHandler<NaverOAuthRetrieveHandler.NaverOAuthUserInfoResponse>(naverWebClient) {
1718
private val naverOAuthConfig by lazy { clientProperties.oauth.naver }
1819

1920
override fun getAccessToken(request: OAuthRetrieveHandler.OAuthGetAccessTokenRequest): OAuthRetrieveHandler.OAuthAccessTokenResponse {
20-
val accessTokenUri =
21+
val accessTokenUrl =
2122
NaverAccessTokenRequest(
2223
grantType = "authorization_code",
2324
clientId = naverOAuthConfig.clientId,
2425
clientSecret = naverOAuthConfig.clientSecret,
2526
code = request.code,
26-
).toUriComponents("/oauth2/token")
27+
).toUriComponents("/oauth2.0/token")
2728

2829
val response =
29-
webClient
30+
getNaverAccessTokenWebClient
3031
.get()
31-
.uri(accessTokenUri)
32+
.uri(accessTokenUrl)
3233
.retrieve()
3334
.bodyToMono(NaverAccessTokenResponse::class.java)
3435
.block()
3536
?: throw OAuthException.OAuthRetrieveFailedException(getErrorMessage())
3637

37-
return OAuthRetrieveHandler.OAuthAccessTokenResponse(response.accessToken, response.tokenType)
38+
return OAuthRetrieveHandler.OAuthAccessTokenResponse(
39+
accessToken = response.accessToken,
40+
refreshToken = response.tokenType,
41+
)
3842
}
3943

4044
override fun getApiEndpoint(): String = "/v1/nid/me"
@@ -45,10 +49,10 @@ class NaverOAuthRetrieveHandler(
4549

4650
override fun mapToOAuthResponse(response: NaverOAuthUserInfoResponse): OAuthRetrieveHandler.OAuthResponse =
4751
OAuthRetrieveHandler.OAuthResponse(
48-
username = response.response.nickname,
52+
username = "",
4953
socialId = response.response.id,
5054
email = response.response.email,
51-
profileImage = response.response.profile_image,
55+
profileImage = "",
5256
)
5357

5458
data class NaverOAuthUserInfoResponse(
@@ -59,29 +63,18 @@ class NaverOAuthRetrieveHandler(
5963

6064
data class NaverUserResponse(
6165
val id: String,
62-
val nickname: String,
63-
val name: String,
6466
val email: String,
65-
val gender: String,
66-
val age: String,
67-
val birthday: String,
68-
val profile_image: String,
69-
val birthyear: String,
70-
val mobile: String,
7167
)
7268

7369
data class NaverAccessTokenRequest(
74-
@JsonProperty("grant_type")
7570
val grantType: String,
76-
@JsonProperty("client_id")
7771
val clientId: String,
78-
@JsonProperty("client_secret")
7972
val clientSecret: String,
8073
val code: String,
8174
) {
82-
fun toUriComponents(baseUri: String): String =
75+
fun toUriComponents(basePath: String): String =
8376
UriComponentsBuilder
84-
.fromPath(baseUri)
77+
.fromPath(basePath)
8578
.queryParam("grant_type", grantType)
8679
.queryParam("client_id", clientId)
8780
.queryParam("client_secret", clientSecret)
@@ -90,9 +83,13 @@ class NaverOAuthRetrieveHandler(
9083
}
9184

9285
data class NaverAccessTokenResponse(
86+
@JsonProperty("access_token")
9387
val accessToken: String,
88+
@JsonProperty("refresh_token")
9489
val refreshToken: String,
90+
@JsonProperty("token_type")
9591
val tokenType: String,
92+
@JsonProperty("expires_in")
9693
val expiresIn: Int,
9794
)
9895
}

Infrastructure-Module/Client/src/test/kotlin/com/asap/client/oauth/platform/NaverOAuthRetrieveHandlerTest.kt

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.asap.client.oauth.platform
22

3+
import com.asap.client.ClientProperties
4+
import com.asap.client.NaverOAuthProperties
5+
import com.asap.client.OAuthProperties
36
import com.asap.client.oauth.OAuthRetrieveHandler
47
import com.asap.client.oauth.exception.OAuthException
58
import io.kotest.assertions.throwables.shouldThrow
@@ -12,16 +15,29 @@ import org.springframework.web.reactive.function.client.WebClient
1215

1316
class NaverOAuthRetrieveHandlerTest :
1417
BehaviorSpec({
15-
var mockWebServer = MockWebServer().also {
16-
it.start()
17-
}
18+
var mockWebServer =
19+
MockWebServer().also {
20+
it.start()
21+
}
1822
var naverWebClient: WebClient =
1923
WebClient
2024
.builder()
2125
.baseUrl(mockWebServer.url("/").toString())
2226
.defaultHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
2327
.build()
24-
var naverOAuthRetrieveHandler = NaverOAuthRetrieveHandler(naverWebClient)
28+
29+
val config =
30+
ClientProperties(
31+
oauth =
32+
OAuthProperties(
33+
naver =
34+
NaverOAuthProperties(
35+
clientId = "test-client-id",
36+
clientSecret = "test-client-secret",
37+
),
38+
),
39+
)
40+
var naverOAuthRetrieveHandler = NaverOAuthRetrieveHandler(naverWebClient, naverWebClient, config)
2541

2642
given("OAuth 요청이 성공적으로 처리되었을 때") {
2743
val accessToken = "test-access-token"
@@ -58,10 +74,8 @@ class NaverOAuthRetrieveHandlerTest :
5874
val response = naverOAuthRetrieveHandler.getOAuthInfo(request)
5975

6076
then("올바른 OAuthResponse를 반환해야 한다") {
61-
response.username shouldBe "Test User"
6277
response.socialId shouldBe "12345"
6378
response.email shouldBe "test@example.com"
64-
response.profileImage shouldBe "https://example.com/profile.jpg"
6579

6680
// 요청 검증
6781
val recordedRequest = mockWebServer.takeRequest()
@@ -110,4 +124,4 @@ class NaverOAuthRetrieveHandlerTest :
110124
}
111125
}
112126
}
113-
})
127+
})

0 commit comments

Comments
 (0)