본문 바로가기

카테고리 없음

트러블슈팅: 일반 로그인을 카카오톡 소셜로그인으로 변경하면서 userprincipal 사용시 userID 대신 providerID로 인식 문제 발생

문제:

 

소셜 로그인이 완성되기전엔 임시로 user를 직접 만들어서 userid를 통해 로그인을 하도록 하고 있었는데, 팀원이 카카오  소셜로그인을 완성하자 소셜아이디로 연결을 시켜놨는데, userprincipal이 소셜로그인을 했을시 생성되는 userid가 아닌 카카오가 발급해준 providerid만을 인식해서 그런 아이디를 찾을수 없다는 오류를 내뱉은것이 문제가 되었다.

 

그리하여 먼저 userprincipal의 항목에 providerid를 직접 집어넣는걸 시도해 보았다.

 

해결시도:

 

먼저, userprincipal이 providerid를 받지 못한다면

data class UserPrincipal(
    val id: Long,
    val email: String,
)

 

 

이럿듯 userprincipal이 providerid를 인식하는 항목이 없기에 문제가 생겼다고 생각하고는

 

data class UserPrincipal(
val id: Long,
val email: String,
val providerId: String
)

 

이렇게 userprincipal에 providerid를 넣어주면 해결될것이라 여겼으나,

@Component
class JwtAuthenticationFilter(
    private val jwtPlugin: JwtPlugin,
) : OncePerRequestFilter() {
    companion object {
        private val BEARER_PATTERN = Regex("^Bearer (.+?)$")
    }

    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain,
    ) {
        val jwt = request.getBearerToken()

        if (jwt != null) {
            jwtPlugin.validateToken(jwt)
                .onSuccess {
                    val userId = it.payload.subject.toLong()
                    val email = it.payload.get("email", String::class.java)

                    val userPrincipal = UserPrincipal(id = userId, email = email)

                    val details = WebAuthenticationDetailsSource().buildDetails(request)
                    val auth = JwtAuthenticationToken(userPrincipal, details)

                    SecurityContextHolder.getContext().authentication = auth
                }
        }

        filterChain.doFilter(request, response)
    }

    private fun HttpServletRequest.getBearerToken(): String? {
        val headerValue = this.getHeader(HttpHeaders.AUTHORIZATION) ?: return null
        return BEARER_PATTERN.find(headerValue)?.groupValues?.get(1)
    }
}

이럿듯 JwtAuthenticationFilter엔 providerid를 인식할수 없기 때문에 오류가 나게 되었다. 

 

@Component
class JwtAuthenticationFilter(
    private val jwtPlugin: JwtPlugin,
) : OncePerRequestFilter() {
    companion object {
        private val BEARER_PATTERN = Regex("^Bearer (.+?)$")
    }

        override fun doFilterInternal(
            request: HttpServletRequest,
            response: HttpServletResponse,
            filterChain: FilterChain,
        ) {
            val jwt = request.getBearerToken()

            if (jwt != null) {
                jwtPlugin.validateToken(jwt)
                    .onSuccess {
                        val userId = it.payload.subject.toLong()
                        val providerId = it.payload.get("providerId", String::class.java)
                        val email = it.payload.get("email", String::class.java)

                        val userPrincipal =
                            UserPrincipal(id = userId, provider = provider, providerId = providerId, email = email)

                        val details = WebAuthenticationDetailsSource().buildDetails(request)
                        val auth = JwtAuthenticationToken(userPrincipal, details)

                        SecurityContextHolder.getContext().authentication = auth
                    }
            }

            filterChain.doFilter(request, response)
        }

        private fun HttpServletRequest.getBearerToken(): String? {
            val headerValue = this.getHeader(HttpHeaders.AUTHORIZATION) ?: return null
            return BEARER_PATTERN.find(headerValue)?.groupValues?.get(1)
        }
}

 

 

그래서 이렇게 providerid를 넣어주었으나, 이것만으론 작동을 하지 않아서

// SocialUserRepository
fun findByProviderId(providerId: String): Optional<SocialUser>

 

이것까지 추가해 보았으나 

java.lang.NullPointerException: Parameter specified as non-null is null: method 라는 오류가 계속해서 발생하였다.

 

그리하여 뎨속 시도해본 결과, 이런 설정들을 고치는건 무의미하게 시간만 날린다고 생각하여 두번째 해결방안인 userID 대신 providerID를 사용하도록 수정하는 것이였다.

 


fun createReview(
        productId: Long,
        providerId: Long,
        createReviewRequest: CreateReviewRequest,
        orderId: Long,
    ): ReviewResponse

 

 

이런식으로 service와 serviceimpl에 providerid를 받도록 하면 훨씬 간단하게 해결이 된다.