어떤 멘토 분이 이런 말을 하셨다.
“요즘은 Spring Security에 OAuth2 라이브러리 하나만 추가해놓고
소셜 로그인 인증을 구현했다고 한다.
과연 이렇게 구현한 사람들이 OAuth2에 대해 안다고 할 수 있을까?
OIDC가 뭔지는 알기나 할까?”
이 말을 듣고 찔려서 공부해보겠다.
OAuth2는 인증 프로토콜이 아니라 “인가” 프로토콜이다.#
Authentication Authorization
많은 글들이 OAuth2예시를 설명하면서, 이를 구분하지 않는다. 거의 소셜 로그인 == OAuth2 로그인 정도로 취급되지만, OAuth2의 목적은 인증이 아닌 인가이다.
OAuth2(2.1) RFC의 첫 문단을 번역하면 이렇다:
OAuth 2.1 인증 프레임워크는 리소스 소유자와 인증 서비스 간의 승인 상호 작용을 조율하여 리소스 소유자를 대신하여 타사 애플리케이션이 HTTP 서비스에 대한 제한된 액세스 권한을 얻거나 타사 애플리케이션이 자체적으로 액세스 권한을 얻을 수 있도록 허용합니다.
즉, OAuth2는 사용자 인증이 아닌, “애플리케이션이 사용자 리소스에 접근할 수 있는 권한” - 즉 인가에 초점이 맞춰져 있다. 다음은 GPT가 준 예시이다:
- 사용자 A와 애플리케이션 B가 있다.
- A는 “B가 내 구글 드라이브 목록 정도는 봐도 돼"라고 동의한다.
- 구글은 B에게 access token을 발급한다.
- 그 토큰으로 A의 리소스(API)를 호출한다.
여기 어디에도 **“A가 진짜 A인지 인증하는 과정”**은 없다. 권한을 위임할 뿐이다. “어? 근데 애가 알아서 사용자 정보 가져오던데?”
사용자 정보를 가져오는 것은 맞다.
그러나 이는 위임된 access token으로 사용자 리소스(API)를 호출한 결과일 뿐이다.
즉, 인증을 한 게 아니라, 권한을 받아서 사용자 정보를 요청한 것이다.
하지만….
OIDC(OpenID Connect)#
위 설명처럼, OAuth2만으로는 사용자가 누군지 검증이 불가능하다. 이를 보완하기 위해 등장한 것이 바로 OIDC이다.
OIDC는 OAuth2의 “인가” 기능에 **“인증”**을 더한 프로토콜이다. 즉, 추가된 id_token을 통해 사용자가 누구인지를 검증할 수 있다.
다음은 OIDC를 지원하지 않는 네이버의 OAuth2 응답이다.
{
"access_token": "Aawefwaefawefawefo",
"refresh_token": "awefwaefwaefgh",
"token_type": "bearer",
"expires_in": "3600"
}다음은 OIDC를 지원하는 Google의 OAuth2 응답이다.
{
"access_token": "aa",
"expires_in": 3598,
"scope": "https://www.googleapis.com/auth/userinfo.email openid",
"token_type": "Bearer",
"id_token": "{{대충 jwt토큰}}"
}id_token#
OIDC는 토큰 응답 시, access_token 외에 JWT 형식의 id_token을 함께 반환한다.
이 id_token은 JWT 형식으로 되어 있고, 고유 식별자, 이메일, 발급자 정보 등 + 스코프에 요청한 정보를 담고 있다.
이
id_token이 바로 “이 사용자가 인증되었고, Google이 발급했다"는 인증서 역할을 한다.
OIDC 사용 시 장점#
ID 토큰만으로 인증이 가능하다. 즉, 응답으로 받은 access token을 가지고 사용자 정보를 가져오는 추가적인 요청이 필요하지 않다.
발급자의 공개키로 서명된 JWT 방식이라, 서버에서 이를 검증할 수 있다.
표준화되어있다. OIDC를 사용하지 않고
/userinfo/me등을 호출해 사용자의 정보를 가져오는 방식은 서버마다 무슨 정보를 내려줄지 알 수 없다. OIDC는 scope에 따라 정해진 사용자 정보를 제공한다.
다음 글에서는 이 개념들을 바탕으로 Spring Security 없이 직접 OAuth2 + OIDC 구현 예제를 코드와 함께 소개할 예정이다.