Terminology
OAuth를 인증에 사용할 수 있을까?
먼저 Authentication과 Authorization의 용어부터 짚어보자.
- Authentication (인증): 참이라는 근거가 있는 무언가를 확인하거나 확증하는 행위
- 사용자 인증에 한정하자면, A 유저가 정말 A인지 검증하는 행위라 하겠다.
- Authorization (허가): 리소스에 대한 접근 권한 및 정책을 지정하는 기능
OAuth 2.0
OAuth는 허가(Authorization Framework)에 해당한다.
Abstract Flow
Grant Type에 따라 Flow가 달라질 수 있지만, OAuth 2.0의 추상화된 Flow를 살펴보자.
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
개발자가 사용자의 Google 자원에 접근하겠다고 한다면,
- Client: Developer’s Backend Server or iOS Application, etc..
- Resource Owner: User
- Authorization Server: Google’s Authorization Server
- Resource Server: Google’s Resource Server
이제 OAuth 2.0에서의 Access Token을 알아보고, OAuth 2.0 Protocol을 인증에 사용되면 안되는 이유에 대해 살펴보자.
Access Token을 사용자 인증에 사용해도 될까?
그렇지 않다. OAuth 2.0 Protocol은 사용자 인증이 OAuth의 스펙을 넘어서는 것이라고 말한다.
10.16. Misuse of Access Token to Impersonate Resource Owner in Implicit Flow
… Authenticating resource owners to clients is out of scope for this specification. … Any specification that uses the authorization process as a form of delegated end-user authentication to the client MUST NOT use the implicit flow without additional security mechanisms that would enable the client to determine if the access token was issued for its use.
Implicit Flow에 한정하여 설명하고 있긴 하지만, 보안 매커니즘을 추가 구현(client가 token audience를 식별할 수 있게 하는 등)하지 않는 이상은 end-user 인증에 사용하지 말라고 되어있다.
OAuth 2.0에서 정의한 Access Token의 Audience는 누구일까? 일반적으로 자원 서버이다.
… it is important for the authorization server to include the identity of the intended recipients (the audience), typically a single resource server (or a list of resource servers), in the token.
Access Token은 보통 클라이언트가 이해하기 어려운(opaque) String이다.
1.4. Access Token
… The string is usually opaque to the client. …
즉, OAuth 2.0에서 Access Token은 클라이언트가 보라고 만든게 아니다. 그저 자원 서버가 유효한 토큰인지 확인하고 허가된 자원에 한해 반환할 수 있도록 인증 서버가 발급하는 것이고, 클라이언트에게는 단순히 자원 서버 API 요청에 Access Token을 첨부하는 용도일 뿐이다.
클라이언트가 Access Token의 내용을 확인해서 user id 값을 보고(사실 OAuth에는 표준으로 정의된 access token format도 없으므로, 클라이언트가 user-id를 확인할 수 있다는 보장도 없다.) authenticated user라고 하는 것은 OAuth의 사용 목적과 다르며 보안 위험이 존재한다.
OAuth 2.0에서의 인가(Authorization)는 사용자(Resource Owner)를 인증(Authentication)한 후에 일어나는 만큼, 사용자 인증에 사용해도 되지 않을까?
Access Token이 사용자에 의해 인증 서버에서 방금 막 발급된 케이스에선 괜찮은 얘기 같다. 하지만, Access Token 발급이 사용자 인증 시에만 이루어지는 것도 아니고 (Refresh Token에 의한 획득), OAuth.net 포스팅에 의하면 grant type에 따라서는 사용자 인증이 전혀 관여되지 않기도 한다.
Access of a protected API as proof of authentication
Since the access token can be traded for a set of user attributes, it is tempting to think that posession of a valid access token is enough to prove that a user is authenticated. This assumption turns out to be true in some cases, where the token was freshly minted in the context of a user being authenticated at the authorization server. However, that’s not the only way to get an access token in OAuth. Refresh tokens and assertions can be used to get access tokens without the user being present, and in some cases access grants can occur without the user having to authenticate at all.
그 밖의 위험성에 대해선 위에 언급한 OAuth.net 포스팅을 참조하자.
이제 OAuth가 인증이 아니란건 알겠다. 그럼 인증 대행은 어떤 프로토콜을 사용해야 할까?
OpenID Connect
OpenID Connect (OIDC)는 인증(Authentication)에 해당한다.
인증 표준에는 OIDC, SAML 등이 있지만, OAuth2.0 기반의 OIDC가 널리 사용되는 것 같다.
번외
Sign in with Apple은 어떤 프로토콜일까?
사실 Sign in with Apple을 알아보던 중 Apple은 무슨 프로토콜을 채택한건가 리서치하다가 OAuth가 인증이 아니란 것도 알고.. OIDC의 존재도 알게 되었다. 😅
Apple은 OpenID Connect을 채택했지만, 약간의 차이가 있었고, 2019년 9월 즈음 모두 해소되었다고 한다.
OpenID 재단은 이러한 Apple에 자신들의 표준(OIDC)에 참여하도록 공개 서한도 보냈다.