내가 사용자의 구글 메일을 대신 읽어주는 서비스를 개발했다치자. 사용자는 그 서비스에 구글 계정 ID/PW를 입력해야 한다. 그래야 내 서비스가 사용자의 메일을 읽어줄 것 아닌가.
그래서 OAuth가 등장했다.
Id Provider가 애플리케이션과 사용자 비밀번호를 공유하지 않고도 애플리케이션이 사용자 자원에 접근할 수 있도록 하는 인가 프레임워크
https://kauth.kakao.com1번이 웹/모바일 환경에서의 가장 표준이고, 2번은 서버 ↔ 서버 간에 자주 사용된다고 한다.
나머지는 거의 사용하지 않는다고 한다. 최근에는 몇 개 더 나왔다던데 그냥 이런 것도 있다~만 알아두면 될 것 같다.
요청 예시
GET https://api.fittoring.com/kakao/login
이때 중요한 파라미터들이 있다.
client_id : 인가 서버에 등록된 우리 앱의 IDredirect_uri : 인가 서버가 인가 코드를 보내줄 콜백 주소. (보통 앱 서버 콜백 API)state : CSRF 방지용 랜덤값GET https://kauth.kakao.com/oauth/authorize
?response_type=code
&client_id=OUR_CLIENT_ID
&redirect_uri=https://our-service.com/auth/kakao/callback
&state=random_string
GET https://api.fittoring.com/kakao/callback?code=AUTH_CODE&state=random_stringaccess token)을 요청요청 예시
POST https://kauth.kakao.com/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id=OUR_CLIENT_ID
&redirect_uri=https://our-service.com/auth/kakao/callback
&code=AUTH_CODE
응답 예시
{
"access_token": "xxx",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "yyy",
"scope": "profile_nickname account_email"
}
access token을 이용해 사용자 정보(카카오id, 닉네임 등) 요청GET https://kapi.kakao.com/v2/user/meaccecss token으로 /userinfo를 요청해보고 응답이 잘 오면 ‘카카오가 인증한 사용자’라고 해석하여 우리 서비스가 로그인을 해주는 방식이다.여기까지가 OAuth로 소셜 로그인을 구현하는 흐름이다. 간단히 정리하면 아래와 같다.
- 인증 서버에서
Access Token을 받는다. (인가)Access Token에는 사용자에 대한 정보가 없다. 따라서Access Token으로 리소스 서버에 사용자 정보를 요청해서ID/이메일등의 정보를 가져온다. (인증)
엄밀히 말하면 위의 과정은 불완전하다.
OAuth는 인가 프레임워크일뿐 인증 방법을 표준화 해두지 않았다.
인가 서버로부터 사용자 정보를 요청할 수 있는 권한(access token)을 받은 것이고, 이 토큰이 누구의 것인지 확인하는 인증의 과정이 없기 때문이다. 이것은 아래의 문제를 야기했다.
불필요한 네트워크 왕복을 동반한다. 대부분의 서비스는 사용자 정보를 필요로 하기 때문에 인증 서버에서 접근 권한을 얻은 후에 리소스 서버에 사용자 정보를 요청해야 했다.
IdP(Id Provider, 구글 카카오 등)마다 사용자 정보를 응답하는 형식이 달라 개발자가 고생한다.
이러한 문제를 해결하기 위해 OAuth 위에 표준화된 인증 레이어를 올려놓은 것이 OIDC이다.
Q. 사용자가 직접 구글,카카오 로그인을 했는데 인증 된 거 아닌가?
IdP입장에서는 사용자를 인증한 것이 맞다. 그런데 우리 서버에서는 아직 사용자의 신원을 확인하지 않았다.
만약 리소스 서버에 사용자 정보를 요청하는 과정에서 사용자의 access token을 중간에 가로챈 공격자가 자신의 access token을 넣으면
사용자는 공격자의 정보를 들고 우리 서버에 로그인 하게 될 것이다. OIDC를 활용해 이런 문제를 예방할 수 있다.
OIDC는 OAuth 위에 id_token 이라는 JWT로 인증 과정을 얹은 것이다.
OIDC를 활성화하면 위의 인가 코드 흐름 5.에서 access token과 함께 id_token도 받게 된다.
클라이언트는 이 id_token의 유효성만 확인하면 별도의 API 호출 없이 사용자의 핵심 신원 정보(Claim)를 즉시 얻을 수 있다.
OAuth는 인가 프로토콜, OIDC는 OAuth에 인증을 추가한 인증·인가 프로토콜이다.
OAuth가 체크인 시, 호텔 카드키를 받는 과정이라면
OIDC는 체크인 시, 호텔 카드키와 신분증을 받는 과정이다.
기본적으로 OAuth 플로우 위에서 돌아가지만 몇 가지 차이가 있다.
scope 추가openid 스코프를 반드시 포함해야 한다. 이는 "OIDC 인증을 수행하겠다"는 의도를 IDP에게 명시적으로 알리는 것입니다.서명(Signature) 검증: IDP의 공개 키를 사용하여 토큰이 변조되지 않았고 IDP가 발급한 것이 맞는지 확인iss (Issuer) 클레임 확인: 토큰 발급자가 우리가 예상한 IDP가 맞는지 확인aud (Audience) 클레임 확인: 토큰의 수신자가 우리 서버의 client_id가 맞는지 확인 (가장 중요)exp (Expiration) 클레임 확인: 토큰이 만료되지 않았는지 확인현재는 OAuth에 OIDC를 얹어 사용하는 것이 IdP를 통한 인증과 인가의 표준이라고 할 수 있다.