OAuth

OAuth

도구

다른 서비스에 비밀번호를 넘기지 않고 필요한 권한만 기한을 붙여 빌려주도록 정한 표준입니다.

등장 배경

2000년대 중반, 웹 서비스가 서로 연결되기 시작하면서 난처한 화면이 하나 생겼습니다. 새로 가입한 서비스가 "아는 사람을 찾아 드릴게요" 라며 메일 계정의 아이디와 비밀번호를 그 자리에서 적어 넣으라고 요구하는 화면이었습니다. 사용자가 내주려던 것은 주소록이었는데 실제로 건네는 것은 메일함 전체를 여는 열쇠였습니다.

건넨 뒤에는 되돌릴 방법도 없었습니다. 그 서비스를 그만 쓰기로 해도 비밀번호는 이미 상대 서버에 저장돼 있었고, 끊는 유일한 방법은 메일 비밀번호를 바꾸는 것이었습니다. 그러면 같은 비밀번호를 줘 둔 다른 서비스 네 곳이 한꺼번에 멈췄습니다. 그중 한 곳이 뚫리면 나머지가 같이 열렸습니다.

문제의 뿌리는 확인과 허가를 구분하지 않은 데 있었습니다. 비밀번호는 본인임을 확인하는 수단인데, 그것을 남에게 주는 순간 상대는 본인이 할 수 있는 일을 전부 할 수 있게 됩니다. 필요했던 것은 "이 서비스가 내 주소록만 읽게 해 달라" 는 말을 기계가 알아들을 형태로 적어 두는 방법이었습니다. OAuth 는 그 형태를 표준으로 정한 결과이고, 2007년에 초안이 나와 2012년에 지금 쓰는 2.0 판이 확정됐습니다.

해결하는 문제

비밀번호를 건네지 않고도 다른 서비스가 내 데이터의 일부에만 닿게 하는 일을 해결합니다. 한 번에 네 가지가 따라옵니다.

  1. 범위 제한 — 허가증에 무엇을 해도 되는지 적습니다. 스코프라고 부르고 "캘린더 읽기" 처럼 한 줄씩 나열합니다. 읽기만 적힌 허가증으로는 일정을 지울 수 없습니다.
  2. 철회 — 사용자가 계정 설정에서 연결 끊기를 누르면 그 허가증만 무효가 됩니다. 다른 서비스에 준 허가증은 그대로 살아 있습니다.
  3. 만료 — 허가증에는 유효 기간이 붙습니다. 짧게는 한 시간짜리를 쓰고 기간이 지나면 갱신용 토큰으로 새로 받습니다. 새 나간 값이 영영 쓸모 있는 상태로 남지 않습니다.
  4. 비밀번호 비공개 — 권한을 빌려주는 쪽은 비밀번호를 한 번도 보지 않습니다. 저장할 일도, 바꿀 때 연락할 일도 없습니다.

작동 순서는 네 단계입니다. 페이지덱이 구글 캘린더 일정을 문서에 끼워 넣는 기능을 붙인다고 해 보겠습니다.

  1. 사용자가 페이지덱에서 캘린더 연결 버튼을 누르면 브라우저가 구글 화면으로 옮겨 갑니다.
  2. 사용자는 그 화면에서 비밀번호를 입력합니다. 화면을 띄운 쪽이 구글이라 페이지덱은 거기 적힌 값을 볼 수 없습니다. 같은 화면에 페이지덱이 요청한 권한 목록이 함께 뜹니다.
  3. 허용을 누르면 구글이 페이지덱 서버로 짧은 인가 코드를 하나 돌려보냅니다. 토큰이 아니라 코드를 먼저 주는 이유는 브라우저 주소창을 거쳐 가는 값에 진짜 열쇠를 싣지 않기 위해서입니다.
  4. 페이지덱 서버가 그 코드를 자기만 아는 비밀 키와 함께 구글에 보내 액세스 토큰으로 바꿉니다. 이후 캘린더를 읽을 때마다 이 토큰을 붙여 보냅니다.

여기서 오가는 토큰은 인가의 결과물입니다. 요청한 사람이 누구인지 확인하는 인증과는 다른 일입니다. 로그인까지 다루려면 OpenID Connect 라는 규격을 한 겹 더 얹습니다. 구글 계정으로 가입하는 소셜 로그인이 바로 이 조합입니다.

대안

대안은 크게 셋이고, 어느 쪽을 쓸지는 권한을 누구에게 빌려주느냐로 갈립니다.

첫째는 사용자의 비밀번호를 직접 받아 저장하는 방식입니다. 만들기는 가장 쉽습니다. 다만 등장 배경에 적힌 문제가 그대로 돌아오고, 상대 서비스가 다중 인증을 켜 두면 아예 작동하지 않습니다. 은행 계좌를 긁어 오던 옛 가계부 앱들이 이 방식이었고 지금은 대부분 정식 연동으로 옮겼습니다.

둘째는 API 키입니다. 서비스가 긴 문자열 하나를 발급하고 요청할 때마다 그 값을 붙이는 방식입니다. 사람이 허용을 누르는 절차가 없어 서버끼리 주고받는 자동화에 잘 맞습니다. 대신 키 하나에 계정의 모든 권한이 걸리는 경우가 많고, 만료가 없어 한 번 새 나가면 사람이 알아채고 폐기할 때까지 유효합니다. 결제 대행사 연동처럼 서버끼리만 관여하는 자리에 씁니다.

셋째는 회사 계정 체계에 얹는 방식입니다. 사내 도구 열 개에 직원이 각각 가입하는 대신 회사 계정 하나로 통과시키고, 퇴사할 때 그 계정만 막습니다. 다만 이 방식은 우리 조직 구성원에게만 통합니다. 외부 사용자가 자기 구글 계정의 데이터를 빌려주는 상황은 여전히 OAuth 의 자리입니다.

실무 용례

"이거 로그인 붙이는 거 아니고 권한만 받아 오는 거예요. 스코프 두 개만 요청합시다."

필요 이상으로 권한을 요청하면 허용 화면에서 사용자가 멈춘다는 경고입니다.

"리프레시 토큰을 평문으로 저장해 두면 그게 비밀번호랑 뭐가 다른가요."

만료 없는 갱신용 토큰은 사실상 장기 열쇠라 암호화해 보관하라는 지적입니다.

"그 계정 연결이 끊겨서 동기화가 멈췄네요. 다시 허용 눌러 달라고 안내 보낼게요."

사용자가 허가를 철회했거나 기한이 지나 토큰이 죽었다는 뜻입니다.

페이지덱이 캘린더 연동을 처음 붙일 때 태오는 요청할 권한 목록을 두 번 줄였습니다. 처음 적어 둔 목록에는 일정 쓰기와 참석자 목록 읽기가 들어 있었는데, 실제로 필요한 것은 제목과 시간뿐이었습니다. 목록을 줄이자 허용 화면에서 되돌아 나가는 사람이 눈에 띄게 줄었습니다.

흔한 오해

로그인 방식의 한 종류로 읽는 경우가 가장 많습니다. 구글 계정으로 로그인 버튼이 이 표준 위에 올라가 있으니 그렇게 보입니다. 이 표준이 정하는 것은 권한을 빌려주고 돌려받는 절차이고, 누구인지 알려 주는 항목은 규격에 없습니다. 이 차이를 모르고 만들면 토큰이 유효하다는 이유로 로그인을 통과시키는 코드가 나오고, 다른 서비스용으로 발급된 토큰을 넣어 남의 계정에 들어가는 길이 열립니다. 신원이 필요하면 OpenID Connect 를 얹어 발급되는 신원 토큰을 따로 검사합니다.

허가증을 받아 뒀으니 사용자 데이터를 계속 쓸 수 있다고 여기는 것도 흔합니다. 토큰은 사용자가 언제든 끊을 수 있고, 제공자 쪽 정책이 바뀌어 스코프가 통째로 사라지기도 합니다. 연동을 데이터베이스처럼 믿고 설계하면 끊긴 순간 기능 하나가 멈춥니다. 끊겼을 때 무엇을 보여 줄지를 붙이는 시점에 함께 정해 둡니다.

자주 헷갈리는 용어

용어무엇을 정하는가OAuth 와의 차이
싱글 사인온한 번 로그인으로 여러 서비스를 쓰게 하는 방식목적이 다릅니다. 이쪽은 같은 조직 안에서 로그인 횟수를 줄이는 일이고, OAuth 는 남의 서비스에 권한 일부를 빌려주는 일입니다
JWT서명된 문자열 하나에 정보를 담아 주고받는 규격절차가 아니라 담는 그릇입니다. OAuth 가 발급하는 토큰이 이 형식일 때가 많지만 다른 형식이어도 됩니다

같이 보면 좋은 페이지

  • 애플리케이션 보안

    접근 제어가 보안 전체에서 어느 자리에 놓이는지 봅니다

  • 인증

    이 표준이 다루지 않는 쪽, 누구인지 확인하는 절차를 봅니다

  • 소셜 로그인

    사용자가 실제로 마주하는 화면 쪽에서 같은 구조를 봅니다

마지막 업데이트 2026-09-16