OpenId Provier 구축 공부 - 1편 (OAuth 2.0)

Posted by yunki kim on February 13, 2025

현재 회사에서 통합회원플랫폼에서 인증/인가 서버 구축을 담당하면서 기존에 간단한 개념만 알고 있었던 인증/인가와 관련된 지식들을 제대로 공부할 기회가 생겼다. 공부한 내용들을 정리해보고자 한다.

현재 구현하는 통합회원플랫폼은 회사 내부의 회원 뿐만 아니라 여러 자회사를 포함한 여러 회사의 서비스에 있는 회원들을 통합해 관리하는 플랫폼이다. 여러 사이트에서 볼 수 있는 “카카오로 로그인하기”, “구글로 로그인하기” 버튼 뒷단에서 돌아가는 프로세스 전체를 구축해야 한다. 때문에 “OpenId Provider 구축 공부”라는 제목으로 올라오는 글들은 대부분 OIDC, OAuth 토큰과 관련된 내용이 될 예정이다.

1. OAuth 2.0은 무엇인가

  • 자신이 소유한 리소스에 SW가 접근할 수 있게 접근 권한을 위임해주는 프로토콜이다
    • OAuth 토큰으로 클라이언트의 접근 권한을 리소스 소유자가 허용한 범위로 제한할 수 있다
  • OAuth2.0 표준 스펙인 RFC6749에 따르면, OAuth2.0은 다음과 같이 정의되어있다.
    • OAuth 2.0 인가 프레임워크는 리소스 소유자를 대신해 HTTP 서비스와 리소스에 대한 접근 요청 승인을 조정하한다. 또한, 리소스 소유자를 대신해 서드파티 애플리케이션에게 리소스에 대한 접근을 허용해주는 방식으로 HTTP 서비스에 대한 서드파티 애플리케이션의 접근을 가능하게 해준다.
    • 요약: OAUth는 시스템 A의 구성요소가 시스템 B의 구성요소에 접근 권한을 얻을 수 있게 해준다. 즉, 사용자가 보호된 리소스에 대한 자신의 접근 권한 일부를 클라이언트 애플리케이션에게 위임하기 위한 프로토콜이다. 때문에 OAuth 시스템에서는 인가 서버라는 구성 요소가 포함된다.
  • OAuth 2.0 구성원
    • 리소스 소유자
      • API에 대한 접근 권한을 갖고 있고, 위임할 수 있는 주체. 클라이언트 소프트웨어를 이용하는 사람.
    • 보호된 리소스
      • 리소스 소유자가 접근하는 구성 요소. 대부분 웹 API 형태를 지닌다
    • 인가 서버
      • 보호된 리소스가 신뢰하는 서버. OAuth Access token을 클라이언트에게 발급한다.
      • 리소스 소유자와 클라이언트를 인증하고, 리소스 소윶자가 클라이언트에게 권한을 위임할 수 있는 매커니즘을 제공한다.
      • 인가 결정을 기억하거나, 토큰에 대한 자기 검증을 제공하는 경우도 있다.
    • 클라이언트
      • 리소스 소유자를 대신해 보호된 리소스에 접근하는 소프트웨어.
      • OAuth 2.0에서 말하는 클라이언트는 웹 브라우저가 아니다. 클라이언트란 보호된 리소스를 구성하는 API를 이용하는 SW이다. → OAuth를 통해 클리이언트는 리소스 소유자 대신 보호된 리소스에 대한 접근 권한을 획득한다.
  • OAuth의 구성 요소
    • OAuth의 구성 요소는 OAuth 구성원을 연결하는 역할을 한다
    • Access Token
      • 클라이언트에게 권한이 위임됐다는 것을 나타내기 위해 인가 서버가 발급하는 토큰이다. OAuth 스펙에서는 토큰 포맷을 정의하고 있지 않지만, 항상 클라이언트가 요청한 접근 권한, 리소스 소유자의 클라이언트 인가, 인가 과정에서 클라이언트에게 부여된 권한을 나타내야 한다.
      • 클라이언트 입장에서 액세스 토큰의 형식은 명확하지 않다. 이는 클라이언트를 더 단순화하고, 인가 서버와 보호된 리소스는 토큰을 배포하는 방법에 있어 엄청난 유연성을 지닌다.
    • Scope
      • 보호된 리소스에 대한 접근 권한을 나타낸다.
      • Scope은 공백으로 구분된 범위 문자열의 조합이다.
    • Refresh Token
      • 리프레시 토큰은 액세스토큰 폐기 또는 만료로 인해, 더 이상 액세스 토큰을 사용할 수 없게 되었을 때 액세스 토큰 재발급 용으로 사용된다.
      • 리프레시 토큰은 보호된 리소스에 전달되지 않는다.
      • OAuth 1.0에서는 리프레시 토큰을 지원하지 않아서, 만료 시간 없는 액세스 토큰을 사용하기도 했다. 이는 토큰 탈취를 위한 공격 증가로 이어졌다.
    • Authorization grant
      • OAuth 프로토콜을 잉요해 OAuth 클라이언트에게 보호된 리소스에 대한 접근 권한을 위임해주는 방법이다. 성공한다면 클라이언트는 액세스 토큰을 얻게 된다.

2. 왜 OAuth 2.0을 사용해야 하나

  • OAuth를 사용하지 않았을 때의 문제점
    • OAuth 프로토콜이 없는 채로 사용할 수 있는 가장 쉬운 방식은 사용자가 클라이언트에게 나의 로그인 정보를 주는 것이다. 이 경우 다음과 같은 문제가 발생한다 .
      • 클라이언트는 사용자가 위임한 id/password를 평문으로 저장해야 한다
        • 클라이언트가 침해되면 사용자의 계정도 침해된다.
        • multi-factor 로그인을 지원하는 서비스는 클라이언트가 id/password 만으로 로그인할 수 없다.
        • 클라이언트가 리소스 소유자로 가장하기 때문에 보호된 리소스 입장에서는 누가 API를 호출하는 것인지 알 수 없다. → 때문에 특정 클라이언트에게는 read 권한만 주는 등 리소스 소유자가 자신 리소스에 대한 접근 권한을 통제할 수 없다.
      • 서드파티 별로 전용 비밀번호를 생성해 사용한다
        • 리소스 소유자가 모든 비밀번호를 관리해야 한다.
  • OAuth를 사용하면
    • 리소스 소유자의 자격 증명이 클라이언트에게 노출되지 않는다. 클라이언트는 토큰을 요청하고, 리소스 소유자가 인가 서버와 통신해 클라이언트를 인가해서 클라이언트에게 접근 권한을 부여한다.
  • OAuth 사용 시 장점
    • 클라이언트는 클라이언트의 자격 증명과 토큰만 안전하게 관리하면 된다
    • 클라이언트 침해로 인한 피해는 클라이언트 사용자로 국한된다
      • 리소스 소유자의 자격 증명 데이터는 유출되지 않는다
    • 인가 서버의 복잡성이 증가(시스템 상의 모든 클라이언트와 사용자에 대한 자격 증명, 토큰을 관리해야 한다)한다. 하지만, 수천개의 클라이언트를 관리하는 것 보다는 인가 서버 하나를 관리하는 것이 더 편리하다.
  • OAuth는 인증 프로토콜이 아니다
    • OAuth 트랜잭션 자체만으로 사용자가 누구인지 알 수 없다.
      • 트랜잭션은 다음과 같은 절차를 포함한다 oauth transaction
    • OAuth는 사용자가 누구인지를 판단하지 않고, 어떤 리소스에 접근 권한이 있는지만 허락한다.
      • 물론, 이 과정에서 인증을 사용한다. 특히, 인가 서버가 리소스 소유자, 클라이언트를 인증할 때 인증을 사용한다. 하지만, 내제된 인증 만으로는 OAuth가 인증 프로토콜이 되지 않는다.
  • 위 OAuth 트랜잭션을 인가 코드 그랜트(Authorization Code Grant) 방식으로 설명하면 다음과 같다 oauth transaction_with_auth_code_grant