구글 아이디로 로그인 구현중 리프레시 토큰(refresh token) 이 안넘어오는 경우 해결책

카카오 아이디 로그인을 PHP 에서 처리하려고 Hybridauth 패키지를 이용해 구현하고 있습니다.

카카오 아이디 로그인이 잘 되어서 이제 구글 로그인도 붙여보려고 테스트하고 있는데요. 이상하게 카카오와는 다르게 refresh token 이 안넘어오네요.

debug 모드로 봐도 refresh_token 이 아예 항목이 없이 넘어옵니다.

계속 구글링 해보고 refresh token is null, refresh token is empty 등으로 검색해보다가 반나절만에 겨우 찾았네요.

역시 설명서를 잘 읽어야 됩니다.

카카오의 경우 access_token 을 얻을 때 항상 refresh_token 도 같이 넘겨주는 데요. 구글의 경우에는 항상 넘겨주는게 아니라 기본적으로 access_token 처음 발급할 때만 넘겨줍니다. 그래서 로그아웃 후 두번째 테스트 할 때부터는 카카오랑 동일한 로직으로 처리하면 refresh_token 이 넘어오지 않게 되는 겁니다.

정확히는 몇가지 refresh_token 이 만료되는 경우가 설명서에 언급되어 있는데요. (https://developers.google.com/identity/protocols/oauth2#expiration)

  • 사용자가 앱의 액세스 권한을 취소했습니다.
  • 갱신 토큰이 6개월 동안 사용되지 않았습니다.
  • 사용자가 비밀번호를 변경했으며 갱신 토큰에 Gmail 범위가 포함되어 있습니다.
  • 사용자 계정에서 부여된 최대 (실시간) 갱신 토큰 수를 초과했습니다.
  • 세션 제어 정책이 적용되는 Google Cloud Platform 조직에 속한 사용자입니다.

이렇게 5가지의 경우에만 새로 리프레시 토큰이 발급됩니다.

그러니 구글 아이디로 로그인을 구현할 때는 리프레스 토큰을 좀더 꼼꼼하게 챙겨야 합니다. 로직을 구현할 때 2가지 정도 추가적으로 고려하시기 바랍니다.

  1. 아무때나 refresh_token 을 받을 수 없기 때문에 첫 access_token 을 발급할 때 받은 refresh_token 값을 DB 등에 장기 저장할 수 있어야 합니다.
  2. 또한 첫 로그인 을 제외하고 위 4가지 이유에 따라 언제든지 새로운 refresh_token 을 받을 수 있으므로 새로 refresh_token 을 받게되면 바로 DB 등에 장기 저장해 둬야 합니다.

이렇게 저장한 refresh_token 은 만료되기 전까지는 계속 사용할 수 있습니다.

모르면 헤맬 수 밖에 없는 부분이네요. 미리 설명서가 영어라고 꼼꼼히 안읽어본 저의 잘못이겠죠. 다른분들은 이 글을 보시고 방황하는 시간을 조금이라도 줄이는데 도움이 되길 바랄 뿐입니다. ^^

참고 문서 >

구글 OAuth2 설명서 (영문) : https://developers.google.com/identity/protocols/oauth2?hl=en#expiration

스택오버플로우 답변 : https://stackoverflow.com/questions/62700314/keycloak-only-gets-google-refresh-token-on-first-login