[OIDC] OIDC(OpenID Connect)와 Oauth2.0
포스트
취소

[OIDC] OIDC(OpenID Connect)와 Oauth2.0

OIDC?

OIDC는 OpenID Connect의 줄임말로, Oauth2.0 기반 인증(Authentication) 프로토콜입니다. 기존 OAuth2.0은 서비스를 사용할 수 있는 권한(Authorization)을 제공했다면, OIDC는 OAuth 플로우에 신원확인(Authentication)을 제공합니다.

OAuth2.0

OIDC 자체가 OAuth2.0 기반이기 때문에, OIDC가 왜 필요하고 어떤식으로 동작하는지 이해하기 위해서 OAuth2.0에 대한 이해가 선행되어야 합니다.

OAuth2.0은 SNS 로그인, 타사 서비스 이용하는 기능을 개발할때 많이 보게되는 단어입니다. OAuth2.0은 다른 서비스의 ID, PW를 직접 제공받지 않아도, 다른 서비스에 저장된 사용자 데이터에 접근할 수 있는 권한을 위임받는 프로토콜입니다.
예를들면 간단한 메모를 작성하고 저장할 수 있는 앱을 개발할때, 구글 드라이브를 이용해서 클라우드 기능을 추가하려고 한다고 가정해보겠습니다. 이때 구글 클라우드에 데이터를 추가하고 삭제하는건 구글 계정의 ID, PW가 있어야 접근이 가능합니다. 하지만 구글에서 제공하는 OAuth2.0 프로토콜을 이용하면 메모 서비스에서 굳이 구글의 ID, PW를 받지 않아도 리소스 접근이 가능해집니다.

OAuth2.0은 이렇게 민감한 정보를 서비스에 알려줄 필요 없이 타사 서비스의 리소스 접근 권한을 얻을 수 있다는 장점때문에 많은 서비스에 도입되어 사용되고 있습니다.

OAuth2.0의 구성 요소

OAuth2.0의 흐름을 이해하려면 우선 4가지 핵심 구성 요소에 대해 알아야합니다.

Resource Owner

Resource Owner는 단어 그대로 자원의 소유자를 뜻합니다. 앞서 예시로 든 메모 서비스에서 메모 서비스를 사용하는 사용자에 해당합니다. 사용자는 우리 서비스를 이용하면서 서비스에서 사용하려는 구글 클라우드 계정의 주인이기도 합니다.

Client

Client는 Resource Server에게 자원을 요청하는 서비스입니다. 메모 서비스에서는 구글에게 자원을 요청하는 메모 서비스 자체가 Client에 해당합니다.

Authorization Server

Authorization Server는 권한을 검증하고 리소스에 접근이 가능한 엑세스 토큰을 발급해주는 서버입니다. 흔히 특정 서비스에서 다른 서비스를 이용할때 그 서비스에 로그인 하는 화면을 많이 보셨을텐데 그 단계에 해당합니다. 메모 서비스에서는 구글 인증 서버가 해당합나다.

Resource Server

Resource Server도 이름 그대로 자원을 가지고 있는 서버입니다. 메모 서비스에서는 실제로 자원을 소유하는 구글 클라우드 서버가 해당됩니다.

Oauth2.0 흐름

ln1

이제 OAuth2.0이 어떤 흐름으로 동작하는지 알아보겠습니다.

  1. 사용자가 타사 서비스 접근이 필요한 기능 요청 및 로그인 요청 (예시 - 소셜로그인)
  2. 사용자에게 타사 서비스 로그인 화면 안내
  3. 사용자가 타사 서비스에 ID/PW를 입력하여 자격 증명 및 권한 부여 승인
  4. 타사 인증 서버는 타사 리소스 접근이 가능한 엑세스 토큰을 발급받을 수 있는 Authorization Code 발급
  5. 서비스에서 전달받은 Authorization Code를 이용해 인증 서버에 엑세스 토큰 교환 요청
  6. 인증 서버는 코드 검증 후 리소스 접근이 가능한 엑세스 토큰 발급
  7. 서비스는 전달받은 엑세스 토큰으로 타사 서비스의 리소스 접근

OAuth2.0 종류

위에서 설명한 플로우는 Authorization Code Grant 방식입니다. OAuth2.0은 상황에 따라 사용 가능한 여러 방식을 제시했는데, 총 4가지가 존재합니다.

Authorization Code Grant

흐름 설명 예시로 든 OAuth2.0의 가장 기본적인 방식입니다. 클라이언트가 사용자 대신 서버에 Authorization Code를 받아 엑세스 토큰으로 교환받는 방식으로 특정 자원에 접근 권한을 얻습니다.
안전한 백엔드 서버끼리 통신하기 때문에 4 가지 방법 중 보안성이 가장 높고 안전한 방식입니다.

Implicit Grant

뜻을 해석하면 암묵적 승인 입니다. 이 방식은 로그인 후 Authorization Code를 발급하는게 아닌 엑세스 토큰을 즉시 발급해서 URL에 넣어 알려줍니다.
보안이 매우 취약한 URL에 중요한 엑세스 토큰을 넣어 보내므로 보안성이 매우 좋지 않습니다. 그래서 OAuth2.1에서는 아예 제외된 방식입니다.
원래 의도는 서버가 따로 없는 환경에서 웹프론트에서 바로 OAuth2.0 프로토콜을 사용하게 하기 위해 제시되었던 방법입니다.

Resource Owner Password Credentials Grant

뜻을 해석하면 비밀번호 자격증명 승인 방식입니다. 뜻 그대로 자원 접근을 요청할 서비스의 ID/PW를 그대로 입력해서 엑세스 토큰을 발급받는 방법입니다.
이 방식은 타사 서비스를 사용할때는 잘 쓰이지 않고, 자사의 여러 서비스를 OAuth2.0으로 제공할때 사용하는 방식입니다.

Client Credentials

이 방식은 사용자 없이 미리 전달받은 Client ID와 Client Secret으로 인증 후 엑세스 토큰을 얻는 방식입니다. 사용자 개입이 없는 서버간 통신에서 간단한 방법으로 OAuth2.0을 구현할때 사용됩니다.

OIDC

이번에는 OIDC에 대해 알아보겠습니다. 앞서 간단하게 설명했듯이, OIDC는 OAuth2.0 기반의 Authentication 프로토콜입니다. OAuth2.0이 리소스에 접근이 가능한 엑세스 토큰을 얻는게 목적이라면, OIDC는 신원을 알 수 있는 IDToken을 얻는게 목적입니다.

IDToken

IDToken은 OIDC의 최종 결과물중 하나입니다. IDToken은 인증을 요청한 사용자의 간단한 정보가 담긴 토큰으로, 사용자가 언제, 어떻게, 누구인지에 대한 정보가 담겨있습니다. IDToken은 반드시 JWT 형식으로 작성됩니다.

IDToken은 엑세스 토큰과 다르게 리소스에 접근하기 위한 토큰이 아니라, 요청한 사용자의 정보 전달이 목적이라서 리소스 요청에는 사용되지 않습니다.

IDToken 내용

1
2
3
4
5
6
7
8
9
10
{
  "iss": "https://accounts.google.com", 
  "sub": "104234567890123456789",       
  "aud": "my-client-id.apps.googleusercontent.com", 
  "iat": 1698765432,                    
  "exp": 1698769032,                    
  "name": "홍길동",
  "email": "hong@example.com",
  "picture": "https://example.com/hong.jpg"
}

IDToken의 클래임은 정해진 표준이 존재합니다. 자세한 내용은 공식문서에서 확인 가능합니다. 여기서는 하나하나 자세히 살펴보지는 않을겁니다.

간략하게 요약하자면, JWT는 발급 일자를 알 수 있는 iat, 토큰 유효 시간 exp, 발급자를 알 수 있는 iss와 같은 필수 클래임이 있습니다. 그리고 IDToken의 목적인 사용자 정보 전달을 위해 name, email, picture과 같은 정보 관련 클레임들도 정의되어 있습니다. 이러한 정보들은 요청시 scope을 지정해서 요청할 수 있습니다.

OIDC 흐름

ln1

이번에는 OIDC의 흐름에 대해 알아보겠습니다. 시퀀스 다이어그램을 보면 알겠지만, OAuth2.0 Authorization Code 기반에 엑세스 토큰과 함께 IDToken을 준다는 부분만 추가된 플로우입니다.

OIDC가 필요한 이유

OAuth2.0과 OIDC를 알아보면 플로우도 비슷하고 결과도 비슷한데 OIDC가 왜 필요한지 의문이 들 수 있습니다. OAuth2.0을 두고 왜 OIDC가 도입되었는지 정리해 보겠습니다.

OIDC라는 프로토콜이 도입되기 전, 많은 서비스들이 SNS 로그인을 지원할때 OAuth2.0을 이용해서 구현했습니다. 그런데 OAuth2.0은 타사 서비스의 자원에 접근할 수 있는 엑세스 토큰을 발급하는게 목적이었기 때문에, SNS 로그인으로 타사 서비스의 계정 정보를 가져오려면 OAuth2.0 플로우 이후 추가적인 요청이 필요했습니다.
게다가 서비스마다 사용자의 정보를 제공하는 방식과 형식이 제각각이라서 여러 서비스의 SNS 로그인을 지원할때는 각 서비스마다 각각 구현해주어야 하는 문제도 있었습니다.

이런 문제를 해결하기 위해 OIDC라는 프로토콜을 도입하게 되었습니다. IDToken이라는 표준을 만들어서 사용자 정보 제공 형식을 표준화 하고, 프로토콜의 결과물로 항상 제공하게 하여 불필요한 네트워크 낭비를 줄일 수 있게 했습니다.
그래서 오늘날 많은 서비스들은 단순 SNS 로그인을 위한 API는 모두 OIDC 프로토콜을 따르게 구성되어있습니다. 대표적인게 Apple에서 제공하는 Apple Sign In인데, Apple 계정을 이용한 SNS 로그인을 진행하면 최종적으로 IDToken을 전달받게 됩니다.

요약하자면 OAuth2.0은 타사 리소스 접근을 위한 좋은 수단이었지만, 사용자 정보를 제공하기에는 부족해서 OAuth2.0을 이용해 고안된게 OIDC라고 정리할 수 있겠습니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.