OAuth2 인증 방식에 대해 알아보자.

piecemaker·2020년 9월 9일
41

요즘 웹 사이트들을 돌아다니다 보면, 이전처럼 웹 사이트 이용을 위해 아이디와 비밀번호로 회원가입 하는 방법 외에도 '카카오 아이디로 로그인', '구글 아이디로 로그인' 등과 같이 유명한 타 서비스의 계정을 본인의 웹 사이트에서도 사용할 수 있도록 구현한 사이트들이 종종 보인다.

한국 사이트에서는 아직 가끔만 보이고 특히 해외 사이트들에서 자주 보이는데, 웹 사이트 뿐만이 아니라 대부분의 한국 모바일 게임에서 볼 수 있는 '카카오 계정으로 로그인'에서 미루어보듯 모바일 애플리케이션에서도 자주 도입되는 인증 방식이라고 할 수 있다 (물론 웹 사이트와의 구현 방법은 다르겠지만). 아래 이미지는 카카오 계정 로그인을 사용하는 '쿠키런' 모바일 게임과, 구글 및 깃허브 로그인을 사용하는 '코드스테이츠' 웹사이트의 예시를 보여준다.

이처럼 웹 사이트 계정 인증에 타 서비스의 계정을 사용하는 인증 방식을 OAuth 2.0 인증 방식이라고 한다. 이 포스팅에서는 OAuth 인증 방식이 어떻게 동작하는지를 구글 서비스를 예로 들어 살펴보고자 한다.

서비스 등록

어떤 특정 서비스의 OAuth 인증을 사용하기 위해서는, 해당 서비스에 내가 OAuth 인증을 사용할 애플리케이션을 등록해야 한다.

내가 https://www.test.com이라는 URL을 가지는 웹 서비스를 하나 만들었는데, 내 웹 서비스에서 '구글 로그인' 방식의 OAuth 인증을 추가로 사용할 수 있도록 지원하고 싶다고 가정하자. 가장 첫 번째로 해야 하는 일은 구글 API 콘솔에 접속하여 새로운 프로젝트를 생성해주는 것이다. 구글과 관련된 대부분의 API를 사용하기 위해서는 각 서비스 마다 새로운 '구글 프로젝트'를 만들어주어야 하기 때문에 필수적인 단계이다. 아래는 test라는 이름의 구글 프로젝트를 만드는 예시이다.

이렇게 구글에 프로젝트를 등록했다면, 해당 프로젝트의 메인 콘솔 페이지 좌측 메뉴에서 '사용자 인증 정보' 메뉴를 찾을 수 있는데, 이 메뉴의 상단에 있는 사용자 인증 정보 만들기 서브메뉴의 OAuth 클라이언트 ID 항목을 선택하면 구글의 OAuth 인증을 사용하기 위해 웹 서비스 관련 정보들을 입력하는 페이지로 이동된다.

OAuth 클라이언트 ID 만들기 페이지로 이동하면 OAuth를 사용할 서비스의 유형과 이름, 그리고 URI을 입력하는 란이 보인다. 애플리케이션 유형과 이름을 원하는 대로 입력하고, 승인된 자바스크립트 출처에는 내 웹 사이트의 루트 URL을 입력하자.

그런데, 맨 마지막의 승인된 리디렉션 URI에는 뭘 넣어야 하는지 모르겠다. OAuth 클라이언트 ID를 만드는데 정확한 정보를 넣을 필요는 없으므로 일단 아래와 같이 내 웹 사이트 URL을 기반으로 아무렇게나 작성한 후, '만들기' 버튼을 눌러보자. 승인된 리디렉션 URI에 넣은 URL 정보는 추후에 변경할 수 있다.

만들기 버튼을 누르면 아래와 같은 모달 창에 클라이언트 ID클라이언트 비밀번호라는 정보가 들어있는 것을 볼 수 있다. 필자는 보안을 위해 내용을 지웠으나 독자분들의 경우에는 정보가 채워져있을 것이다. 이제 이 정보를 사용해 내 웹 사이트에서 Google OAuth 인증을 사용할 수 있다.

OAuth를 사용하기 위해 구글에 내 웹 서비스를 등록하는 절차는 알겠다. 그런데, 위에서 우리가 대충 채우고 넘어간 리디렉션 URI는 뭘 뜻하는 것이고, 구글로부터 받은 클라이언트 ID클라이언트 비밀번호는 프로젝트에서 어떻게 사용해야 하는 것일까?

이를 이해하기 위해서는 OAuth 2.0이 어떻게 동작하는지에 대해 알아야 한다. 지금부터 OAuth 2.0 인증 방식이 정확히 어떻게 동작하는지에 대해 알아보자.

OAuth 2.0 동작 방식

OAuth 인증 방식은 위에서 언급한 대로 인증의 과정을 '타 서비스에게 위임' 하는 인증 방식이다. '위임'한다는 뜻은 내 웹 사이트에 '구글 로그인' 인증을 넣었다고 해서 사용자가 구글 웹 사이트에 직접 로그인하는 것이 아니라는 뜻이다. 내 웹 사이트에 접속한 사용자의 정보는 여전히 내 웹 사이트에서 관리해야 한다.

구글이 해주는 일은 웹 사이트 사용자가 '구글 로그인' 기능을 통해 구글에게 전송한 구글 계정 정보가 유효한지 (구글 아이디 및 비밀번호가 일치하는지)를 확인한 후, 유효하다면 해당하는 구글 유저 정보 중 일부 (유저 이름, 프로필 이미지 등)를 내 웹 사이트에 제공해주는 '인증' 과정만을 처리해주는 것 뿐이다.

1. 구글 인증 페이지

우리가 처음 웹 사이트에 접속해 로그인 페이지에서 '구글 로그인' 버튼을 누르면, 다음과 같이 Google 인증 페이지로 이동하도록 구현하고 싶다.

이 인증 페이지는 구글에서 제공하는 Google 인증 서버 페이지이며, https://accounts.google.com/o/oauth2/auth URL에서 제공한다. 하지만, 단순히 이 링크를 주소창에 치면 아래와 같은 에러 메시지를 볼 수 있다. 에러 내용을 보면 필수적으로 제공해줘야 하는 파라미터가 주어지지 않았다는 것을 알 수 있다.

잘 생각해보면 매우 당연한 에러인데, 우리가 구글 로그인 기능을 사용하기 위해 Google 인증 서버 페이지에 접속한다는 뜻은 특정 웹 사이트에서 구글 계정을 사용하는 OAuth 인증을 사용하고 싶다는 것을 의미한다. 그런데 다짜고짜 주소창에 인증 서버 페이지 주소를 입력하면 대체 어떤 웹 사이트에서 OAuth 인증을 요청하는지를 알 수 없기 때문에 오류가 발생하는 것이다.

이 때 '어떤 웹 사이트에서 OAuth 인증을 요청하는가'를 구글 인증 서버에 알려주기 위해 사용하는 것이 위에서 OAuth 클라이언트 생성 시 받았던 클라이언트 ID이다. 우리가 웹 서비스를 구글에 프로젝트로 등록했고, 등록 시 웹 사이트 URL 정보를 제공했기 때문에 구글 인증 서버에 클라이언트 ID만 주면 구글에서 어떤 웹 사이트에서 OAuth 인증을 요청하는지를 자체적으로 식별할 수 있는 것이다.


OAuth를 사용하기 위해서는 구글 인증 서버에 클라이언트 ID 이외에도 많은 추가 정보들을 제공해주어야 하지만, 그 중 가장 중요한 추가 정보 하나만을 설명하자면 리디렉션 URL 정보이다. 리디렉션(Redirection)이 무엇인지는 다 아실거라 생각해서 리디렉션에 대한 설명은 하지 않겠다.

웹 사이트 사용자가 구글 인증 서버에 올바른 구글 계정 정보를 입력하면, 구글에서는 해당 정보가 유효한지 판단한 후 유효하다면 해당하는 유저의 정보를 우리의 웹 서비스로 전송해야 한다. 웹 사이트로 계정 정보를 전송 해야지 웹 서비스에서도 현재 로그인 한 유저가 어떤 유저인지를 식별할 수 있으며, 웹 서비스에서 자체적으로 유저 정보를 관리할 수 있기 때문이다. (다시 한번 언급하지만 OAuth 인증 방식에서 Google은 단지 '인증'만을 다루고, 실제 유저 정보는 웹 사이트에서 관리한다)

그렇다면 구글 유저 정보를 우리 웹 서비스의 특정 URL로 전송해주어야 한다는 의미인데, 이 URL이 바로 위에서 설명한 리디렉션 URL이다. 위의 OAuth 클라이언트 ID 만들기에서 승인된 리디렉션 URI에 우리가 어떤 정보를 줬는지 다시 한번 보자.

우리가 구글에 웹 서비스를 등록할 때, 리디렉션 URL로 https://www.test.com/auth/google/callback이라는 URL을 제공했다. 따라서, 구글 인증 서버에서 OAuth를 사용하기 위해서는 인증 서버에 이 https://www.test.com/auth/google/callback이라는 URL을 리디렉션 URL 정보로 줘야 하며, 구글은 인증이 끝나면 해당 URL로 로그인 한 구글 계정 정보를 POST로 전송해준다.

실제로는 더 많은 정보를 제공해주어야 하나, 위에서 언급한 두 가지 정보인 클라이언트 ID리디렉션 URL정보를 제공한 Google 인증 서버 페이지 URL은 다음과 같다. 이 URL로 접속하면 우리는 우리가 기대했던 대로 Google 인증 페이지로 이동하게 되며, 유저가 Google 계정으로 성공적으로 로그인을 하면 Google 계정 정보가 리디렉션 URL로 전송될 것이다.

https://accounts.google.com/o/oauth2/auth?client_id=OAuth-클라이언트-아이디&redirect_uri=https://www.test.com/auth/google/callback

2. 액세스 토큰 (Access Token)

위에서는 구글이 리디렉션 URL로 구글 계정 정보를 POST로 전송해준다고 말했다. 하지만 실제로는 바로 계정 정보를 전송해버리면 보안 상으로 취약하므로 OAuth 2.0에서 하나의 단계를 더 추가하는데, 이 단계를 구현하기 위해 사용되는 것이 바로 액세스 토큰 (Access Token)이다.

사용자가 구글 인증에 성공하면, 구글에서는 우리의 리디렉션 URL인 https://www.test.com/auth/google/callback로 리다이렉트 하는데, 이 때 사용자 정보를 POST로 보내주는 대신 다음과 같이 리디렉션 URL에 code라는 매개변수 정보를 추가해준다.

https://www.test.com/auth/google/callback?code=코드정보

웹 서비스에서는 이 code라는 매개변수 값을 URL로부터 얻어온 후, 이 code를 통해 구글 계정 정보에 접근할 수 있는 액세스 토큰을 얻는다. 액세스 토큰을 얻기 위해서는 https://accounts.google.com/o/oauth2/token 이라는 URL에 code 정보를 포함해 POST 요청을 해야 한다.

이 때, 우리는 보안을 위해 code 정보 이외에도 추가 정보를 제공해줘야 하는데, 이 경우 사용되는 것이 바로 구글에 웹 서비스 등록 시 발급받은 클라이언트 ID클라이언트 비밀번호 정보이다. 또한, 이 POST 요청에 대한 응답으로 구글에서 액세스 토큰 정보를 전송해줄 때에도 위에서와 동일한 리디렉션 URL을 사용하므로 리디렉션 URL 정보도 함께 제공해줘야 한다.

https://www.googleapis.com/oauth2/token
POST Body 정보: code=코드정보, client_id=클라이언트-아이디, client_secret=클라이언트-비밀번호, redirect_uri=https://www.test.com/auth/google/callback

이 POST 요청에 대한 결과로 구글 서버는 다음과 같이 액세스 토큰 정보가 포함 된 JSON 데이터를 리디렉션 URL로 전송해준다.

{
  "access_token" : "ya29.AHES6ZTtm7SuokEB-RGtbBty9IIlNiP9-eNMMQKtXdMP3sfjL1Fc",
  "token_type" : "Bearer",
  "expires_in" : 3600,
  "refresh_token" : "1/HKSmLFXzqP0leUihZp2xUt3-5wkU7Gmu2Os_eBnzw74"
}

우리는 이제 이 access_token에 명시된 액세스 토큰 값을 통해 웹 서비스에서 다양한 구글 API들을 사용할 수 있고, 물론 유저의 구글 계정 프로필 정보도 가져올 수 있게 되었다. 예를 들어, https://www.googleapis.com/oauth2/v3/userinfo 라는 URL에 우리의 액세스 토큰 정보를 포함하여 GET 요청을 보내면, 아래와 같은 유저 정보를 JSON 형태로 얻을 수 있다.

{
 "sub": "110248495921238986420",
 "name": "Aaron Parecki",
 "given_name": "Aaron",
 "family_name": "Parecki",
 "picture": "https://lh4.googleusercontent.com/-kw-iMgD
   _j34/AAAAAAAAAAI/AAAAAAAAAAc/P1YY91tzesU/photo.jpg",
 "email": "aaron.parecki@okta.com",
 "email_verified": true,
 "locale": "en",
 "hd": "okta.com"
}

참고로 이러한 액세스 토큰은 브라우저의 캐시로 저장되거나 웹 서비스에 세션으로 저장될 수 있다. 만약 캐시나 세션에 액세스 토큰 정보가 저장된다면, 액세스 토큰이 만료되지 않는 한 브라우저를 종료했다가 다시 접속해도 자동으로 이전 로그인 정보로 로그인 되도록 웹 사이트를 구축할 수도 있다.

정리

지금까지 살펴본 OAuth 인증 절차를 하나의 다이어그램으로 표현한다면 다음과 같을 것이다.

사용하는 OAuth 2.0 서비스에 따라 5~6번의 과정은 생략될 수 있음을 기억했으면 한다. 보다 단순한 서비스의 경우 code를 발급하는 과정을 건너 뛰고 인증 서버에서 바로 액세스 토큰을 제공해주는 경우도 종종 존재하기 때문이다. 단 어떤 OAuth 2.0 서비스던 간에 큰 인증 흐름은 위에서 설명한 것과 크게 다르지 않으므로, 어떤 절차로 OAuth 2.0 인증이 이루어지는지를 기억하면 될 것이다.

참고 문헌

https://www.oauth.com/
https://developers.google.com/youtube/v3/guides/auth/server-side-web-apps?hl=ko

profile
풀스택 지망생

4개의 댓글

comment-user-thumbnail
2021년 4월 1일

너무 좋은 설명이예요! 감사합니다.

답글 달기
comment-user-thumbnail
2021년 4월 22일

좋은 설명 감사합니다. 마지막에 다이어그램으로 한 번에 요약된 그림도 깔끔해서 정리가 한 번에 되었습니다. 감사합니다.

답글 달기
comment-user-thumbnail
2021년 6월 26일

설명 너무 잘해주셔서 잘 이해했습니다. 감사합니다

답글 달기
comment-user-thumbnail
2021년 8월 30일

너무 설명을 잘해주셔서 바로 이해됐습니다. 감사합니다.

답글 달기