-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* chore : 애플 프라이빗 키 추가 * feat : 애플 API Client 구현 * feat : 애플 API 요청 시 필요한 support 클래스 * feat : 애플 API 통신 시 필요 dto * feat : 애플 관련 yml 프로퍼티 클래스 * feat : RestTemplate 빈 등록 * feat : 로그인 서비스 애플 타입 구현 * feat : out-web 모듈 jwt 의존성 추가 * feat : 애플 api 관련 에러코드 추가 * refactor : idToken 요청하는 rest 호출 코드 제거 * refactor : 로그인 요청 dto 네이밍 변경 * refactor : 네이밍 변경에 따른 테스트 수정 * refactor : 엘비스 연산자 컨벤션
- Loading branch information
1 parent
195880d
commit d419332
Showing
13 changed files
with
169 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
adapters/out-web/src/main/kotlin/com/pokit/auth/common/config/RestTemplateConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.pokit.auth.common.config | ||
|
||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.web.client.RestTemplate | ||
|
||
@Configuration | ||
class RestTemplateConfig { | ||
@Bean | ||
fun restTemplate() = RestTemplate() | ||
} |
10 changes: 10 additions & 0 deletions
10
adapters/out-web/src/main/kotlin/com/pokit/auth/common/dto/ApplePublicKey.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.pokit.auth.common.dto | ||
|
||
data class ApplePublicKey( | ||
val kty: String, | ||
val kid: String, | ||
val use: String, | ||
val alg: String, | ||
val n: String, | ||
val e: String, | ||
) |
11 changes: 11 additions & 0 deletions
11
adapters/out-web/src/main/kotlin/com/pokit/auth/common/dto/ApplePublicKeys.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.pokit.auth.common.dto | ||
|
||
data class ApplePublicKeys( | ||
val keys: List<ApplePublicKey>, | ||
) { | ||
fun getMatchedKey(alg: String, kid: String): ApplePublicKey? { | ||
return keys.firstOrNull { key -> | ||
key.alg == alg && key.kid == kid | ||
} | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
adapters/out-web/src/main/kotlin/com/pokit/auth/common/support/AppleKeyGenerator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.pokit.auth.common.support | ||
|
||
import com.pokit.auth.common.dto.ApplePublicKey | ||
import com.pokit.auth.common.dto.ApplePublicKeys | ||
import com.pokit.common.exception.ClientValidationException | ||
import com.pokit.token.exception.AuthErrorCode | ||
import org.springframework.stereotype.Component | ||
import java.math.BigInteger | ||
import java.security.KeyFactory | ||
import java.security.PublicKey | ||
import java.security.spec.RSAPublicKeySpec | ||
import java.util.Base64 | ||
|
||
@Component | ||
class AppleKeyGenerator { | ||
fun generatePublicKey(headers: Map<String, String>, publicKeys: ApplePublicKeys): PublicKey { | ||
val alg = headers["alg"] | ||
?: throw ClientValidationException(AuthErrorCode.INVALID_ID_TOKEN) | ||
val kid = headers["kid"] | ||
?: throw ClientValidationException(AuthErrorCode.INVALID_ID_TOKEN) | ||
val publicKey = publicKeys.getMatchedKey(alg, kid) ?: throw ClientValidationException(AuthErrorCode.INVALID_ID_TOKEN) | ||
|
||
return getPublicKey(publicKey) | ||
} | ||
|
||
private fun getPublicKey(publicKey: ApplePublicKey): PublicKey { | ||
val nBytes = Base64.getUrlDecoder().decode(publicKey.n) | ||
val eBytes = Base64.getUrlDecoder().decode(publicKey.e) | ||
|
||
val publicKeySpec = RSAPublicKeySpec(BigInteger(1, nBytes), BigInteger(1, eBytes)) | ||
|
||
val keyFactory = KeyFactory.getInstance(publicKey.kty) | ||
return keyFactory.generatePublic(publicKeySpec) | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
adapters/out-web/src/main/kotlin/com/pokit/auth/common/support/AppleTokenParser.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.pokit.auth.common.support | ||
|
||
import com.fasterxml.jackson.core.type.TypeReference | ||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import io.jsonwebtoken.Claims | ||
import io.jsonwebtoken.Jwts | ||
import org.springframework.stereotype.Component | ||
import java.nio.charset.StandardCharsets | ||
import java.security.PublicKey | ||
import java.util.* | ||
|
||
@Component | ||
class AppleTokenParser( | ||
private val objectMapper: ObjectMapper | ||
) { | ||
private val typeReference = object : TypeReference<Map<String, String>>() {} | ||
|
||
fun parseHeader(idToken: String): Map<String, String> { | ||
val header = idToken.split("\\.")[0] | ||
val decodedHeader = String(Base64.getDecoder().decode(header), StandardCharsets.UTF_8) | ||
return objectMapper.readValue(decodedHeader, typeReference) | ||
} | ||
|
||
fun parseClaims(idToken: String, publicKey: PublicKey): Claims { | ||
return Jwts.parser() | ||
.verifyWith(publicKey) | ||
.build() | ||
.parseSignedClaims(idToken) | ||
.payload | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
adapters/out-web/src/main/kotlin/com/pokit/auth/impl/AppleApiAdapter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.pokit.auth.impl | ||
|
||
import com.pokit.auth.common.dto.ApplePublicKeys | ||
import com.pokit.auth.common.support.AppleKeyGenerator | ||
import com.pokit.auth.common.support.AppleTokenParser | ||
import com.pokit.auth.port.out.AppleApiClient | ||
import com.pokit.user.dto.UserInfo | ||
import org.springframework.stereotype.Component | ||
import org.springframework.web.client.RestTemplate | ||
import org.springframework.web.util.UriComponentsBuilder | ||
|
||
|
||
@Component | ||
class AppleApiAdapter( | ||
private val restTemplate: RestTemplate, | ||
private val appleKeyGenerator: AppleKeyGenerator, | ||
private val appleTokenParser: AppleTokenParser | ||
) : AppleApiClient{ | ||
override fun getUserInfo(idToken: String): UserInfo { | ||
val claims = decodeAndVerifyIdToken(idToken) // id token을 통해 사용자 정보 추출 | ||
val email = claims["email"] as String | ||
|
||
return UserInfo(email = email) | ||
} | ||
|
||
// 애플에게 공개 키 요청 후 공개키로 idToken 내 고객 정보 추출 | ||
private fun decodeAndVerifyIdToken(idToken: String): Map<String, Any> { | ||
val appleKeyUrl = "https://appleid.apple.com/auth/keys" | ||
val url = UriComponentsBuilder | ||
.fromUriString(appleKeyUrl) | ||
.encode() | ||
.build() | ||
.toUri() | ||
|
||
val publicKeys = restTemplate.getForObject( | ||
url, | ||
ApplePublicKeys::class.java | ||
) | ||
|
||
val header = appleTokenParser.parseHeader(idToken) | ||
val publicKey = appleKeyGenerator.generatePublicKey(header, publicKeys) | ||
val claims = appleTokenParser.parseClaims(idToken, publicKey) | ||
return claims | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
application/src/main/kotlin/com/pokit/auth/port/out/AppleApiClient.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.pokit.auth.port.out | ||
|
||
import com.pokit.user.dto.UserInfo | ||
|
||
interface AppleApiClient { | ||
fun getUserInfo(idToken: String): UserInfo | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,11 +2,11 @@ package com.pokit.auth.port.service | |
|
||
import com.pokit.auth.port.`in`.AuthUseCase | ||
import com.pokit.auth.port.`in`.TokenProvider | ||
import com.pokit.auth.port.out.AppleApiClient | ||
import com.pokit.auth.port.out.GoogleApiClient | ||
import com.pokit.token.dto.request.SignInRequest | ||
import com.pokit.token.model.AuthPlatform | ||
import com.pokit.token.model.Token | ||
import com.pokit.user.dto.UserInfo | ||
import com.pokit.user.model.Role | ||
import com.pokit.user.model.User | ||
import com.pokit.user.port.out.UserPort | ||
|
@@ -15,6 +15,7 @@ import org.springframework.stereotype.Service | |
@Service | ||
class AuthService( | ||
private val googleApiClient: GoogleApiClient, | ||
private val appleApiClient: AppleApiClient, | ||
private val tokenProvider: TokenProvider, | ||
private val userPort: UserPort, | ||
) : AuthUseCase { | ||
|
@@ -23,8 +24,8 @@ class AuthService( | |
|
||
val userInfo = | ||
when (platformType) { | ||
AuthPlatform.GOOGLE -> googleApiClient.getUserInfo(request.authorizationCode) | ||
AuthPlatform.APPLE -> UserInfo("[email protected]") // TODO | ||
AuthPlatform.GOOGLE -> googleApiClient.getUserInfo(request.idToken) | ||
AuthPlatform.APPLE -> appleApiClient.getUserInfo(request.idToken) | ||
} | ||
|
||
val userEmail = userInfo.email | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters