From 0371bea94c5dc3ca4422ac589b1ccf1791b200a0 Mon Sep 17 00:00:00 2001 From: Junghoon Kim Date: Wed, 8 Jan 2025 12:15:30 +0900 Subject: [PATCH] :sparkles: created CustomAuthenticationSuccessHandler --- .../CustomAuthenticationSuccessHandler.kt | 79 +++++++++++++++++++ .../service/SocialLoginUserService.kt | 12 +-- .../karrot/user/persistence/NormalUser.kt | 4 +- 3 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 src/main/kotlin/com/toyProject7/karrot/socialLogin/handler/CustomAuthenticationSuccessHandler.kt diff --git a/src/main/kotlin/com/toyProject7/karrot/socialLogin/handler/CustomAuthenticationSuccessHandler.kt b/src/main/kotlin/com/toyProject7/karrot/socialLogin/handler/CustomAuthenticationSuccessHandler.kt new file mode 100644 index 0000000..3d6e2ca --- /dev/null +++ b/src/main/kotlin/com/toyProject7/karrot/socialLogin/handler/CustomAuthenticationSuccessHandler.kt @@ -0,0 +1,79 @@ +package com.toyProject7.karrot.socialLogin.handler + +import com.fasterxml.jackson.databind.ObjectMapper +import com.toyProject7.karrot.socialLogin.OAuth2AuthenticationException +import com.toyProject7.karrot.user.UserAccessTokenUtil +import com.toyProject7.karrot.user.service.UserService +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import org.springframework.security.core.Authentication +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken +import org.springframework.security.oauth2.core.user.OAuth2User +import org.springframework.security.web.authentication.AuthenticationSuccessHandler +import org.springframework.stereotype.Component + +@Component +class CustomAuthenticationSuccessHandler( + private val userService: UserService +) : AuthenticationSuccessHandler { + + override fun onAuthenticationSuccess( + request: HttpServletRequest, response: HttpServletResponse, authentication: Authentication + ) { + val oauth2User = authentication.principal as OAuth2User + val oauth2Token = authentication as OAuth2AuthenticationToken + val provider = oauth2Token.authorizedClientRegistrationId + + // Extract attributes + val attributes = oauth2User.attributes + val providerId = extractProviderId(attributes, provider) + val email = extractEmail(attributes, provider) + val name = extractName(attributes, provider) + + // Create or retrieve the user + val user = userService.createOrRetrieveSocialUser(email, providerId, provider, name) + + // Generate JWT + val accessToken = UserAccessTokenUtil.generateAccessToken(user.id) + + // Send the JWT in the response body as JSON + val responseBody = mapOf("accessToken" to accessToken, "user" to user) + response.contentType = "application/json" + response.characterEncoding = "UTF-8" + response.writer.write(ObjectMapper().writeValueAsString(responseBody)) + } + + private fun extractProviderId(attributes: Map, provider: String): String { + return when (provider) { + "google" -> attributes["sub"] as String + "naver" -> (attributes["response"] as Map)["id"] as String + "kakao" -> attributes["id"].toString() // Kakao's id may be Long, convert to String + else -> throw OAuth2AuthenticationException() + } + } + + private fun extractEmail(attributes: Map, provider: String): String { + return when (provider) { + "google" -> attributes["email"] as String + "naver" -> (attributes["response"] as Map)["email"] as String + "kakao" -> { + val kakaoAccount = attributes["kakao_account"] as Map + kakaoAccount["email"] as String + } + else -> throw OAuth2AuthenticationException() + } + } + + private fun extractName(attributes: Map, provider: String): String { + return when (provider) { + "google" -> attributes["name"] as String + "naver" -> (attributes["response"] as Map)["name"] as String + "kakao" -> { + val kakaoAccount = attributes["kakao_account"] as Map + val profile = kakaoAccount["profile"] as Map + profile["nickname"] as String + } + else -> "Unknown" + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/toyProject7/karrot/socialLogin/service/SocialLoginUserService.kt b/src/main/kotlin/com/toyProject7/karrot/socialLogin/service/SocialLoginUserService.kt index b88c94a..e2b3b24 100644 --- a/src/main/kotlin/com/toyProject7/karrot/socialLogin/service/SocialLoginUserService.kt +++ b/src/main/kotlin/com/toyProject7/karrot/socialLogin/service/SocialLoginUserService.kt @@ -15,16 +15,6 @@ class SocialLoginUserService(private val userService: UserService) : OAuth2UserS override fun loadUser(userRequest: OAuth2UserRequest): OAuth2User { // Load the user details from the OAuth2 provider - val oauth2User = oAuth2UserService.loadUser(userRequest) - - // Extract attributes - val provider = userRequest.clientRegistration.registrationId - val email = oauth2User.getAttribute("email") ?: throw OAuth2AuthenticationException() - val providerId = oauth2User.getAttribute("sub") ?: throw OAuth2AuthenticationException() - val name = oauth2User.getAttribute("name") ?: throw OAuth2AuthenticationException() - - // Create or retrieve the user - userService.createOrRetrieveSocialUser(email, providerId, provider, name) - return oauth2User + return oAuth2UserService.loadUser(userRequest) } } \ No newline at end of file diff --git a/src/main/kotlin/com/toyProject7/karrot/user/persistence/NormalUser.kt b/src/main/kotlin/com/toyProject7/karrot/user/persistence/NormalUser.kt index 0b29731..3f8000e 100644 --- a/src/main/kotlin/com/toyProject7/karrot/user/persistence/NormalUser.kt +++ b/src/main/kotlin/com/toyProject7/karrot/user/persistence/NormalUser.kt @@ -12,9 +12,9 @@ class NormalUser( temperature: Double, email: String, - @Column(name = "user_id", nullable = false) + @Column(name = "user_id") var userId: String, - @Column(name = "hashed_password", nullable = false) + @Column(name = "hashed_password") var hashedPassword: String, ) : UserEntity(nickname = nickname, location = location, temperature = temperature, email = email) { // Additional attributes and methods for normal users can go here