Oauth 2.0(노션 이동 완료)

2022. 5. 11. 21:17

0. 역할(호칭) 정리

  • Oauth2.0은 양자가 아닌 삼자의 이야기임. 따라서 미리 Oauth2.0 에 등장하는 호칭들을 정리
    • 우리의 서비스 : Client
    • 우리서비스의 사용자 : Resource Owner
    • 우리서비스가 빌려쓰려는 다른 서비스(카카오) : Resource Server
    • 추가)공식문서에 따르면 Resourceserver의  권한에 대한 처리를 진행하는 autrhorization server를 언급하기도 함

 

1. Oauth 2.0이 필요한 이유

  • 나의 서비스(Client)에 다른 서비스(Resource Server)를 연동시켜서, 내 서비스의 유저(Resource Owner)가 내 서비스를 통해 다른 서비스를 사용할 수 있게 해주려는 상황
    • 말이 어려운데 그냥 예를 들면 편함. 내 서비스에서, 내서비스의 유저가 카카오 로그인을 하려는 상황임
  • 이때, Resource Owner가  Client에게 Resource Server의 아이디와 비밀번호를 가르쳐 주는게 가장 깔끔하고 편하다.
    • 그러면 Resource owner가 Resource server를 사용하듯이, 우리 서비스(Client)가 Resource server에 접속할 수 있다.
    • 그래서 resource owner가 다른 서비스(카카오)를 내 서비스를 통해 이용할 때, 우리 서버가 자동으로 다른 서비스에 접속해서 유저가 하려는 모든 것을 대신 실행해준다.
    • 하지만 이것은 당연하지만 굉장히 위험하고 잘못된 행위.
      • resouce owner입장에서는 처음보는 서비스한테 자신의  id/pw를 맡기는 것임. 
      • 우리서비스 입장에서도, 유저의 아이디와 비번을 가지고 있다가 유실되면 문제가 생길 수 잇음. 즉 우리 서비스 입장에서도 유저의 다른 서비스(카카오)의 아이디와 비밀번호 같은 개인정보를 가지고 있지 않는게 좋음. 
      • 반대로 다른 서비스(카카오)입장에서도 자기 유저들의 정보를 다른 서비스가 가지고 있는게 매우 불만족스러운 상황임
    • 모두가 싫어하는 이 방식(아이디와 비밀번호를 내 서비스에게 주는 방식)을 해결해주는 것이 바로 Oauth 2.0임!

 

2. Oauth 2.0의 방식

  • 내 서비스가 유저의 아이디와 비밀번호를 가지고 있던 방식에서
  • Resouce Server(카카오)가 Resouce owner의 요청에 의해 access token을 발급
    • access token은 우선 Resource owner의 아이디와 비밀번호같은 개인정보가 아니며, Resouce server의 모든 기능이 아니라 유저가 요청한 일부기능만 선택적으로 제공해줄 수 잇다는 장점이 있다.
  • Oauth를 통해 client(우리서비스)가 accesstoken을 획득한 후, Resouce Server(카카오)에 해당 토큰을 보여주면서 허가를 받아 다른 서비스의 데이터에 접근해서 데이터를 조회하고 수정하거나 삭제함

 

3. 등록

  • 우리의 client가 resource server를 이용하기 위해서는, resource server에 우리 클라이언트를 먼저 등록해야 함
  • 등록에 성공할 경우, client와 resource server사이에는 다음의 것이 정해진다
    • client ID : resource server입장에서 client를 식별하기 위한 id. 노출되어도 ㄱㅊ
    • client Secret : pw. 노출되어서는 안된다.
    • Authorized redirect URIs : resource server가 client에 권한을 부여하는 과정에서 권한이 부여된 코드(Authorized Code)를 주는데, 이때 코드를 전해줄 주소. 즉 client가 권한이 부여된 코드를 받을 주소. 반대로 resource server에서도 client id와 authorized redirect URIs가 일치하지 않는다면 요청을 무시함.

출처 : 생활코딩

4. Resource Owner의 허락(승인)

  • client가 resource server로의 등록이 완료되면, resource server는 클라이언트id의 비밀번호와 authorized redirect urls를 알게 된다.
  • 이제 client(우리서버)가 resource server의 특정 기능을 resource owner(유저)로 하여금 우리 서버(client)에서 사용할 수 있도록 한다고 하자. 즉, 단순하게 말해서 우리서비스에서 카카오톡 로그인을 할 수 있도록 하는 상황임
  • 우리(client)는 우선 유저에게 카카오톡 로그인 창을 보여줄 것임. 해당 로그인창은 다음과 같은 링크가 연결되어 있다.
https://resource.server/?client_id=1&scope=B,C&redirect_uri=https://client/callback
  • 우리 서비스(client)가 resource server에 등록된 id = 1
  • resource owner가 resource server에서 사용할 수 있는 모든 기능 중 B,C기능을 사용하려 한다
  • 권한이 부여된 코드를 받을 주소는 다음고 같다. : authorized_redirect_uri = https://client/callback 
  • 참고)만약 resource server에 등록된 client_id의 redirect_url과 일치하지 않는다면, resource server는 거기서 통신을 종료한다.

 

  • 아래는 실제 구글로그인 버튼에 연결되어 있는 링크의 예시
    • redirect url, scope, client_id 등이 확인된다
    • scope같은 경우는 url로 되어있는데, 구글에서 요구하는 양식일뿐 전체적인 틀 자체는 비슷하다.

출처:생활코딩

  • resource owner(유저)가 저 버튼을 누른 것이므로, 유저가 저 url로 요청을 보낸 것임
  • 그러면 서버는 유저에게 우선 로그인을 요구한다.
    • resource owner가 방금 요청을 보낸 유저가 해당 서비스의 유저인지를 확인하는 것 .
    • 만약 이미 로그인이 되어 있었다면 이 단계는 생략된다.
  • 로그인이 완료된다면 resource server는 우선 받은 client id가 존재하는지 확인하고, 해당 client id의 redirect_url이 받은 redirect_url과 일치하는지를 확인한다.(다르면 통신 종료)
  • 일치할 경우, resource server는 resource owner에게 B,C의 기능(scope)에 대한 권한을 client에게 부여할지를 묻는다.
  • owner가 승낙하면, owner가 이에 대해 허용했다는 정보가 resource server에게 전해짐
    • 즉, resource server는 해당 [user1 & scope B,C] 즉, 유저1이 scope에 대한 권한을 client에 부여하는 것에 허락했다는 정보를 가지고 있음
    • 근데 처음에 카카오로그인 버튼을 누를 때, client_id를 같이 보냈으므로, resouce server는 결론적으로 해당 user가 특정 client에 resourceserver의 b,c라는 기능에 대한 권한을 부여했다는 정보를 가지게 된다. 

 

5. Resource Server의 승인

  • resource owner의 승인을 받았으니, 해당 승인을 바탕으로 resource server가 이제 client에게 resource server의 기능을 사용할 수 있도록 승인을 해줘야 한다.
  • resouce server는 해당 user가 특정 client에 resourceserver의 b,c라는 기능에 대한 권한을 부여했다는 정보를 가지고 있음에도, 바로 access token을 발행하지 않고 authorization code 우선 발급하여 유저(resouce owner)에게 응답한다.
  • 응답할 때, authorization code를 location헤더에 redirect_url과 함께 보낸다
    • 응답을 받은 유저의 브라우저는 자동으로 location헤더의 주소로 redirect된다.(이건 걍 http통신의 규칙임)
#응답의 location헤더에 redirect_url과 authorization code를 담아서 보낸다.
Location : https://client/callback?code=3

 

  • redirect_url은 client(우리 서버)가 미리 설정해둔 주소임
    • 따라서 해당 주소로 redirect되면서 쿼리파라미터로 authorization code를 들고올 경우, client측에서 해당 code를 받을 수 있도록 미리 설정해둠으로써, client는 authorizaton code를 획득할 수 있다.

출처 : 생활코딩

 

  • 이제 authorization code를 알게된 client는, 해당 code를 가지고 resource server에 직접적으로(유저를 거치지 않고!) 통신을 요청한다.
    • 이때, authorization code와 redirect_url, client_id, client_secret을 함께 요청한다
    • 그 외에 grant_type 등을 같이 보냄
http://resource.server/token?grant_type=authorization_code&code=3&redirect_url=https://client/callback&client_id=1&client_secret=2
  • 이 부분에 대해 의문이 들었었음. 왜 바로 access_token을 보내지 않고, code를 보내서 한번 더 확인하는 거지?
    • 멘토님 의견에 따르면, 서버입장에서 보안 레이어를 한 겹 더 둔거임.
    • auth code를 서버에 보내는 과정에서, 등록할 때 발급한 client_secret을 서버가 받는데 이게 마치 PW와 같은 역할을 함. 즉 아이디와 비밀번호를 발급해서 한번 더 보안을 다진다는 의미에서 보안 레이어를 한겹 더 두었다 라고 볼 수 있음
    • 또한 설령 PW를 받지 않더라도 그냥 client/resource owner간의 통신을 한바퀴 더 돌려주는 것 자체가 보안을 강화시켜줄 수 있음. 마치 웹서버에서 서브넷을 통해 앞단에 alb나 proxy서버를 두어서 보안을 강화하는 것과 비슷한 맥락(물론 웹서버의 경우, alb나 proxy가 보안을 강화시켜주는 것 외에 다른 역할도 함)
    • 추가)모든 서비스의 Oauth혹은 소셜로그인이 이런 방식으로 돌아가는 것은 아님. client_secret을 받지 않는 곳도 있고, 이렇게 인가 코드를 주고 받는 것없이 그냥 바로 access_token을 주고 받는 경우도 있다.

 

6. Access token

  • code 및 client_secret을 기반으로 인증이 완료되었으면, 이제 access_token을 발급해야 함.
  • 또한 code 및 client_secret을 기반으로 인증이 완료될 경우, auth_code는 삭제되어야 한다.

 

  • 암튼, 이제서야 resource server는 access_token을 발급하여 client에게 직접 전달
  • 참고로 Oauth의 목적 자체가 바로 access_token을 발급하고, 이를 기반으로 (유저의 id와 pw같은 개인정보의 교류없이)인증이 진행될 수 있도록 하는 것에 있음
  • 이제 client가 전달받은 access_token은 , 해당 access_token을 가지고 있다면 특정 유저에 대한 resource server의 특정 기능(scope)에 대한 권한을 가지고 접근할 수 있음을 의미한다.

출처 : 생활코딩

  • access_token4를 가지고 있다 = id가 1인 user의 b,c기능에 대해 접근할 수 있다
  • resource server가 해당 토큰을 client에게 줌으로써, 클라이언트는 이제 id가 1인 유저의 b,c기능에 접근할 수 있게 되는 것임

 

7. API조작

  • 이제 access_token이 있으므로 필요한 기능에 접근할 수 있는 권한이 있음
  • 하지만 권한이 있다고 내 멋대로 resource server에서 원하는 정보를 들고올 수 있는 게 아님
  • resource_server에서 요구하는 대로 그 방식에 맞게 정보를 요청하거나 수정해야 하며, 요구되는 그 방식을 API라고 부름
  • 백엔드가 권한을 보증하는 카카오 토큰을 가지고 카카오 서버에 접근해서 원하는 정보를 가져오는 것 자체가 카카오API를 조작하는 것

 

 

8. Refresh Token

  • access_token은 수명이 있음. 그 수명이 끝났을 때, 더이상 권한을 보증해주지 않음
  • 이때 새 access_Token을 발급해주기 위한 토큰이 refresh token임
  • access_token이 만료되었을 때, refresh_token을 보여줌으로써 새로운 access_token을 발급받을 수 있다.

출처 : rfc 6749

 

  • 물론 모든 서비스에서 공통적으로 적용되는 사항이 아니며, refresh_token을 사용하지 않고 매번 그냥 새로운 access_token을 발급받도록 하는 곳도 있다. 선택의 문제
  • refresh_token을 도대체 왜 받는가? 어차피 다시 refresh_token을 주고 access_token을 새로 발급받을 거라면, 그냥 access_token의 유효기간을 길게 하면 될텐데? 라는 의문이 생길 수 있음
    • 이에 대해서는 보안상의 측면에 이점이 있는 듯함
    • access_token은 한번 탈취당하면, 해당 토큰이 만료될때까지 계속해서 특정 유저의 특정기능에 접근할 수 있음
    • 즉 access_token이 털릴 경우, 유효기간이 길다면 계속해서 개인정보가 털릴 수 있는 것
    • 반대로 access_token의 유효기간을 아주 짧게 만들면, 빠른시간내에 만료가 되므로 혹여나 털리더라도 오랜시간 털리지는 않을 수 있음

'network(http..)' 카테고리의 다른 글

Network port forwarding(WSL 원격통신을 위한 준비)  (0) 2022.05.06
인증(암호화 / bcrypt ) , 인가(JWT)  (0) 2022.04.18
HTTP 개괄  (0) 2022.04.07
쿠키, 세션, 토큰  (0) 2022.03.18
HTTP 헤더2// http 강의 (8)  (0) 2022.01.10

BELATED ARTICLES

more