6 min read

OAuth2.0와 OIDC

OAuth2.0와 OIDC
Photo by Conny Schneider / Unsplash

백엔드 개발자가 계정에 대한 이야기를 하면 가장 많이 나오는 것이 OAuth와 OIDC 입니다. 많은 서비스에서 사용하고 있으며, 활용하는 프로토콜 입니다.

인증 프로세스나 실무에서 적용 방법 보다도 이론적인 내용을 정리해보고자 합니다.

인증과 인가에 대해 제대로 이해하려면 OAuth2.0과 OIDC까지는 알아야 합니다.

OAuth와 OIDC

OAuth는 많이들 사용하고 있는 인가 기능을 제공하는 기술입니다.

OIDC는 유저의 인증에 초점을 맞춘 프로토콜이죠.

그래서 OIDC는 id_token을 통해 신원을 확인하고, API를 접근할 때는 access_token이 가지고 있는 권한에 따라 각 API에 접근할 수 있도록 구성하고 있습니다.

OAuth 2.0 프로세스

OAuth 2.0 - Authorization Code + PKCE

위 프로세스는 OAuth 2.0을 중심으로 짜여진 시퀀스 다이어그램입니다.

OAuth는 사용자가 누구인지 보다 이 토큰으로 무엇을 할 수 있는지가 핵심입니다.

PKCE는 모바일이나 SPA 환경에서 기본적으로 사용됩니다.

OIDC 프로세스

OIDC - Authorization Code Flow(ID Token, nonce) 인증 중심

위 프로세스의 포인트는 OIDC가 OAuth 위에 얹혀서, id_token으로 로그인(인증) 결과를 표준화 해준다는 점입니다.

id_token은 API 권한이 아닌 클라이언트가 로그인 완료를 신뢰하기 위한 토큰으로 활용됩니다.

nonce는 재사용 및 리플레이 방어에서 중요한 역할을 합니다.

정리

OAuth2와 OIDC는 함께 묶이는 개념입니다.

둘의 차이점은 다음과 같이 이야기 할 수 있죠.

  • OAuth 2.0 : 인가 프로토콜이며, 인증된 사용자에게 자원 접근 권한을 부여하는 것이 핵심 기능
  • OIDC : OAth 2.0을 확장하여, 사용자의 인증 정보를 안전하게 전달하는 인증 프로토콜

그럼 OIDC는 왜 사용할까요?

OIDC를 사용하는 이유는 사용자를 검증하기 위해서 사용합니다.

OAuth 2.0으로는 해당 토큰을 전송한 클라이언트가 누구인지 알 수 없기 때문이죠.

즉, 클라이언트의 신원을 안전하게 확인할 수 있도록 해주는 프로토콜 입니다.

OAuth 2.0과 OIDC Token

OAuth 2.0에는 access_token을, OIDC에서는 id_token을 사용합니다.

  • ID Token은 로그인 이벤트의 증명서라고 할 수 있습니다. 클라이언트가 검증해서 누가 로그인했는지 확인하는 Token이죠.
  • Access Token은 API 접근 권한의 열쇠입니다. 리소스 서버가 검증해서 무엇을 할 수 있는지를 확인하는 용도입니다.

id_token 요소

id_token는 JWT를 사용합니다.

  • iss : 발급자
  • aud : 이 토큰의 대상
  • sub : 사용자 고유 식별자
  • exp, iat : 만료/발급 시간
  • nonce : 리플레이 방지. 로그인 요청 시 넣은 nonce와 매칭
  • azp : 요청해서 발급받은 클라이언트(ex: OAuth client_id)
  • at_hash, c_hash : access token / code와의 결합 검증용

예시

{
  "iss": "https://op.example.com",
  "aud": "client-123",
  "sub": "user-789",
  "exp": 1710000000,
  "iat": 1709996400,
  "nonce": "n-0S6_WzA2Mj"
}

access_token 요소

access_token의 특징은 문자열로만 정의하고 내부 구조를 꼭 JWT로 정의하진 않습니다. 또한, Bearer 토큰을 기반으로 access_token이 구성되어 있으므로 함께 살펴보겠습니다.

토큰 응답에서의 요소(표준 필드)

  • access_token : 실제 토큰 값
  • token_type : 보통 Bearer
  • expires_in : 만료까지 초
  • scope : 발급된 권한 범위
  • refresh_token : access_token 발급용

access token이 JWT일 때 클레임

아래의 내용은 구현 관행입니다. 표준이라고 하기엔 무리가 있습니다.

  • iss : 발급자
  • aud : 리소스 서버(API) 식별자
  • sub : 사용자/주체
  • scope 또는 scp : 권한 범위
  • exp, iat, jti : 만료/발급/토큰 식별자

JWT 자체의 registered claim 개념은 JWT 스펙(RFC 7519) 을 참고하면 좋습니다.

정리하면 access_token리소스 서버가 검증하고 해석하는 게 원칙입니다.

클라이언트가 내부를 파싱해서 이 사람이 누구네로 쓰기 시작하면 설계가 흐려지기 쉽습니다.

Role 설계와 연결

Role/권한을 “정책 집행”에 쓰기 위해서는 다음 내용이 필요합니다.

  • Access Token(= API용) 안에 roles/permissions 클레임을 넣고 RS에서 강제
  • 권한은 별도 권한조회(Authorization Service)로 분리

반대로 id_token에 Role을 넣는 건 “UI 표시” 정도까진 편하게 가져갈 수 있습니다.

그 이상으로 권한을 부여하면, 책임 경계가 무너지게 됩니다.

용어 설명

PKCE(Proof Key for Code Exchange) - 인가 코드 가로채기를 막기 위한 보안 확장.

PKCE는 Authorization Code Flow에서 code가 탈취되면 공격자가 토큰 발급이 되기 때문에 나온 보안 확장입니다.

code_verifiercode_challenge를 통해 값을 증명합니다.

code_verifier는 클라이언트가 랜덤하게 만든 비밀 문자열이며, 외부 노출되면 안됩니다.

code_challengecode_verifier를 변환한 값으로 보통 S256(SHA-256 적용 후 Base64URL)로 변환합니다.

OpenID Provider(OP) - 로그인을 수행하고, 그 결과를 표준 방식으로 증명해주는 주체. OP는 OAuth의 Authroization Server(AS) 역할에 OIDC 인증 기능을 함께 수행하는 경우가 많습니다.

대표적으로 4가지 일을 합니다.

  1. 사용자 인증
  2. 동의 및 Scope/Clame 제어
  3. 토큰 발급
  4. 검증 기반 제공

마무리

여기까지 OAuth2.0과 OIDC에 대해 알아봤습니다.

공부해보면 확장되어 공부할만한 내용들이 많이 있습니다.

대표적으로 글 마지막에 다른 OpenID Provider가 있는데요.

추가로 공부하기 좋은 주제로 보입니다.