소셜 로그인 리졸버 도입
This commit is contained in:
@@ -13,8 +13,7 @@ import kr.co.vividnext.sodalive.member.login.LoginResponse
|
|||||||
import kr.co.vividnext.sodalive.member.login.SocialLoginRequest
|
import kr.co.vividnext.sodalive.member.login.SocialLoginRequest
|
||||||
import kr.co.vividnext.sodalive.member.notification.UpdateNotificationSettingRequest
|
import kr.co.vividnext.sodalive.member.notification.UpdateNotificationSettingRequest
|
||||||
import kr.co.vividnext.sodalive.member.signUp.SignUpRequestV2
|
import kr.co.vividnext.sodalive.member.signUp.SignUpRequestV2
|
||||||
import kr.co.vividnext.sodalive.member.social.google.GoogleAuthService
|
import kr.co.vividnext.sodalive.member.social.SocialAuthServiceResolver
|
||||||
import kr.co.vividnext.sodalive.member.social.kakao.KakaoAuthService
|
|
||||||
import kr.co.vividnext.sodalive.useraction.ActionType
|
import kr.co.vividnext.sodalive.useraction.ActionType
|
||||||
import kr.co.vividnext.sodalive.useraction.UserActionService
|
import kr.co.vividnext.sodalive.useraction.UserActionService
|
||||||
import org.springframework.data.domain.Pageable
|
import org.springframework.data.domain.Pageable
|
||||||
@@ -36,8 +35,7 @@ import org.springframework.web.multipart.MultipartFile
|
|||||||
@RequestMapping("/member")
|
@RequestMapping("/member")
|
||||||
class MemberController(
|
class MemberController(
|
||||||
private val service: MemberService,
|
private val service: MemberService,
|
||||||
private val kakaoAuthService: KakaoAuthService,
|
private val socialAuthServiceResolver: SocialAuthServiceResolver,
|
||||||
private val googleAuthService: GoogleAuthService,
|
|
||||||
private val trackingService: AdTrackingService,
|
private val trackingService: AdTrackingService,
|
||||||
private val userActionService: UserActionService,
|
private val userActionService: UserActionService,
|
||||||
private val messageSource: SodaMessageSource,
|
private val messageSource: SodaMessageSource,
|
||||||
@@ -345,31 +343,7 @@ class MemberController(
|
|||||||
@RequestHeader("Authorization") authHeader: String,
|
@RequestHeader("Authorization") authHeader: String,
|
||||||
@RequestBody request: SocialLoginRequest
|
@RequestBody request: SocialLoginRequest
|
||||||
): ApiResponse<LoginResponse> {
|
): ApiResponse<LoginResponse> {
|
||||||
if (!authHeader.startsWith("Bearer ")) {
|
return processSocialLogin(MemberProvider.GOOGLE, authHeader, request)
|
||||||
throw SodaException(messageKey = "member.social.google_login_failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
val token = authHeader.substring(7)
|
|
||||||
val response = googleAuthService.authenticate(token, request.container, request.marketingPid, request.pushToken)
|
|
||||||
|
|
||||||
if (!response.marketingPid.isNullOrBlank()) {
|
|
||||||
trackingService.saveTrackingHistory(
|
|
||||||
pid = response.marketingPid,
|
|
||||||
type = AdTrackingHistoryType.SIGNUP,
|
|
||||||
memberId = response.memberId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.isNew) {
|
|
||||||
userActionService.recordAction(
|
|
||||||
memberId = response.memberId,
|
|
||||||
isAuth = false,
|
|
||||||
actionType = ActionType.SIGN_UP
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val message = messageSource.getMessage("member.signup.success", langContext.lang)
|
|
||||||
return ApiResponse.ok(message = message, data = response.loginResponse)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/login/kakao")
|
@PostMapping("/login/kakao")
|
||||||
@@ -377,12 +351,27 @@ class MemberController(
|
|||||||
@RequestHeader("Authorization") authHeader: String,
|
@RequestHeader("Authorization") authHeader: String,
|
||||||
@RequestBody request: SocialLoginRequest
|
@RequestBody request: SocialLoginRequest
|
||||||
): ApiResponse<LoginResponse> {
|
): ApiResponse<LoginResponse> {
|
||||||
|
return processSocialLogin(MemberProvider.KAKAO, authHeader, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processSocialLogin(
|
||||||
|
provider: MemberProvider,
|
||||||
|
authHeader: String,
|
||||||
|
request: SocialLoginRequest
|
||||||
|
): ApiResponse<LoginResponse> {
|
||||||
|
val errorKey = when (provider) {
|
||||||
|
MemberProvider.GOOGLE -> "member.social.google_login_failed"
|
||||||
|
MemberProvider.KAKAO -> "member.social.kakao_login_failed"
|
||||||
|
else -> "common.error.bad_request"
|
||||||
|
}
|
||||||
|
|
||||||
if (!authHeader.startsWith("Bearer ")) {
|
if (!authHeader.startsWith("Bearer ")) {
|
||||||
throw SodaException(messageKey = "member.social.kakao_login_failed")
|
throw SodaException(messageKey = errorKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
val token = authHeader.substring(7)
|
val token = authHeader.substring(7)
|
||||||
val response = kakaoAuthService.authenticate(token, request.container, request.marketingPid, request.pushToken)
|
val authService = socialAuthServiceResolver.resolve(provider)
|
||||||
|
val response = authService.authenticate(token, request.container, request.marketingPid, request.pushToken)
|
||||||
|
|
||||||
if (!response.marketingPid.isNullOrBlank()) {
|
if (!response.marketingPid.isNullOrBlank()) {
|
||||||
trackingService.saveTrackingHistory(
|
trackingService.saveTrackingHistory(
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package kr.co.vividnext.sodalive.member.social
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberProvider
|
||||||
|
|
||||||
|
interface SocialAuthService {
|
||||||
|
fun getProvider(): MemberProvider
|
||||||
|
fun authenticate(
|
||||||
|
token: String,
|
||||||
|
container: String,
|
||||||
|
marketingPid: String?,
|
||||||
|
pushToken: String?
|
||||||
|
): SocialLoginResponse
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package kr.co.vividnext.sodalive.member.social
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberProvider
|
||||||
|
import org.springframework.stereotype.Component
|
||||||
|
|
||||||
|
@Component
|
||||||
|
class SocialAuthServiceResolver(
|
||||||
|
val services: List<SocialAuthService>
|
||||||
|
) {
|
||||||
|
private val serviceMap: Map<MemberProvider, SocialAuthService> = services.associateBy { it.getProvider() }
|
||||||
|
|
||||||
|
fun resolve(provider: MemberProvider): SocialAuthService {
|
||||||
|
return serviceMap[provider] ?: throw IllegalArgumentException("Unsupported social provider: $provider")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,10 @@ package kr.co.vividnext.sodalive.member.social.google
|
|||||||
import kr.co.vividnext.sodalive.common.SodaException
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
import kr.co.vividnext.sodalive.jwt.TokenProvider
|
import kr.co.vividnext.sodalive.jwt.TokenProvider
|
||||||
import kr.co.vividnext.sodalive.member.MemberAdapter
|
import kr.co.vividnext.sodalive.member.MemberAdapter
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberProvider
|
||||||
import kr.co.vividnext.sodalive.member.MemberService
|
import kr.co.vividnext.sodalive.member.MemberService
|
||||||
import kr.co.vividnext.sodalive.member.login.LoginResponse
|
import kr.co.vividnext.sodalive.member.login.LoginResponse
|
||||||
|
import kr.co.vividnext.sodalive.member.social.SocialAuthService
|
||||||
import kr.co.vividnext.sodalive.member.social.SocialLoginResponse
|
import kr.co.vividnext.sodalive.member.social.SocialLoginResponse
|
||||||
import org.springframework.beans.factory.annotation.Value
|
import org.springframework.beans.factory.annotation.Value
|
||||||
import org.springframework.security.core.context.SecurityContextHolder
|
import org.springframework.security.core.context.SecurityContextHolder
|
||||||
@@ -18,19 +20,21 @@ class GoogleAuthService(
|
|||||||
|
|
||||||
@Value("\${cloud.aws.cloud-front.host}")
|
@Value("\${cloud.aws.cloud-front.host}")
|
||||||
private val cloudFrontHost: String
|
private val cloudFrontHost: String
|
||||||
) {
|
) : SocialAuthService {
|
||||||
fun authenticate(
|
override fun getProvider(): MemberProvider = MemberProvider.GOOGLE
|
||||||
idToken: String,
|
|
||||||
|
override fun authenticate(
|
||||||
|
token: String,
|
||||||
container: String,
|
container: String,
|
||||||
marketingPid: String?,
|
marketingPid: String?,
|
||||||
pushToken: String?
|
pushToken: String?
|
||||||
): SocialLoginResponse {
|
): SocialLoginResponse {
|
||||||
val googleUserInfo = googleService.getUserInfo(idToken)
|
val googleUserInfo = googleService.getUserInfo(token)
|
||||||
?: throw SodaException(messageKey = "member.social.google_login_failed")
|
?: throw SodaException(messageKey = "member.social.google_login_failed")
|
||||||
val memberResolveResult = memberService.findOrRegister(googleUserInfo, container, marketingPid, pushToken)
|
val memberResolveResult = memberService.findOrRegister(googleUserInfo, container, marketingPid, pushToken)
|
||||||
val member = memberResolveResult.member
|
val member = memberResolveResult.member
|
||||||
val principal = MemberAdapter(member)
|
val principal = MemberAdapter(member)
|
||||||
val authToken = GoogleAuthenticationToken(idToken, principal.authorities)
|
val authToken = GoogleAuthenticationToken(token, principal.authorities)
|
||||||
authToken.setPrincipal(principal)
|
authToken.setPrincipal(principal)
|
||||||
SecurityContextHolder.getContext().authentication = authToken
|
SecurityContextHolder.getContext().authentication = authToken
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package kr.co.vividnext.sodalive.member.social.kakao
|
|||||||
import kr.co.vividnext.sodalive.common.SodaException
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
import kr.co.vividnext.sodalive.jwt.TokenProvider
|
import kr.co.vividnext.sodalive.jwt.TokenProvider
|
||||||
import kr.co.vividnext.sodalive.member.MemberAdapter
|
import kr.co.vividnext.sodalive.member.MemberAdapter
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberProvider
|
||||||
import kr.co.vividnext.sodalive.member.MemberService
|
import kr.co.vividnext.sodalive.member.MemberService
|
||||||
import kr.co.vividnext.sodalive.member.login.LoginResponse
|
import kr.co.vividnext.sodalive.member.login.LoginResponse
|
||||||
|
import kr.co.vividnext.sodalive.member.social.SocialAuthService
|
||||||
import kr.co.vividnext.sodalive.member.social.SocialLoginResponse
|
import kr.co.vividnext.sodalive.member.social.SocialLoginResponse
|
||||||
import org.springframework.beans.factory.annotation.Value
|
import org.springframework.beans.factory.annotation.Value
|
||||||
import org.springframework.security.core.context.SecurityContextHolder
|
import org.springframework.security.core.context.SecurityContextHolder
|
||||||
@@ -18,19 +20,21 @@ class KakaoAuthService(
|
|||||||
|
|
||||||
@Value("\${cloud.aws.cloud-front.host}")
|
@Value("\${cloud.aws.cloud-front.host}")
|
||||||
private val cloudFrontHost: String
|
private val cloudFrontHost: String
|
||||||
) {
|
) : SocialAuthService {
|
||||||
fun authenticate(
|
override fun getProvider(): MemberProvider = MemberProvider.KAKAO
|
||||||
accessToken: String,
|
|
||||||
|
override fun authenticate(
|
||||||
|
token: String,
|
||||||
container: String,
|
container: String,
|
||||||
marketingPid: String?,
|
marketingPid: String?,
|
||||||
pushToken: String?
|
pushToken: String?
|
||||||
): SocialLoginResponse {
|
): SocialLoginResponse {
|
||||||
val kakaoUserInfo = kakaoService.getUserInfo(accessToken)
|
val kakaoUserInfo = kakaoService.getUserInfo(token)
|
||||||
?: throw SodaException(messageKey = "member.social.kakao_login_failed")
|
?: throw SodaException(messageKey = "member.social.kakao_login_failed")
|
||||||
val memberResolveResult = memberService.findOrRegister(kakaoUserInfo, container, marketingPid, pushToken)
|
val memberResolveResult = memberService.findOrRegister(kakaoUserInfo, container, marketingPid, pushToken)
|
||||||
val member = memberResolveResult.member
|
val member = memberResolveResult.member
|
||||||
val principal = MemberAdapter(member)
|
val principal = MemberAdapter(member)
|
||||||
val authToken = KakaoAuthenticationToken(accessToken, principal.authorities)
|
val authToken = KakaoAuthenticationToken(token, principal.authorities)
|
||||||
authToken.setPrincipal(principal)
|
authToken.setPrincipal(principal)
|
||||||
SecurityContextHolder.getContext().authentication = authToken
|
SecurityContextHolder.getContext().authentication = authToken
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user