구글 로그인 추가

This commit is contained in:
2025-04-04 13:21:49 +09:00
parent 1bbaf8f7b7
commit 5598bca8d3
12 changed files with 208 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
package kr.co.vividnext.sodalive.member.social
import kr.co.vividnext.sodalive.member.login.LoginResponse
data class SocialLoginResponse(
val memberId: Long,
val marketingPid: String?,
val loginResponse: LoginResponse
)

View File

@@ -0,0 +1,54 @@
package kr.co.vividnext.sodalive.member.social.google
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.jwt.TokenProvider
import kr.co.vividnext.sodalive.member.MemberAdapter
import kr.co.vividnext.sodalive.member.MemberService
import kr.co.vividnext.sodalive.member.login.LoginResponse
import kr.co.vividnext.sodalive.member.social.SocialLoginResponse
import org.springframework.beans.factory.annotation.Value
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.stereotype.Service
@Service
class GoogleAuthService(
private val googleService: GoogleService,
private val memberService: MemberService,
private val tokenProvider: TokenProvider,
@Value("\${cloud.aws.cloud-front.host}")
private val cloudFrontHost: String
) {
fun authenticate(idToken: String, container: String, marketingPid: String?): SocialLoginResponse {
val googleUserInfo = googleService.getUserInfo(idToken)
?: throw SodaException("구글 로그인을 하지 못했습니다. 다시 시도해 주세요")
val member = memberService.findOrRegister(googleUserInfo, container, marketingPid)
val principal = MemberAdapter(member)
val authToken = GoogleAuthenticationToken(idToken, principal.authorities)
authToken.setPrincipal(principal)
SecurityContextHolder.getContext().authentication = authToken
val jwt = tokenProvider.createToken(
authentication = authToken,
memberId = member.id!!
)
val loginResponse = LoginResponse(
userId = member.id!!,
token = jwt,
nickname = member.nickname,
email = member.email,
profileImage = if (member.profileImage != null) {
"$cloudFrontHost/${member.profileImage}"
} else {
"$cloudFrontHost/profile/default-profile.png"
}
)
return SocialLoginResponse(
memberId = member.id!!,
marketingPid = marketingPid,
loginResponse = loginResponse
)
}
}

View File

@@ -0,0 +1,15 @@
package kr.co.vividnext.sodalive.member.social.google
import org.springframework.security.authentication.AbstractAuthenticationToken
import org.springframework.security.core.GrantedAuthority
class GoogleAuthenticationToken(
private val idToken: String,
authorities: Collection<GrantedAuthority>? = null
) : AbstractAuthenticationToken(authorities) {
private var principal: Any? = null
init { isAuthenticated = authorities != null }
override fun getCredentials(): Any = idToken
override fun getPrincipal(): Any? = principal
fun setPrincipal(principal: Any) { this.principal = principal }
}

View File

@@ -0,0 +1,45 @@
package kr.co.vividnext.sodalive.member.social.google
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
import com.google.api.client.json.gson.GsonFactory
import kr.co.vividnext.sodalive.common.SodaException
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
@Service
class GoogleService(
@Value("\${google.web-client-id}")
private val googleWebClientId: String
) {
private val transport = GoogleNetHttpTransport.newTrustedTransport()
private val jsonFactory = GsonFactory.getDefaultInstance()
private val clientIds = listOf(googleWebClientId)
fun getUserInfo(idToken: String): GoogleUserInfo? {
val verifier = GoogleIdTokenVerifier.Builder(transport, jsonFactory)
.setAudience(clientIds)
.setIssuers(listOf("accounts.google.com", "https://accounts.google.com"))
.build()
return try {
val token = verifier.verify(idToken)
if (token != null) {
val payload = token.payload
val email = payload.email ?: throw SodaException("이메일 제공에 동의하셔야 서비스 이용이 가능합니다.")
GoogleUserInfo(
sub = payload.subject,
email = email,
name = payload["name"] as? String
)
} else {
null
}
} catch (e: Exception) {
e.printStackTrace()
null
}
}
}

View File

@@ -0,0 +1,7 @@
package kr.co.vividnext.sodalive.member.social.google
data class GoogleUserInfo(
val sub: String,
val email: String,
val name: String?
)