본문으로 건너뛰기
홈
기술
기술 전체
프로그래밍68
컴퓨터 과학63
AI48
웹 개발36
인프라33
데이터31
소프트웨어 공학18
소개
← 목록으로소프트웨어 공학 › 보안 › OAuth

2. OAuth 2.0

목차

OAuth 2.0: 권한 위임 흐름과 현재 권장 방식

OAuth 2.0은 애플리케이션이 사용자의 비밀번호를 직접 받지 않고, 허용된 자원과 작업에 접근할 토큰을 얻는 권한 위임 프레임워크다. OAuth 1.0의 매 요청 서명 모델 대신, 토큰 발급과 API 요청을 TLS로 보호하는 흐름을 정의한다. 여기서 “서명이 필요 없다”는 말이 암호화나 보안 검증이 필요 없다는 뜻은 아니다. 토큰을 가진 자가 요청할 수 있는 bearer token을 쓰는 경우 유출 방지와 HTTPS가 특히 중요하다.

네 역할과 두 서버

역할하는 일
Resource Owner자원에 대한 권한을 가진 사용자 또는 주체
Client허가를 받아 자원에 접근하려는 애플리케이션
Authorization Server사용자 동의와 클라이언트 검사를 거쳐 토큰 발급
Resource Server토큰을 검증하고 보호 자원 제공

인증 서버와 자원 서버는 논리적 역할이며, 실제 배포에서 같은 서버일 수도 있다. access token은 보호 API에 보내고, refresh token은 새 접근 토큰을 얻을 때 인증 서버의 토큰 엔드포인트에 보낸다. 클라이언트가 사용자의 신원을 확인하려면 OAuth만으로 충분하다고 가정하지 말고 OpenID Connect나 공급자의 사용자 정보 계약을 확인해야 한다.

Authorization Code + PKCE

[그림1. Authorization Code Grant type 으로 Access Token을 얻어오는 시퀀스 다이어그램]

현재 웹과 모바일 클라이언트의 기본 선택지는 Authorization Code와 PKCE다. 위 그림의 발급 순서에 다음 보안 검사를 함께 적용해야 한다.

  1. 클라이언트는 요청마다 새 code_verifier를 만들고 SHA-256 기반 code_challenge를 계산한다. 사용자를 인증 서버의 승인 URL로 보낼 때 client_id, 등록된 redirect_uri, 필요한 scope, state, code_challenge를 포함한다.
  2. 사용자는 인증 서버 화면에서 로그인하고 요청된 권한을 승인한다. 클라이언트가 사용자의 비밀번호를 수집하지 않는다.
  3. 인증 서버는 등록된 리다이렉트 주소로 짧은 수명의 code를 보낸다. 클라이언트는 돌아온 state가 자신이 시작한 요청의 값인지 확인한다. 값이 다르면 코드 교환을 중단한다.
  4. 클라이언트는 code와 원래의 code_verifier를 토큰 엔드포인트로 보낸다. 인증 서버는 challenge와 일치하는지, 코드가 해당 클라이언트·리다이렉트 주소에 묶여 있는지 검사한 뒤 토큰을 발급한다.
  5. 클라이언트는 access token으로 자원 서버를 호출한다. 자원 서버는 토큰의 유효성, 대상, 필요한 권한을 확인한다.

PKCE는 탈취된 승인 코드만으로 토큰을 얻지 못하게 한다. 공개 클라이언트에는 필수이고, 기밀 클라이언트에도 권장된다. client_secret을 브라우저 JavaScript나 모바일 앱에 넣어 기밀 클라이언트처럼 취급하면 비밀값이 노출된다. 또한 scope를 최소로 요청하고, 리다이렉트 주소를 정확히 등록해야 한다. 상세 기준은 RFC 9700을 따른다.

다른 grant는 언제 쓰나?

Client Credentials

[그림4. Client Credentials Grant 시퀀스 다이어그램]

사람의 동의가 아니라 클라이언트 자신의 권한으로 서버 간 API를 호출할 때 사용한다. 예를 들어 내부 정산 서비스가 자신에게 허용된 배치 API를 호출한다. 사용자 계정으로 행동하는 흐름과 혼동하면 토큰의 주체를 잘못 해석할 수 있다. 클라이언트 자격 증명은 서버에서 보관해야 한다.

Device Authorization Grant

브라우저 입력이 불편한 TV나 콘솔은 장치에서 인증을 끝내려 하지 않고, 사용자에게 별도 기기에서 방문할 URL과 코드를 보여 줄 수 있다. 장치는 승인 완료를 토큰 엔드포인트에 주기적으로 확인한다. 폴링 간격과 만료 처리는 RFC 8628에 정의되어 있다.

Refresh Token

접근 토큰이 만료됐을 때 클라이언트가 refresh token으로 새 토큰을 요청하는 절차다. refresh token은 항상 발급되는 것이 아니며, 새 접근 토큰을 받는 순간 기존 접근 토큰이 반드시 무효화되는 것도 아니다. 회전·재사용 탐지·철회 정책은 인증 서버 설정과 클라이언트 유형에 따라 확인해야 한다. refresh token을 자원 서버에 보내지 않는다.

예전 그림에서 주의할 흐름

Implicit Grant

[그림2. Implicit Grant 시퀀스 다이어그램]

이 방식은 승인 응답에 접근 토큰을 직접 담는다. 초기 OAuth 2.0에서는 브라우저 기반 클라이언트의 선택지였으나, 토큰 유출·재사용 위험 때문에 현재 보안 모범 사례는 사용을 피하고 Authorization Code를 권장한다. 위 그림은 레거시 흐름을 이해하기 위한 자료다. 그림의 토큰 검증 단계가 모든 클라이언트에 공통으로 요구되는 절차라는 뜻은 아니다.

Resource Owner Password Credentials

[그림3. Resource Owner Password Credentials Grant 시퀀스 다이어그램]

클라이언트가 사용자 아이디와 비밀번호를 직접 받아 토큰으로 교환하는 방식이다. “신뢰할 수 있는 클라이언트면 써도 된다”는 오래된 설명은 현재 기준에 맞지 않는다. RFC 9700은 이 grant를 사용하지 말아야 한다(MUST NOT)고 명시한다. 비밀번호가 더 많은 시스템에 노출되고, 다단계 인증 같은 현대적 인증 흐름과도 맞지 않는다.

실제 연동 체크

API를 호출할 때는 인증 서버가 발급한 토큰을 자원 서버에 전달하고, 자원 서버는 요청마다 해당 API에 필요한 권한을 검증한다. 401이 나오면 토큰 만료·잘못된 토큰을, 403이면 권한 부족을 우선 점검하되 공급자 문서의 오류 계약을 따른다. 토큰, 승인 코드, state와 code_verifier를 로그나 분석 도구로 흘리지 않도록 전송·저장 위치를 확인한다. 보안은 grant 이름 하나를 고르는 것으로 끝나지 않는다.

참고: RFC 6749: OAuth 2.0, RFC 9700: OAuth 2.0 Security Best Current Practice, RFC 8628: Device Authorization Grant

같은 카테고리의 글