The Developer's Guide to Seamless Social Logins

OAuth 는 open authorization 의 약자로, Mechanism for Delegation of Authorization 이다.

OAuth 2.0 Abstract Flow:

OAuth 2.0 방식으로 Social Login 을 구현하는 경우 Authorization Code Grant 방식을 사용하게 된다.

< Authorization Code Grant Flow >
1. 사용자가 App(client) 에 접근한다.
2. Client 는 사용자에게 접근 권한을 요청한다.
3. Client 는 사용자를 OAuthProvider 와 연결한다. 서비스 제공자는 사용자에게 Client 가 리소스에 접근할 권한에 대해 허용 여부를 직접 질의한다.
(사용자가 허락했다는 가정) 서비스 제공자는 Backend 에게 사용자의 리소스에 접근할 수 있는 액세스 토큰과 교환할 수 있는 태그(Authorization Code)를 전달한다.
4. Backend 는 Authorization Code 로 OAuthProvider 에게 AccessToken 을 요청한다.
5. Backend 는 OAuthProvider 가 준 AccessToken 을 이용해서, Application 을 이용할 수 있는 AccessToken, RefreshToken 등을 만들어서 Client 에게 응답한다.
6. Client 는 Backend 에서 발급한 AccessToken 을 가지고 Backend 에게 Resources 를 요청한다.

Tag is known as an authorization code and it can be exchanged for an access token. The tag is a one-time-use tag, and so is said to be consumable. OAuth 2.0에서는 인가 코드 만료시간을 10분으로 제한하도록 권장한다.

인가 요청 시 state(optional) 값을 담아서 보낼 수 있다. 클라이언트의 요청과 그에 따른 콜백 간의 상태를 유지하기 위해 사용되며, 클라이언트가 서비스 제공자에게 전달하면 서비스 제공자는 이 값을 다시 응답에 포함해서 전달한다. Cross-site request forgery 공격을 차단하기 위한 수단이 될 수 있다.

Authorization Code Grant Flow 를 사용하는 경우 아래와 같은 프로퍼티들이 필요하다.

Authorization Code Grant Flow 에 보안이 조금 더 추가된 매커니즘이 Authorization Code Flow with Proof Key for Code Exchange (PKCE) 이다. 악의적인 사용자에 의한 interception attacks 을 막을 수 있다.

이번엔 OpenIdConnect 에 대해서 알아보자.

OpenIDConnect(OIDC) 는 사용자가 안전하게 로그인하는 데 사용할 수 있는 OAuth 2.0 기반의 표준 Authentication 프로토콜이다.

표준 프로토콜이기 때문에 한 번만 구현 해두면, Apple, Google, Kakao 등 다양한 Provider 들에 대해서 서버에서 유연하게 처리할 수 있다.

OpenIDConnect 에서는 scope 를 openid, profile, email, address 로 표준화했다. THE LAWS OF IDENTITY - Minimal Disclosure for a Constrained Use 원칙을 적용한 것이라고 보여진다.

IdToken 을 검증하기 위해서 OpenIdProvider 가 제공하는 공개키 목록을 조회한 후, 서버에서는 일정 기간 캐싱해두어서 사용한다. 공개키 목록이 필요한 이유는 IdToken(JWT Format) 을 검증해야하기 때문이다.

IdToken 은 그 자체로 로그인을 수행하게 만들 수 있기 때문에, 노출되어서는 안된다. 따라서 IdToken 을 Server Side 에서 얻도록 해야 한다. 또한 검증은 IdTokenValidation 을 따라야 한다.

OpenIdConnect Flow

OpenIdConnect Flow:

< OpenIdConnect Flow >
1. Client Side 에서 Authorization Code Flow 진행 (nonce 값을 넣어서 code 생성)
  - 이때 Provider 별로 Authorization Code 와 함께 IdToken 을 같이 주는 경우가 있음 (e.g Apple)
  - IdToken 을 응답으로 주는 경우에는 서버로 IdToken 과 nonce 를 전달하면 된다.
2. Client 에서 Server 로 Authorization Code 와 nonce 값을 전달.
3. Server 에서 Authorization Code 로 IdToken 획득
4. Verfiying IdToken 
  - public key 목록 조회
  - 각 Provider 에서 제공하는 IdToken 검증 방법 문서를 보면서 해당 절차대로 토큰을 검증
  - nonce 값 검증
5. IdToken 을 통해서 유저 정보 가져오기 (e.g email, profile ...)

Google

Google 의 OpenIdConnect 구현 방법을 살펴보면 아래와 같은 순서로 가이드가 되어있다.

  1. 위조 방지 상태 토큰 만들기
  2. Google 에 인증 요청 보내기
  3. 위조 방지 상태 토큰 확인
  4. code을(를) 액세스 토큰 및 ID 토큰으로 교환
  5. ID 토큰 검증
  6. ID 토큰에서 사용자 정보 가져오기
  7. 사용자 인증하기

여기서 code 는 Authorization Code 를 의미한다. 따라서 Client Side 에서 해야할 단계와 Server Side 에서 해야할 단계를 명확하게 구분 지을 수 있다. 1~3번까지는 Client Side 에서 진행할 수 있다. 4~7번은 Server Side 에서 진행한다.

Verifying Token 과정은 OIDC 스펙을 구현하는 모든 소셜 로그인의 경우 거의 동일하다. (e.g Apple, Kakao)

Apple

Apple 도 Google, Kakao 처럼 Configuration 을 먼저 진행해야 한다.

Apple 의 경우에는 Client 에서 Authorization Flow 를 구현하고 응답으로 Authorization Code 와 IdToken 을 응답으로 받는다. 따라서 Client 에서는 Server 로 IdToken 과 nonce 값을 전달하고, Server 에서는 아래 절차대로 IdToken 을 검증한다.

Verifying a user:

  • Verify the JWS E256 signature using the server’s public key
  • Verify the nonce for the authentication
  • Verify that the iss field contains https://appleid.apple.com
  • Verify that the aud field is the developer’s client_id
  • Verify that the time is earlier than the exp value of the token

Kakao

Kakao 의 경우에는 Google 과 구현 방식이 거의 동일하다.

References

  • Mastering Oauth 2.0 / Charles Bihis