OAuth 2.0은 사용자의 자격 증명을 직접 노출하지 않고,
타사 서비스가 사용자 데이터를 안전하게 액세스할 수 있도록 설계된 인증 및 권한 위임 프로토콜입니다.
이를 통해 사용자는 내 비밀번호를 직접 제공하지 않고도 Google, Facebook, GitHub 등의 계정을
사용하여 다른 서비스에 로그인하거나, 특정 API 권한을 위임할 수 있습니다.
AI에서 Agent들의 인증 인가를 위해서 개념을 다시한번 정리 한다.
🔹 1. OAuth 2.0의 주요 개념
✅ 1) 클라이언트(Client)
- OAuth를 사용하는 애플리케이션 (예: 쿠팡이 네이버 로그인 기능을 사용할 때, 쿠팡이 클라이언트)
- 사용자 데이터를 직접 저장하지 않으며, 액세스 토큰을 통해 권한을 부여받음
✅ 2) 리소스 소유자(Resource Owner)
- OAuth 인증을 진행하는 사용자 (예: 네이버 로그인 시, 네이버 계정을 가진 사용자)
- 자신의 데이터를 타사 애플리케이션이 접근하도록 승인할 수 있음
✅ 3) 리소스 서버(Resource Server)
- 보호된 리소스를 제공하는 서버 (예: Google Drive, Facebook API, GitHub API)
- 클라이언트가 액세스 토큰을 제공하면 해당 데이터를 반환
✅ 4) 권한 서버(Authorization Server)
- 액세스 토큰을 발급하는 서버 (예: Google OAuth Server, Facebook OAuth Server)
- 클라이언트의 인증 요청을 받아 토큰을 생성하고, 사용자 권한을 검증함
✅ 5) 액세스 토큰(Access Token)
- 클라이언트가 리소스 서버에 접근할 때 사용하는 토큰
- 일반적으로 JWT(JSON Web Token) 형식으로 발급됨
- 특정 유효 기간이 있으며, 만료되면 새로 갱신해야 함
✅ 6) 리프레시 토큰(Refresh Token)
- 액세스 토큰이 만료되었을 때, 사용자의 재승인 없이 새로운 액세스 토큰을 요청하는 데 사용됨
- 리프레시 토큰은 일반적으로 장기간 유효함
🚀 리소스 서버(Resource Server) vs 권한 서버(Authorization Server) 차이점
📌 요약:
- 리소스 서버 = "데이터 제공 (Access Token 필요)"
- 권한 서버 = "사용자 인증 & Access Token 발급"
- 권한서버에서는 토큰을 발급
- 리소스 서버는 토큰을 검증
🔹 리소스 서버 토큰 검증 방식
리소스 서버가 Access Token을 검증
✅ 1) 권한 서버에 검증 요청 (Remote Introspection)
✅ 2) 토큰을 직접 검증 (Local JWT Validation)
- 위 두가지 방법으로 토큰을 검증하는데 보통 리소스 서버에서 토큰을 직접 검증하는 방법을 쓴다
- 권한 서버는 Access Token을 JWT 형식으로 발급한다
- 리소스 서버는 권한 서버의 해석하여 유효성 검증한다
🔹 Google Drive + Notion OAuth 2.0 예제
📌 시나리오:
👉 내가 Notion에서 Google Drive 파일을 연동하려고 함
👉 Notion이 내 Google Drive 파일에 접근할 수 있도록 허용(OAuth 2.0 권한 위임)
📌 OAuth 2.0 역할 정리
역할 예제
클라이언트(Client) | Notion (Google Drive 파일을 접근하려는 서비스) |
리소스 소유자(Resource Owner) | 나 (Google Drive 파일의 주인, 권한을 위임하는 사람) |
사용자(User) | 나 (Notion을 사용하는 사용자, 로그인하는 주체) |
리소스 서버(Resource Server) | Google Drive API (보호된 리소스, 즉 내 파일을 제공하는 서버) |
권한 서버(Authorization Server) | Google OAuth Server (Access Token을 발급하는 서버) |
🚀 OIDC (OpenID Connect)는 OAuth 2.0과 어떤 차이가 있을까?
OAuth 2.0은 "권한 위임(Authorization)"을 위한 프로토콜이지만,
OIDC(OpenID Connect)는 "사용자 인증(Authentication)"을 위한 프로토콜
📌 문제점 (OAuth 2.0만 사용할 때 발생하는 문제)
✅ OAuth 2.0의 Access Token에는 "사용자가 누구인지"에 대한 정보가 없음
✅ 클라이언트가 Access Token만 가지고 있으면, 사용자의 프로필 정보를 확인할 방법이 없음
✅ Access Token은 "특정 API 접근 권한"만 부여할 뿐, 사용자 인증을 보장하지 않음
📌 Access Token을 jwt로 발급할때 사용자 정보를 넣으면 리소스 서버가 jwt를 검증 하면 사용자가 누군지 알수있지 않나? OIDC가 필요 없는 거 아니야?"
🔹 1. Access Token에 사용자 정보를 포함하는 것의 문제점
👉 OAuth 2.0에서 Access Token을 JWT로 발급할 때 사용자 정보를 넣을 수 있지만,
이 방식은 몇 가지 보안 및 설계상 문제를 일으킬 수 있음
❌ 문제 1: 사용자 정보가 토큰에 있으면 변경이 불가능함
- JWT는 한 번 발급되면 내용이 변경되지 않음 (Immutable)
- 만약 사용자가 이름, 이메일을 변경하면?
- 기존 Access Token을 가진 클라이언트(예: Notion)는 여전히 변경 전 정보를 사용하게 됨
📌 예제
1️⃣ 사용자가 Google 계정에서 이름을 "John Doe" → "Jack Doe"로 변경
2️⃣ 기존 Access Token은 "John Doe"로 저장된 상태
3️⃣ Notion이 Google Drive API를 호출하면 여전히 "John Doe"로 보임
✅ OIDC에서는 ID Token을 사용하고, 추가로 /userinfo API를 호출하면 최신 사용자 정보를 받을 수 있음
❌ 문제 2: 보안 위험 (토큰 노출 시 개인 정보 유출)
- Access Token이 JWT로 발급되면서 email, name 같은 사용자 정보가 포함되면, 토큰이 유출될 경우 개인 정보도 함께 노출됨
- JWT는 디코딩(Base64 Decode)이 가능하기 때문에 토큰을 가로채면 누구의 데이터인지 쉽게 확인 가능
📌 예제 (JWT Access Token 디코딩)
{
"sub": "user_12345",
"name": "John Doe",
"email": "johndoe@example.com",
"scope": "read write"
}
- JWT는 Base64로 인코딩된 문자열이므로, 누구나 쉽게 디코딩하여 사용자 정보를 볼 수 있음
- Access Token은 주로 브라우저나 모바일 앱에서 저장되므로, 노출 위험이 있음
✅ 해결 방법:
- Access Token에는 최소한의 정보(sub, scope)만 포함하고, 사용자 정보는 별도로 /userinfo API에서 가져오는 방식 사용
- 이 방식이 OIDC에서 일반적으로 사용됨
🔹 2. OIDC에서는 어떻게 해결할까?
OIDC에서는 Access Token이 아니라 ID Token을 사용하여 "사용자가 누구인지"를 확인합니다.
✔ OAuth 2.0에서는 사용자별로 승인한 scope(권한)가 다를 수 있기 때문에, 클라이언트가 /userinfo API를 호출해서 실제 사용자 정보를 가져와야 함
✔ Access Token만 보고는 어떤 사용자 정보를 가져올 수 있는지 알 수 없기 때문에, /userinfo API를 호출해야 함
✅ OAuth 2.0만 사용할 때 (문제 발생)
1️⃣ 사용자가 Google 로그인 버튼 클릭
2️⃣ Google OAuth 서버가 로그인 처리 후 Access Token 발급
3️⃣ 클라이언트가 Google API(/userinfo)를 호출해서 사용자 정보 가져오기
4️⃣ (문제점) Access Token이 만료되거나 유출될 경우, 보안 문제 발생
4️⃣ (문제점) Access Token이 만료되거나 유출될 경우, 보안 문제 발생
[1] 사용자 → 클라이언트 (Google 로그인 버튼 클릭)
[2] 클라이언트 → Google OAuth Server (Access Token 요청)
[3] Google OAuth Server → 클라이언트 (Access Token 발급)
[4] 클라이언트 → Google API (/userinfo 요청)
[5] Google API → 클라이언트 (사용자 프로필 정보 반환)
❌ 문제점:
- 매번 /userinfo API를 호출해야 최신 사용자 정보를 가져올 수 있음
- Access Token이 유출되면 사용자 정보가 노출될 위험이 있음
✅ OIDC를 사용한 경우 (해결 방법)
1️⃣ 사용자가 Google 로그인 버튼 클릭
2️⃣ Google OAuth 서버가 로그인 처리 후 ID Token + Access Token 발급
3️⃣ 클라이언트가 ID Token을 검증하여 로그인 완료
4️⃣ 최신 사용자 정보가 필요하면 /userinfo API 호출
[1] 사용자 → 클라이언트 (Google 로그인 버튼 클릭)
[2] 클라이언트 → Google OAuth Server (ID Token + Access Token 요청)
[3] Google OAuth Server → 클라이언트 (ID Token + Access Token 발급)
[4] 클라이언트 → ID Token 검증 후 로그인 완료
[5] (필요할 경우) 클라이언트 → Google API (/userinfo 요청)
✅ OIDC의 장점:
- ID Token을 활용하여 "사용자가 누구인지" 바로 확인 가능
- Access Token에는 최소한의 정보만 포함하여 보안 강화
- 최신 사용자 정보가 필요할 때만 /userinfo API 호출
✅ Access Token은 탈취될 위험이 있는데, ID Token은 안전한가?
👉 OIDC 방식(ID Token 사용)이 보안적으로 더 안전한 이유는 "ID Token이 클라이언트에서만 사용되고, 서버 API 요청에 사용되지 않기 때문"
📌Access Token은 API 요청마다 서버로 전송되므로 탈취 위험이 높음!
📌ID Token은 서버에서 클라이언트로 한 번만 전달되므로, 네트워크에서 노출될 가능성이 낮음!
📌 ID Token이 탈취되면?
- 해커가 ID Token을 가로채더라도, API 요청에는 사용할 수 없음 (Access Token이 필요하기 때문)
🔹 1. OIDC를 사용해도 Access Token이 유출되면 어떻게 되나?
✅ Access Token이 탈취되면, 해커는 리소스 서버(API)에 요청을 보낼 수 있음
✅ Access Token만 있으면 사용자의 데이터를 불법적으로 접근 가능
✅ OIDC가 있든 없든 Access Token 유출 자체는 큰 보안 위협!
🔹 2. OIDC가 OAuth 2.0보다 보안적으로 더 나은 이유
💡 "Access Token이 유출되면 API를 사용할 수 있는 건 똑같은데, 왜 OIDC가 더 안전하다고 하나?"
OIDC는 OAuth 2.0의 인증(Authentication) 기능을 강화하여 보안성을 높입니다.
즉, OIDC가 Access Token 자체를 보호하는 건 아니지만, 보안 강화를 위한 추가적인 보호 기능을 제공합니다.
🔹 3. OIDC를 사용하면 Access Token 유출을 어떻게 방지할 수 있나?
OIDC는 Access Token 유출을 방지하기 위해 추가적인 보안 조치를 제공합니다.
✅ 1) ID Token을 활용하여 Access Token 탈취 탐지
💡 "Access Token이 탈취되었는지 확인할 방법이 있을까?"
OIDC에서는 ID Token을 사용하여 클라이언트에서 Access Token이 정상적으로 사용되고 있는지 확인 가능합니다.
📌 Access Token을 요청하는 클라이언트의 정보(azp, aud)를 검증하여 이상 탐지 가능
✅ aud (Audience, 대상)
- Access Token을 사용할 수 있는 대상(리소스 서버, API)을 지정
- 리소스 서버(API)는 Access Token의 aud 값을 확인하여, 자신을 위한 토큰인지 검증
- 예를 들어, Google Drive API에서 사용해야 하는 Access Token이면 aud 값이 Google Drive의 Client ID가 됨
✅ azp (Authorized Party, 인증된 클라이언트)
- Access Token을 발급받은 클라이언트(Client)의 ID
- 보통 OAuth 2.0에서 클라이언트가 여러 개일 경우, 특정 클라이언트만 사용할 수 있도록 제한하는 역할
- 예를 들어, Notion이 Google Drive에 접근하려고 하면, azp 값은 Notion의 Client ID가 됨
✅ azp 값이 변경된 경우 → Access Token 탈취 가능성!
- Access Token은 **Notion(Client A)**에서 발급받았는데,
- 다른 클라이언트(Client B)가 API 요청 시 사용하고 있다면?
- Access Token이 탈취되었을 가능성이 있음! 🚨
✅ aud 값이 변경된 경우 → Access Token이 다른 API에서 사용됨!
- Access Token은 Google Drive API에서 사용하려고 발급받았는데,
- 다른 API(Gmail API)에서 사용하려고 하면?
- Access Token이 유출되어 다른 API에서 사용될 가능성이 있음! 🚨
📌 Access Token이 유출되었다면, 다른 클라이언트에서 요청이 오므로 탐지 가능
✅ 2) Access Token을 주기적으로 갱신하여 유출된 토큰을 무효화 (Refresh Token Rotation)
💡 "Access Token이 탈취되었을 때, 이를 막을 방법이 있을까?"
OIDC는 Refresh Token Rotation을 사용하여 Access Token을 주기적으로 갱신할 수 있습니다.
📌 방식
1️⃣ 클라이언트는 Access Token과 함께 Refresh Token을 받음
2️⃣ Access Token이 만료되면, Refresh Token을 이용하여 새 Access Token을 발급
3️⃣ 기존 Refresh Token은 무효화됨 → 해커가 탈취한 Access Token은 더 이상 사용 불가!
✅ Refresh Token을 한 번 사용하면 즉시 폐기하고, 새로운 Refresh Token을 발급 ✅ 탈취된 Refresh Token이 사용될 경우, 비정상적인 요청으로 감지하여 세션 종료
✅ 해커가 사용되지 않은 Refresh Token을 탈취하면 기존 사용자는 어떻게 되나?
💡 "해커가 내 Refresh Token을 먼저 사용하면, 내 세션은 어떻게 되는 거야?"
✅ 해커가 Refresh Token을 먼저 사용하면,기존 사용자의 Refresh Token은 즉시 폐기됨
✅ 기존 사용자가 Access Token을 갱신하려 하면,"Refresh Token이 유효하지 않음" 오류 발생
✅ 따라서 기존 사용자는새로운 로그인을 해야 함
📌 이상 탐지 시스템이 작동하여 기존 사용자에게 경고
👉 권한 서버는 Refresh Token을 사용할 때 'IP, 디바이스 정보, 위치'를 기록하여 이상 요청을 탐지
📌 정상적인 경우
- 기존 사용자 IP: 192.168.1.10
- Refresh Token 사용 IP: 192.168.1.10
'개발' 카테고리의 다른 글
HaProxy 의 역할과 graceful stop 과정 (0) | 2024.03.11 |
---|---|
CORS - Cross-Origin Resource Sharing 란 무엇일까 (0) | 2024.03.04 |
Spring 예제 코드로 알아보는 semaphore, mutex 동기화 이해 (1) | 2024.02.16 |
istio(이스티오)와 서비스 메시, 프록시 (1) | 2024.02.12 |
mysql aborted clients 문제 해결 (0) | 2023.10.05 |