OpenID Connect
더 많은 작업
- OpenID Connect, OIDC; 오픈아이디 커넥트
- OAuth 2.0 위에 인증 계층을 얹어, 클라이언트가 사용자의 신원을 확인하고 기본 프로필 정보를 받을 수 있게 한 표준
OAuth 2.0은 사용자가 앱에 "내 대신 이 API를 써도 된다"는 권한을 위임하는 인가 프레임워크이다. 액세스 토큰은 API 호출용 열쇠일 뿐 "누가 로그인했는가"를 표준화된 형태로 알려 주지 않는다. 그래서 각 서비스가 OAuth를 로그인에 제각각 응용하면서 토큰 바꿔치기 같은 취약점이 생겼다. OpenID 재단(OpenID Foundation)은 2014년 OpenID Connect Core 1.0을 확정해, 인증 결과를 담는 ID 토큰과 표준 사용자 정보 엔드포인트를 정의했다. 지금은 소비자 서비스의 소셜 로그인과 기업 IDaaS의 SaaS 연동에서 가장 널리 쓰이는 연합 인증 표준이다.
| 용어 | 설명 |
|---|---|
| OpenID 공급자(OP) | 사용자를 인증하고 ID 토큰을 발급하는 쪽. OAuth의 인가 서버 역할을 겸한다. 연합 용어로는 IdP이다. |
| 신뢰 당사자(RP) | ID 토큰을 받아 사용자를 로그인시키는 클라이언트 애플리케이션이다. |
| openid 스코프 | 인가 요청에 openid 스코프 값이 있어야 OIDC 요청이 된다. 없으면 일반 OAuth 요청이다.
|
| ID 토큰 | 인증 사건에 관한 클레임을 담은 서명된 JWT이다. |
| UserInfo 엔드포인트 | 액세스 토큰을 제시하면 사용자 클레임(이름, 이메일 등)을 돌려주는 OAuth 보호 자원이다. |
| 디스커버리 | OP가 /.well-known/openid-configuration 경로에 엔드포인트 주소, 지원 알고리즘, 서명 키 위치(jwks_uri)를 JSON으로 공개해 RP가 자동 설정하게 한다.
|
ID 토큰은 JWT(JSON Web Token) 형식이며 OP가 서명한다. RP는 서명을 OP의 공개키로 검증하고 아래 클레임을 확인해야 한다.
| 클레임 | 의미 | RP가 확인할 것 |
|---|---|---|
| iss | 발급자(issuer) 식별자 URL | 기대한 OP와 정확히 일치하는가 |
| sub | 발급자 안에서 사용자를 유일하게 식별하는 값 | 계정 연결 키로 쓴다(이메일 대신 iss + sub 조합) |
| aud | 토큰을 받을 대상(audience). RP의 client_id가 들어간다. | 내 client_id가 포함되어 있는가. 다른 앱용 토큰 재사용을 막는다. |
| exp | 만료 시각 | 지났으면 거부한다. |
| iat | 발급 시각 | 너무 오래된 토큰을 거부한다. |
| nonce | RP가 인증 요청에 넣은 임의 값을 그대로 돌려준 것 | 요청 때 보낸 값과 같은가. 재전송 공격을 막는다. |
| auth_time, acr, amr | 인증 시각, 인증 맥락 등급, 사용한 인증 방법 | 민감 작업에서 재인증·다중 인증 여부를 판단한다. |
ID 토큰은 "누가 로그인했는가"를 RP에게 알려 주는 용도이고, API 호출에는 액세스 토큰을 쓴다. ID 토큰을 API 접근 열쇠로 보내는 것은 잘못된 사용이다.
OIDC Core는 세 가지 흐름을 정의한다.
| 흐름 | response_type | 토큰 전달 경로 | 현재 권고 |
|---|---|---|---|
| 인가 코드 흐름(Authorization Code Flow) | code | 브라우저로는 일회용 코드만 받고, 토큰은 백엔드 채널(토큰 엔드포인트)로 받는다. | 권장. PKCE를 함께 쓴다. |
| 암시적 흐름(Implicit Flow) | id_token, id_token token | 토큰이 URL 조각(fragment)에 실려 브라우저로 바로 온다. | 비권장. 토큰이 브라우저 기록·리퍼러·악성 스크립트로 새기 쉽다. |
| 하이브리드 흐름(Hybrid Flow) | code id_token 등 | 일부는 브라우저로, 일부는 토큰 엔드포인트로 받는다. | 특수한 경우에 쓴다. |
PKCE(Proof Key for Code Exchange, RFC 7636)는 클라이언트가 요청마다 임의 비밀값(code_verifier)을 만들고 그 해시(code_challenge)를 인가 요청에 넣었다가, 코드를 토큰으로 바꿀 때 원래 값을 제시하게 하는 방식이다. 중간에 인가 코드를 가로챈 공격자는 원래 값을 모르므로 토큰을 받지 못한다. 2025년 1월 발행된 OAuth 2.0 보안 모범 사례(RFC 9700)는 공개 클라이언트(모바일 앱, SPA)에 PKCE를 의무화하고 기밀 클라이언트에도 권장하며, 암시적 그랜트처럼 인가 응답으로 액세스 토큰을 내보내는 방식은 쓰지 말도록(SHOULD NOT) 했다. 사용자 비밀번호를 클라이언트가 직접 받는 리소스 소유자 비밀번호 그랜트는 금지(MUST NOT)했다.
- RP가 code_verifier를 만들고 그 해시를 code_challenge로 계산한다.
- RP가 사용자를 OP 인가 엔드포인트로 보낸다(scope=openid, response_type=code, state, nonce, code_challenge 포함).
- OP가 사용자를 인증하고 동의를 받은 뒤 인가 코드를 붙여 RP로 리디렉션한다.
- RP가 state를 확인하고, 토큰 엔드포인트에 코드와 code_verifier를 보낸다.
- OP가 검증 후 ID 토큰과 액세스 토큰(필요시 리프레시 토큰)을 준다.
- RP가 ID 토큰 서명과 iss·aud·exp·nonce를 검증하고 세션을 만든다. 추가 정보가 필요하면 UserInfo 엔드포인트를 호출한다.
| 구분 | SAML 2.0 | OpenID Connect |
|---|---|---|
| 표준화 | OASIS | OpenID 재단 |
| 메시지 형식 | XML 어서션, XML 서명 | JSON, JWT(JWS 서명) |
| 전송 | 브라우저 POST·리디렉트 바인딩 | HTTP 리디렉트 + REST 호출 |
| 모바일·SPA 적합성 | 낮음(XML 처리, 브라우저 중심) | 높음 |
| API 인가 | 별도 수단 필요 | 같은 흐름에서 OAuth 액세스 토큰을 함께 받음 |
| 설정 | 메타데이터 XML을 수동 교환하는 경우가 많음 | 디스커버리 문서로 자동 설정 |
| 주 사용처 | 기업 웹 SSO, 기존 엔터프라이즈 앱 | 소비자 로그인, 최신 SaaS·모바일, 클라우드 워크로드 |
- 서명 검증 생략, alg 값을 none으로 바꾼 토큰 허용은 치명적이다. 허용 알고리즘을 고정한다.
- redirect_uri는 사전 등록한 값과 정확히 일치할 때만 허용한다. 와일드카드는 토큰 유출 경로가 된다.
- state는 CSRF 방지, nonce는 ID 토큰 재전송 방지용이다. 둘 다 생략하지 않는다.
- 이메일 클레임만으로 계정을 연결하면, 이메일을 검증하지 않는 OP를 통해 남의 계정을 가로채는 공격이 가능하다. iss + sub 조합을 쓴다.
- OAuth 2.0은 인가, OIDC는 그 위의 인증 계층이다. "사용자 인증용 표준"을 고르라면 OIDC 또는 SAML이다.
- OIDC의 핵심 산출물은 ID 토큰(JWT)이며, aud는 토큰을 받을 앱, nonce는 재전송 방지 값이다.
- 모바일 앱·SPA에는 인가 코드 흐름 + PKCE를 고른다. 암시적 흐름은 흔한 오답이다.
- SAML은 XML 기반 기업 웹 SSO, OIDC는 JSON·REST 기반으로 모바일·API 친화적이라는 차이를 기억한다.
- OpenID Connect Core 1.0 – OpenID Foundation
- OpenID Connect Discovery 1.0 – OpenID Foundation
- RFC 9700, Best Current Practice for OAuth 2.0 Security – IETF
- RFC 7636, Proof Key for Code Exchange by OAuth Public Clients – IETF