보안

OAuth 2.0 및 OpenID Connect 심층 분석과 안전한 구현 가이드

강코의 코딩 일기 2026. 6. 6. 08:31
반응형

OAuth 2.0과 OpenID Connect의 핵심 원리, 동작 방식, 보안 취약점 및 안전한 구현 전략을 심층 분석하여 개발자가 신뢰할 수 있는 인증/인가 시스템을 구축하도록 돕습니다.

분산 시스템 환경에서 사용자 인증 및 권한 부여는 현대 웹 및 모바일 애플리케이션 개발의 핵심 요소이다. 수많은 서비스가 서로 연동되는 복잡한 생태계에서, 사용자 데이터를 안전하게 보호하면서도 편리한 접근성을 제공하는 것은 개발자와 사용자 모두에게 중요한 과제이다. 이 과정에서 OAuth 2.0OpenID Connect (OIDC)는 사실상의 표준으로 자리매김하였다. 그러나 이들 프로토콜의 복잡성으로 인해 잘못된 이해나 구현은 심각한 보안 취약점으로 이어질 수 있다. 과연 우리는 이 강력한 도구들을 안전하고 효과적으로 활용하고 있는가?

OAuth 2.0 및 OpenID Connect 심층 분석과 안전한 구현 가이드 - toddler hand, child's hand, hand, trust, hands, closeness, affection, hold tight, security, keep, support, prop up, connection, contact, close, relationship, connect, together, love, connect competition, trust, trust, trust, trust, trust, security, security, security, support, support, connection

Image by Myriams-Fotos on Pixabay

OAuth 2.0의 본질: 위임된 권한 관리

OAuth 2.0은 사용자의 자격 증명을 공유하지 않고도 특정 리소스에 대한 접근 권한을 안전하게 위임할 수 있도록 설계된 인가(Authorization) 프레임워크이다. 이는 사용자가 자신의 정보(예: 소셜 미디어 프로필, 클라우드 저장소 파일)를 제3자 애플리케이션과 공유하고자 할 때, 자신의 아이디와 비밀번호를 직접 제공하는 대신, 해당 리소스에 대한 접근 권한만을 부여하는 메커니즘을 제공한다.

OAuth 2.0 핵심 역할 및 흐름 이해

OAuth 2.0은 네 가지 핵심 역할로 구성된다:

  • 리소스 소유자(Resource Owner): 보호된 리소스의 소유자이자 해당 리소스에 대한 접근 권한을 부여할 수 있는 사용자이다.
  • 클라이언트(Client): 리소스 소유자의 승인을 받아 보호된 리소스에 접근하려는 애플리케이션이다. 웹 애플리케이션, 모바일 앱, 백엔드 서비스 등이 될 수 있다.
  • 인가 서버(Authorization Server): 리소스 소유자를 인증하고, 클라이언트에게 접근 권한을 부여하는 서버이다. 접근 토큰(Access Token)을 발급한다.
  • 리소스 서버(Resource Server): 보호된 리소스를 호스팅하는 서버이다. 클라이언트로부터 받은 접근 토큰의 유효성을 검증하여 리소스 접근을 허용하거나 거부한다.

일반적인 OAuth 2.0 흐름은 다음과 같은 단계로 진행된다:

  1. 클라이언트가 리소스 소유자에게 리소스 접근 권한을 요청한다.
  2. 리소스 소유자는 인가 서버로 리다이렉트되어 인증 및 권한 부여 여부를 결정한다.
  3. 리소스 소유자가 클라이언트에게 권한 부여를 승인하면, 인가 서버는 클라이언트에게 인가 코드(Authorization Code)를 발급한다.
  4. 클라이언트는 이 인가 코드를 인가 서버에 제시하여 접근 토큰(Access Token)을 요청한다.
  5. 인가 서버는 클라이언트의 유효성을 검증한 후 접근 토큰과 선택적으로 갱신 토큰(Refresh Token)을 발급한다.
  6. 클라이언트는 접근 토큰을 사용하여 리소스 서버에 보호된 리소스 접근을 요청한다.
  7. 리소스 서버는 접근 토큰의 유효성을 검증하고, 유효한 경우 요청된 리소스를 클라이언트에게 제공한다.

주요 Grant Type 분석 및 선택 기준

OAuth 2.0은 다양한 시나리오에 맞춰 여러 Grant Type (권한 부여 방식)을 제공한다. 각 방식은 클라이언트의 특성과 보안 요구사항에 따라 적절히 선택되어야 한다.

  • Authorization Code Grant (인가 코드 방식): 가장 일반적이고 가장 안전하다고 평가되는 방식이다. 클라이언트가 직접적으로 사용자 자격 증명이나 접근 토큰을 다루지 않아 중간자 공격 위험이 낮다. 웹 애플리케이션에 주로 사용된다.
  • Client Credentials Grant (클라이언트 자격 증명 방식): 리소스 소유자의 개입 없이 클라이언트 자체가 리소스 소유자 역할을 하는 경우에 사용된다. 주로 서버 간 통신, 즉 특정 애플리케이션이 자신의 리소스에 접근하거나 다른 서비스의 API를 호출할 때 활용된다.
  • Implicit Grant (암시적 방식): 과거에는 클라이언트 측(브라우저 기반) 애플리케이션에서 사용되었으나, 보안 취약점(토큰이 URL에 노출될 수 있음)으로 인해 사용이 권고되지 않는다. 대신 PKCE가 적용된 Authorization Code Grant가 권장된다.
  • Resource Owner Password Credentials Grant (리소스 소유자 비밀번호 자격 증명 방식): 클라이언트가 사용자의 아이디와 비밀번호를 직접 받아 인가 서버에 전달하는 방식이다. 이는 높은 신뢰를 요구하며, 보안상 위험이 매우 크므로 특별한 경우가 아니면 사용해서는 안 된다. 주로 클라이언트가 리소스 소유자와 동일한 조직에 속하고, 레거시 시스템과의 통합 등 매우 제한적인 상황에서만 고려될 수 있다.

OpenID Connect: 인증 계층의 추가

OpenID Connect (OIDC)는 OAuth 2.0 프로토콜 위에 구축된 인증(Authentication) 계층이다. OAuth 2.0은 인가 프레임워크로서 '누가 누구에게 무엇을 할 수 있는가?'에 초점을 맞춘다면, OIDC는 '사용자가 누구인가?'라는 질문에 답하기 위해 설계되었다. 즉, OIDC는 사용자 신원 정보를 클라이언트에게 안전하게 전달하는 표준 방식을 제공한다.

OAuth 2.0 위에서 동작하는 OIDC

OIDC는 OAuth 2.0의 인가 흐름을 그대로 활용하면서, 몇 가지 추가적인 기능을 정의한다. 가장 중요한 추가 기능은 ID 토큰(ID Token)의 도입이다. 인가 서버는 접근 토큰을 발급할 때, 사용자 신원 정보가 담긴 ID 토큰도 함께 발급한다. 이 ID 토큰은 JWT(JSON Web Token) 형식으로 서명되어 있으며, 클라이언트는 이를 통해 사용자의 신원을 검증할 수 있다.

ID Token과 UserInfo Endpoint의 역할

  • ID Token: 사용자 인증 정보를 포함하는 JWT이다. 클라이언트는 ID 토큰을 파싱하고 서명을 검증하여 사용자가 성공적으로 인증되었음을 확인하며, 토큰 내의 클레임(claims)을 통해 사용자의 고유 식별자(sub), 이름(name), 이메일(email) 등의 기본 프로필 정보를 얻을 수 있다. ID 토큰은 주로 클라이언트가 사용자의 신원을 확인하는 데 사용되며, 토큰 자체에 민감한 정보는 최소한으로 포함하는 것이 일반적이다.
  • UserInfo Endpoint: ID 토큰에 포함되지 않은 추가적인 사용자 프로필 정보가 필요한 경우, 클라이언트는 접근 토큰을 사용하여 인가 서버의 UserInfo Endpoint에 요청을 보낼 수 있다. 이 엔드포인트는 표준화된 방식으로 사용자 정보를 JSON 형식으로 반환한다. 이는 클라이언트가 필요한 사용자 정보를 유연하게 가져올 수 있도록 돕는다.

OIDC를 통해 클라이언트는 단일 로그인(SSO) 환경을 구축하고, 다양한 서비스에서 일관된 사용자 경험을 제공할 수 있다. 예를 들어, 구글, 페이스북, 카카오 등에서 제공하는 '로그인' 기능은 대부분 OIDC를 기반으로 동작한다.

OAuth 2.0 및 OIDC의 보안 위협과 취약점

OAuth 2.0과 OIDC는 강력한 보안 메커니즘을 제공하지만, 잘못 구현되거나 특정 공격 시나리오에 노출될 경우 심각한 취약점을 야기할 수 있다. 주요 보안 위협은 다음과 같다.

  • 리다이렉트 URI 조작 (Redirect URI Manipulation): 인가 서버는 인가 코드 또는 접근 토큰을 발급한 후, 미리 등록된 클라이언트의 리다이렉트 URI로 리다이렉트한다. 이때 악의적인 공격자가 이 URI를 조작하여 인가 코드나 토큰을 가로챌 수 있다.
  • CSRF (Cross-Site Request Forgery) 공격: state 파라미터가 사용되지 않거나 제대로 검증되지 않을 경우, 공격자가 사용자의 세션을 가로채 인가 요청을 위조할 수 있다.
  • 인가 코드 탈취 (Authorization Code Interception): 특히 퍼블릭 클라이언트(모바일 앱, SPA 등)에서 인가 코드가 중간에 탈취될 경우, 공격자가 이를 이용하여 접근 토큰을 발급받을 수 있다.
  • PKCE (Proof Key for Code Exchange) 미적용: 퍼블릭 클라이언트에서 Authorization Code Grant를 사용할 때 PKCE를 적용하지 않으면, 인가 코드가 탈취되었을 때 공격자가 손쉽게 접근 토큰을 획득할 수 있다.
  • Scope 오용 또는 과도한 권한 부여: 클라이언트가 필요 이상의 권한(Scope)을 요청하거나, 인가 서버가 사용자에게 과도한 권한을 부여하도록 허용할 경우, 클라이언트가 침해당했을 때 피해 범위가 확대될 수 있다.
  • 토큰 탈취 및 재사용 (Token Theft and Replay): 접근 토큰이나 갱신 토큰이 탈취될 경우, 공격자가 이를 이용하여 사용자 리소스에 지속적으로 접근할 수 있다. 특히 갱신 토큰은 유효 기간이 길어 더 큰 위험을 초래할 수 있다.
  • Client Secret 노출: 클라이언트 비밀 키(Client Secret)가 노출되면 공격자가 클라이언트인 척 위장하여 인가 서버와 통신할 수 있다.
  • ID Token 변조 및 위조: OIDC에서 ID Token의 서명 검증이 제대로 이루어지지 않으면, 공격자가 위조된 ID Token을 클라이언트에게 전달하여 사용자를 속일 수 있다.
OAuth 2.0 및 OpenID Connect 심층 분석과 안전한 구현 가이드 - man, face, facial recognition, biometric, identify, security, people, authentication, identification, database, scanning, facial recognition, facial recognition, facial recognition, facial recognition, facial recognition, biometric

Image by Tumisu on Pixabay

안전한 OAuth 2.0 및 OIDC 구현 가이드라인

앞서 언급된 보안 위협을 방지하고 안전한 시스템을 구축하기 위한 핵심 가이드라인은 다음과 같다.

  • PKCE (Proof Key for Code Exchange) 강제 적용: 퍼블릭 클라이언트(SPA, 모바일 앱)에서는 반드시 PKCE를 Authorization Code Grant와 함께 사용해야 한다. PKCE는 인가 코드가 중간에 탈취되더라도 공격자가 접근 토큰을 발급받지 못하도록 방지하는 역할을 한다. 클라이언트는 인가 요청 시 code_challenge를 생성하여 전송하고, 토큰 요청 시 code_verifier를 함께 전송하여 인가 서버가 이를 검증하도록 한다.
  • Redirect URI 화이트리스트 관리: 인가 서버는 클라이언트가 미리 등록한 정확한 Redirect URI 목록에 대해서만 리다이렉트를 허용해야 한다. 와일드카드 사용은 피하고, 완전한 URI를 등록하여 조작 공격을 방지한다.
  • state 파라미터 활용: 모든 인가 요청 시 예측 불가능한 state 파라미터를 생성하여 세션에 저장하고, 콜백 시 받은 state 값과 비교하여 CSRF 공격을 방지해야 한다.
  • Scope 최소화 원칙: 클라이언트는 필요한 최소한의 권한(Scope)만을 요청해야 한다. 사용자가 부여하는 권한의 범위가 좁을수록, 클라이언트가 침해당했을 때의 피해를 최소화할 수 있다.
  • 토큰 관리 전략 수립:
    • Access Token: 짧은 유효 기간을 설정하고, 만료 시 Refresh Token을 사용하여 재발급받도록 한다. 탈취 시 피해를 줄이기 위함이다.
    • Refresh Token: 긴 유효 기간을 가질 수 있으므로, 재사용 방지 및 폐기 메커니즘(Revocation)을 반드시 구현해야 한다. 또한, Refresh Token은 절대 클라이언트 측 저장소(예: 로컬 스토리지)에 저장해서는 안 되며, 보안이 강화된 저장소(예: HttpOnly 쿠키, 서버 사이드 저장소)에 안전하게 보관해야 한다.
  • Client Secret 안전한 관리: Confidential Client(서버 측 애플리케이션)의 Client Secret은 절대 외부에 노출되어서는 안 된다. 환경 변수, 키 관리 시스템(KMS) 등을 통해 안전하게 관리하고, 소스 코드에 직접 하드코딩하는 것을 피해야 한다. 퍼블릭 클라이언트는 Client Secret을 사용할 수 없으므로, PKCE가 더욱 중요해진다.
  • HTTPS/TLS 강제 적용: 모든 OAuth 2.0 및 OIDC 통신(인가 요청, 토큰 요청, 리소스 요청)은 반드시 HTTPS/TLS를 통해 암호화되어야 한다. 이는 중간자 공격(Man-in-the-Middle)을 방지하는 가장 기본적인 보안 조치이다.
  • 입력 유효성 검사 및 에러 처리: 인가 서버와 클라이언트 모두 모든 입력 파라미터에 대해 철저한 유효성 검사를 수행해야 한다. 악의적인 입력에 대한 적절한 에러 처리 및 로깅은 공격 탐지에 필수적이다.
  • ID Token 서명 검증: OIDC 클라이언트는 수신한 ID Token의 서명(Signature)을 반드시 검증하여 토큰의 무결성과 신뢰성을 확인해야 한다. JWKS(JSON Web Key Set) Endpoint를 통해 공개 키를 가져와 검증하는 것이 표준적인 방법이다.
{
  "iss": "https://accounts.google.com",
  "azp": "YOUR_CLIENT_ID.apps.googleusercontent.com",
  "aud": "YOUR_CLIENT_ID.apps.googleusercontent.com",
  "sub": "100000000000000000000",
  "email": "user@example.com",
  "email_verified": true,
  "at_hash": "some_hash_value",
  "name": "User Name",
  "picture": "https://lh3.googleusercontent.com/a/some_picture",
  "given_name": "User",
  "family_name": "Name",
  "locale": "ko",
  "iat": 1678886400,
  "exp": 1678890000
}

위 예시는 일반적인 ID Token의 페이로드(Payload) 구조를 보여준다. iss (발급자), sub (주제, 고유 식별자), aud (대상 수신자), exp (만료 시간) 등의 클레임은 OIDC 표준에 따라 반드시 포함되어야 한다.

OAuth 2.0 및 OpenID Connect 심층 분석과 안전한 구현 가이드 - io centers, security, access card, access card, access card, access card, access card, access card

Image by websubs on Pixabay

OAuth 2.0 vs OpenID Connect: 명확한 차이점 비교

두 프로토콜의 관계와 차이점을 명확히 이해하는 것은 안전한 시스템 설계를 위해 매우 중요하다.

특징 OAuth 2.0 OpenID Connect
주요 목적 인가(Authorization): 사용자의 리소스 접근 권한을 위임 인증(Authentication): 사용자 신원 확인 및 프로필 정보 획득
제공하는 핵심 정보 Access Token: 리소스 접근 권한 증명 ID Token: 사용자 신원 증명 (JWT 형식)
프로토콜 계층 독립적인 인가 프레임워크 OAuth 2.0 프로토콜 위에 구축된 인증 계층
주요 사용 사례 외부 서비스의 API 접근 (예: Google Drive, Twitter API) 통합 로그인 (SSO), 사용자 신원 확인 (예: Google Login, Kakao Login)
사용자 정보 획득 리소스 서버를 통해 접근 토큰으로 특정 리소스 획득 ID Token 클레임 및 UserInfo Endpoint를 통해 표준화된 사용자 프로필 획득

요약하자면, OAuth 2.0은 '문 열쇠'를 주는 것이 아니라 '문 열 수 있는 권한 카드'를 주는 것이며, OIDC는 그 권한 카드와 더불어 '이 카드를 사용하는 사람이 누구인지'를 증명하는 신분증을 함께 제공하는 것으로 이해할 수 있다.

결론 및 추가 고려사항

OAuth 2.0과 OpenID Connect는 현대 분산 시스템의 인증 및 인가를 위한 강력하고 유연한 표준이다. 이들을 통해 사용자 경험을 향상시키고, 민감한 정보를 안전하게 보호하면서 서비스 간의 원활한 연동을 가능하게 한다. 그러나 그 복잡성으로 인해 잘못된 구현은 심각한 보안 취약점을 초래할 수 있다. PKCE 적용, Redirect URI 화이트리스트 관리, state 파라미터 활용, Scope 최소화, 토큰 안전 관리, HTTPS 강제 적용 등 핵심 보안 가이드라인을 철저히 준수하는 것이 무엇보다 중요하다.

개발자는 각 프로토콜의 본질적인 목적과 동작 방식을 명확히 이해하고, 각자의 애플리케이션 환경과 보안 요구사항에 맞는 Grant Type 및 구현 전략을 신중하게 선택해야 한다. 또한, OIDC를 사용하는 경우 ID Token의 서명 검증과 UserInfo Endpoint 활용에 대한 정확한 이해를 바탕으로 안전한 사용자 신원 확인을 보장해야 한다. 보안은 한 번의 설정으로 끝나는 것이 아니라 지속적인 검토와 업데이트가 필요한 영역임을 명심해야 한다. 이 글에서 제시된 가이드라인이 여러분의 안전한 OAuth 2.0 및 OpenID Connect 구현에 실질적인 도움이 되기를 바란다.

OAuth 2.0 및 OpenID Connect 구현 과정에서 겪었던 어려움이나 성공적인 경험이 있다면 댓글로 공유해 주시기 바랍니다.

📌 함께 읽으면 좋은 글

  • [보안] 민감 데이터 보호를 위한 데이터 암호화와 키 관리 전략 완벽 가이드
  • [보안] CI/CD 보안 자동화: SAST, DAST, SCA 통합으로 안전한 개발 파이프라인 구축
  • [튜토리얼] Nx 워크스페이스 모노레포 프로젝트 설정 및 효율적 관리 가이드

이 글이 도움이 되셨다면 공감(♥)댓글로 응원해 주세요!
궁금한 점이나 다루었으면 하는 주제가 있다면 댓글로 남겨주세요.

반응형