개발/Spring

[Spring] Spring Security 를 이용한 SNS 로그인 (카카오)

hojak99 2019. 12. 29. 21:55

이번에 사이드프로젝트를 진행하면서 카카오 로그인을 붙여야 했다.

Spring boot 를 이용하여 카카오 로그인을 연동해야 했기에 카카오에서 제공하는 REST API 를 이용하였다.

https://developers.kakao.com/docs/restapi/user-management

 

Kakao Developers_

더 나은 세상을 꿈꾸고 그것을 현실로 만드는 이를 위하여 카카오에서 앱 개발 플랫폼 서비스를 시작합니다.

developers.kakao.com

 

 


우선 처음으로 access token 과 refresh token 을 관리하는 것을 구현해보기 때문에 처음에 Spring Security 를 이용하여 어떻게 구현할 것인지, access token 과 refresh token 을 어떻게 관리하고 갱신할 것인지 잡히는 것이 없었고 구글링하고 레퍼런스 문서를 보면서 구현할 수 있었다.

이번 글에서는 내가 삽질한 것을 공유해보려고 한다.

OAuth2ClientAuthenticationProcessingFilter 를 이용 

위 사진과 같이 나는 OAuth2ClientAuthenticationProcessingFilter 를 이용하여 카카오 로그인을 연동하려 했고 정상적으로 연동을 했다. 

그러나 access token, refresh token 을 관리하려면 아래 사진과 같이 Authorization Code 를 발급 받아 해당 code 를 이용하여 사용자 토큰을 얻어야만 한다. 

이 때 Authorization Code 는 일회용인 것을 잊지말자.

 

카카오의 OAuth 인증 과정

 

Spring 에서 제공하는 OAuth2ClientAuthenticationProcessingFilter 를 이용하면 굉장히 쉽게 code 를 얻을 수 있다. 위에 올려놓은 코드를 보다시피 사용자가 로그인을 성공적으로 마친 후 해당 kakaoAuthenticationSuccessHandler 가 호출되면서 해당 handler 내부에서 로그인 성공 시 카카오에서 주는 response 에서 email, name 등 정보를 가지고 DB 에 조회하여 데이터가 존재하지 않는다면 DB 에 넣는 식으로 로직을 추가해 놓은 상태이다.

그리고 HttpServletResponse 에서 getParamter() 메소드를 통해 code 값을 가져온 후 카카오에 사용자의 토큰을 요청했을 때 아래 사진과 같은 에러가 발생하였다.

토큰 요청 시 에러 발생

분명 정상적으로 토큰 요청을 했고, code 값도 카카오에서 주는 code 값을 이용하였으나 에러가 발생했다. 

"authorization code not found for code" 만 보았을 때는 내 잘못이 아닌 것만 같았다. 분명 카카오에서 발급된 code 값을 이용했고 난 그 code 값을 이용했을 뿐인데,,!!

 


 

다시 OAuth2ClientAuthenticationProcessingFilter 로 돌아와서 해당 filter 에 restTemplate 와 tokenService 의 setter 를 호출 했었다.

그리고 OAuth2ProtectedResourceDetails 를 생성 시 아래 사진과 같이 accessTokenUri 를 설정했었다.

accessTokenUri
accessToken, refresh token

 

OAuth2ClientAuthenticationProcessingFilter 코드에서 해당 메소드 부분에 브레이크 포인트를 걸고 로그인 성공 시 해당 메소드를 타게 되는데 이 restTemplate.getAccessToken() 을 통해 accessToken 과 refreshToken 을 가지고 OAuth2AccessToken 을 생성하는 것을 볼 수 있다.

즉 우리가 직접 사용자 토큰을 요청하지 않아도 OAuth2ClientAuthenticationProcessingFilter 해당 필터를 통해 요청하게 된다.

그리고 해당 코드와 같이 AuthenticationSuccessHandler 를 구현하는 클래스에서 Authenticationdetails 를 통해 accessToken 을 가져올 수 있다. 그러나 refresh token 은 해당 detail object 에서 가져올 수 없다. refresh token 을 얻어 DB 에서 관리하게 하기 위해 해당 클래스에서 OAuth2ClientContext 를 DI 받아 아래 사진과 같이 사용하면 refresh token 과 만료 시간을 얻을 수 있다.


 

결론은 OAuth2ClientAuthenticationProcessingFilter 를 이용한다면 굳이 code 값을 가지고 사용자 토큰을 얻으려고 하지 말자. 알아서 얻어 온다. 

반응형