Oauth2.0으로 소셜 로그인을 구현해도 되는걸까?
아마 많은 개발자분들이 제목을 보고 ‘엥 당연한거 아니야?’라고 생각할 수도 있을 것 같습니다만 이런 고민을 하게 된 배경을 말씀드리겠습니다.
제가 소셜 로그인을 구현할 때는 Oauth2.0 + OIDC를 이용하여 구현했습니다. 그래서 Oauth2.0의 AccessToken은 자원 접근을 위해 사용되고 OIDC의 ID Token은 사용자 인증을 위한 것임을 알게되었죠.
그런데 분명 저도 소셜 로그인을 구현할 때 처음부터 OIDC를 도입할 생각은 하지 않았었고, 또 많은 개발자들이 Oauth2.0만을 사용하여 구현하는 것도 보았습니다. 그래서 과연 이런 구현 방법이 옳은 것인지에 대해 고민을 하며 Oauth2.0과 OIDC에 대한 표준에 대해 살짝 읽어보며 글을 작성하였습니다.
Oauth2.0
먼저 Oauth2.0의 표준 문서의 요약의 첫줄을 보면
The OAuth 2.0 authorization ramewofrk enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.
Oauth2.0의 본래 목적은 리소스 소유자를 대신하여 리소스에 대한 권한을 부여하는 목적임을 확인할 수 있습니다. 그렇다면 ‘Oauth2.0에서 얻는 AccessToken을 인증 목적으로 쓰기에는 조금 부적합 한 것 아닐까?’라는 생각이 들어 AccessToken에 관해서도 찾아보았습니다.
AccessToken
액세스 토큰을 설명하는 첫 줄에도 역시 이런 말이 있습니다.
Access tokens are credentials used to access protected resources. An access token is a string representing an authorization issued to the client.
첫 줄에 액세스 토큰의 목적이 자원에 접근하기 위한 신원자격임을 설명합니다. 그래서 분명히 본래 목적은 자원에 접근하기 위한 것이 맞습니다.
즉, 액세스 토큰을 소셜 로그인에 사용한다는 것은 기존 AccessToken의 자원 접근 권한에 더해 Oauth2.0 Client의 서비스 이용 권한을 추가 한다는 의미입니다.
본래 목적과는 다르지만 AccessToken을 얻었다는 것 자체가 Resource Owner에 대해 인증을 성공한 것을 의미하기 때문에 Oauth2.0 Server의 보안을 신뢰한다면 그렇게 사용해도 될 것 같습니다. (보안을 신뢰하지 않는다면 애초에 소셜 로그인을 안하겠지?)
하지만 본래 사용 목적과 다르게 자원에 대한 접근이 아닌 서비스 이용에 대한 인증으로 사용을 했기 때문에, 만약 Oauth2.0 Server가 해킹당하여 해당 토큰을 인증 방식으로 사용하던 서비스까지 해킹당한다고 하더라도 이에 대한 책임을 묻기는 어려울 것 같습니다. (추측)
그러면 서비스 인증에 AccessToken을 사용하는 것이 ID Token을 사용하는 것과는 어떤 점이 다른거지? 라는 의문을 가질 수도 있을 것 같습니다.
AccessToken vs ID Token
아래는 액세스 토큰에 대한 다른 설명입니다.
The token may denote an identifier used to retrieve the authorization information or may self-contain the authorization information in a verifiable manner (i.e., a token string consisting of some data and a signature).
An access token is a string representing an authorization issued to the client. The string is usually opaque to the client.
AccessToken은 Resource Server에서 검증을 해야하기 떄문에 직접 내용을 담을 필요도 없고 읽을 필요도 없습니다. 인가 정보를 찾는데 필요한 식별자 또는 JWT와 같이 Resource Server에서 토큰에 대한 검증할 수 있는 정보만을 포함하면 되는 것이죠.
실제로 카카오 로그인의 AccessToken 문자열을 보면 읽을 수 없는 Opaque Token임을 확인할 수 있습니다.

이와 다르게 OIDC에서의 ID Token은 목적 자체가 인증에 있기 떄문에 Oauth2.0 Client에서 이를 직접 읽고 검증할 수 있습니다.
The primary extension that OpenID Connect makes to OAuth 2.0 to enable End-Users to be Authenticated is the ID Token data structure. The ID Token is a security token that contains Claims about the Authentication of an End-User by an Authorization Server when using a Client, and potentially other requested Claims. The ID Token is represented as a JSON Web Token (JWT) [JWT].
그래서 형식을 크게 제한하지 않는 AccessToken과는 다르게 JWT로 표현 된다고 말하고 있고 JWS 공개키 목록을 가져와 직접 내용을 읽고 검증할 수 있습니다.
두 토큰을 비교한 표 입니다.
AccessToken | ID Token | |||
---|---|---|---|---|
인증을 위해 사용할 수 있는가? | 본래 목적과는 다르지만 인증 성공의 결과이기 때문에 가능은 함 | 본래 목적이 인증을 위한 것임 | ||
Oauth2.0 Client가 토큰을 읽고 검증할 수 있는가? | Oauth2.0 Server가 검증해야함 | 공개키를 통해 검증 가능 | ||
장단점 | 검증 로직을 Oauth2.0 Server에 위임하여 편하지만 검증을 요청하고 받는 네트워크 비용이 필요 | 직접 검증을 하는 로직이 필요하지만 추가적인 요청이 필요하지 않음(공개키는 캐싱 가능함) |
결론
결론적으로 AccessToken을 인증에 사용하여 소셜 로그인을 구현할 수 있지만, 토큰의 본래 목적과는 다른 추가적인 권한을 부여했다는 것을 인지하고 사용 하는 것이 좋아보입니다. 그리고 만약 검증 로직을 구현할 충분할 시간이 있다면 ID Token을 인증에 사용하는 것을 추천드립니다.
참고자료:
OAuth2.0 표준
OIDC1.0 표준