
OAuth 2.0 → OIDC → JWT → Keycloak → Spring Boot 소셜 로그인까지, 전체 흐름을 하나로 묶어서 정리
OAuth 2.0 : 권한 위임의 표준 규격 (비밀번호 공유 없이 제3자에게 권한을 넘기는 방법)
↓ (위에 신원 확인 기능을 얹음)
OIDC : OAuth 2.0 + "로그인(사용자가 누구인지 확인)"을 표준화한 확장판
↓ (OIDC의 산출물이 이 형식)
JWT : OIDC/OAuth에서 실제로 주고받는 토큰의 데이터 형식 (서명된 JSON)
↓ (이 표준들을 실제로 구현한 소프트웨어)
Keycloak : OIDC/OAuth 2.0을 구현한 오픈소스 인증 서버
↓ (실무에서 이걸 우리 서비스에 붙이는 방법)
Spring 소셜 로그인 : Spring Security가 OAuth2/OIDC 흐름을 처리해주는 실제 구현체
핵심 한 줄: OAuth는 뼈대, OIDC는 그 위의 로그인 표준, JWT는 데이터 형식, Keycloak은 이걸 구현한 서버, Spring Security는 우리 코드에서 이걸 다루는 방법.
제3자 앱(예: 노션)이 내 다른 서비스(예: 구글 캘린더) 데이터에 접근해야 할 때, 비밀번호를 그대로 넘기지 않고 필요한 권한만 안전하게 위임하기 위한 표준.
옛날 방식(비밀번호 직접 입력)의 문제점:
| 역할 | 설명 | 예시 |
|---|---|---|
| Resource Owner | 자원의 주인 (나) | 구글 계정 사용자 |
| Client | 접근을 요청하는 제3자 앱 | 노션 |
| Authorization Server | 권한(토큰)을 발급하는 서버 | 구글 인가 서버, Keycloak |
| Resource Server | 실제 보호된 데이터가 있는 서버 | 구글 캘린더 API |
권한을 통째로 주지 않고 잘게 쪼갠 단위로 부여.
예: calendar.read, calendar.write, email.read
→ Client는 필요한 scope만 요청, 사용자는 그 범위만 허락 여부 결정
상황별로 다른 흐름을 씀.
| Grant Type | 언제 쓰나 | 특징 |
|---|---|---|
| Authorization Code | 웹/앱에서 사용자가 직접 로그인하는 경우 (가장 흔함) | 가장 안전, "구글로 로그인" 방식 |
| Client Credentials | 서버 대 서버 통신, 사람 개입 없음 | 배치 작업, 서버 간 API 호출 |
| Refresh Token | Access Token 재발급용 | Access Token은 수명이 짧고, 이걸로 재로그인 없이 갱신 |
OAuth 2.0 자체는 "이 토큰이 이 권한을 가지고 있다"만 보장하지, "이 토큰을 가진 사람이 누구인지"는 표준 범위 밖이었음. 이 부분을 보완한 게 OIDC.
OAuth 2.0 위에 "사용자 신원 확인(로그인)" 기능을 추가로 표준화한 확장 규격.
| 구분 | OAuth 2.0 | OIDC |
|---|---|---|
| 목적 | 권한 위임 | 사용자 인증(로그인) |
| 발급 토큰 | Access Token | Access Token + ID Token |
| 토큰 형식 규정 | 자유 | ID Token은 반드시 JWT |
| "이 사람 누구야?" | 알 수 없음 | ID Token 안에 사용자 정보 포함 |
Keycloak은 OIDC(및 OAuth 2.0) 규격을 실제로 구현한 서버 소프트웨어. 여러 앱이 각자 로그인 로직을 만들지 않고 Keycloak 하나로 통합 인증(SSO)을 구현할 수 있게 해줌.
점(.)으로 구분된 3부분, 각각 Base64Url로 인코딩된 JSON.
eyJhbGciOiJSUzI1NiJ9 . eyJzdWIiOiIxMjM0NSJ9 . 서명값
Header Payload Signature
(알고리즘 정보) (실제 데이터, claim) (위조 방지용 서명)
RS256)exp), 발급자(iss) 등 claim서버가 DB를 조회하지 않고도, 서명만 검증하면 토큰의 진위를 확인할 수 있음.
→ 마이크로서비스 환경에서 서비스마다 "이 사용자 로그인 상태 맞아?"를 DB에 물어보지 않고 빠르게 검증 가능 (Stateless 인증).
Red Hat이 만든 오픈소스 인증/인가 서버. OIDC, OAuth 2.0을 구현.
마이크로서비스 아키텍처에서는 각 서비스가 개별적으로 JWT를 검증하지 않고, API Gateway(예: Envoy Gateway) 단에서 JWT 서명을 미리 검증하는 패턴을 많이 씀 → 검증 실패 시 뒤 서비스까지 요청이 도달하지 않아 각 서비스의 인증 로직 부담이 줄어듦.
소셜 서비스(구글)의 Access Token ≠ 우리 서비스의 로그인 토큰. 완전히 별개다.
1. 사용자가 "구글로 로그인" 클릭
→ Spring 앱이 구글 로그인 페이지로 리다이렉트
→ client_id, redirect_uri, scope(profile email 등)를 함께 전달
2. 구글 로그인 + 사용자 허락
→ 비밀번호 입력은 구글 페이지에서 발생 (Spring 앱은 비밀번호를 절대 못 봄)
→ 허락 시 구글이 redirect_uri로 authorization code를 붙여서 리다이렉트
예: https://our-app.com/callback?code=abc123
3. Spring 서버가 code를 Access Token으로 교환 (서버 대 서버)
POST https://oauth2.googleapis.com/token
code=abc123
client_id=...
client_secret=...
redirect_uri=...
→ client_secret이 필요해서 브라우저에서는 위조 불가능
4. 액세스 토큰으로 사용자 정보 조회 (액세스 토큰의 실질적 용도)
GET https://www.googleapis.com/oauth2/v3/userinfo
Authorization: Bearer {구글 액세스 토큰}
→ 이메일, 이름, 프로필 사진 등 획득. 여기서 역할 끝.
5. 우리 서비스의 회원가입/로그인 처리 + 자체 JWT 발급
→ 받은 이메일로 DB 조회 → 없으면 회원가입, 있으면 로그인
→ 우리 서비스 전용 JWT를 새로 발급해서 클라이언트에게 전달
→ 이후 우리 API 호출은 이 JWT로 인증
spring-boot-starter-oauth2-client 의존성 추가 시 2~4번 과정이 대부분 자동화됨id_token(JWT)까지 함께 주면 OIDC 방식 → OidcUser로 처리OAuth2User로 처리provider(google/kakao), provider_id 컬럼으로 구분| 용어 | 한 줄 정의 |
|---|---|
| OAuth 2.0 | 비밀번호 공유 없이 제3자에게 권한을 위임하는 표준 |
| Access Token | "이 권한을 가지고 있다"를 증명하는 토큰 (API 호출용) |
| ID Token | "이 사용자가 누구인지"를 증명하는 토큰 (OIDC에서 추가됨, JWT 형식) |
| OIDC | OAuth 2.0 + 로그인(신원 확인) 표준 |
| JWT | 서명이 포함된 JSON 기반 토큰 형식 (Header.Payload.Signature) |
| Keycloak | OIDC/OAuth 2.0을 구현한 오픈소스 인증 서버 |
| SSO | 여러 앱을 하나의 인증 서버로 통합 로그인 처리하는 것 |
| Scope | 요청/허용하는 권한의 범위 단위 |
| Grant Type | OAuth에서 토큰을 발급받는 방식 (Authorization Code, Client Credentials 등) |
oauth2-client로 구글/카카오 로그인 붙여보기SecurityPolicy로 게이트웨이 단에서 JWT 검증하기