ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OAuth 프로토콜의 이해와 활용 2 - OAuth란 무엇인가?
    IT, 프로그래밍/보안 2020. 6. 29. 21:37

    앞에서는 OAuth가 왜 필요하고 어떻게 발전해 왔는지 알아보았습니다.

     

    이번시간에는 OAuth가 무엇이고, 어떻게 흘러가는지 알아보겠습니다.

     

    OAuth는 위와 같은 플로우로 이루어 집니다.. 라고 하면 처음 보시는 분들은 당연히 이해하기 힘드실 거라고 생각하기에

     

    쉽게 예제로 한 번 알아보겠습니다.

     

    다들 살면서 면회를 한 번씩은 가보셨을꺼라고 생각합니다.

     

    군부대에 면회를 갔다고 생각하고 OAuth가 어떻게 동작하는지 알아봅시다.

     

    (실제와는 약간 차이가 있을 수 있는점 감안해주세요!)

     

    군부대는 기본적으로 보안을 매우 중요시하고, 특별한 목적 없이는 들어갈 수 없습니다.

     

    또한, 들어간다 하더라도 신분에 따라 머무를 수 있는 시간과 들어갈 수 있는 공간이 다릅니다.

     

     

    오늘 김일병의 가족이 김일병을 면회왔다고 생각해봅시다.

     

    우선 김일병의 가족은 위병소 (군부대의 출입을 통제하는 곳)에 도착하면, 어떤 목적으로 부대에 방문하려고 하는지, 방문자는 누구인지 명확하게 밝혀야 합니다. 

     

     

    위병소에서는 김일병에게 가족이 면회 왔다는 소식을 알리고, 실제 가족이 맞는지 확인합니다.

     

    실제 가족이 맞다면, 김일병은 위병소에 가족이 맞다고 대답합니다.

     

     

    위병소에서는 김일병의 가족에게 면회가 허용된 장소로 안내하고, 그 장소에만 머무를 수 있는 임시 출입증을 줍니다.

    이 임시 출입증은 면회소 외의 장소에 출입할때는 사용할 수 없고, 18시까지만 머무를 수 있습니다.

     

    그런데, 군부대에는 장병들의 가족들만 올 수 있는게 아니죠.

     

    가끔 군부대 내에 있는 시설이 고장나면, 민간 업체에 맡겨서 수리를 하기도 합니다.

     

    보일러가 고장나서, 외부 업체가 수리를 하러 온 상황을 생각해 봅시다.

     

    우선 보일러 수리공이 위병소에 도착해서 자신의 방문 목적과 신원을 명확하게 알립니다.

     

    위병소에는 해당 시설 담당자에게 방문하고자 한 보일러 수리공이 맞는지 확인합니다.

    담당자는 수리하러 온 게 맞으면 맞다고 대답을 해줍니다.

     

     

    위병소에서는 보일러 수리공에게 A건물에 출입할 수 있는 임시출입증을 발급합니다.

     

    이 임시출입증은 A건물에만 내일 18시까지 출입할 수 있습니다.

     

     

     

    여기서 우리가 주목해야 할 점은 방문자들 모두 방문 목적과 신분에 따라 접근할 수 있는 곳이 달랐다는 것입니다.

    김일병의 가족과 보일러 수리공은 허락받은 장소외에는 갈 수 없고, 장소 출입 시 반드시 임시출입증을 지참하여야 합니다.

     

    또한 부대 내에 있는 구성원이 접근하려는 외부인의 신원을 확인해 주었다는 점도 기억합시다.

     

    김일병과 시설 관리 담당자는 각각 접근하려는 외부인의 신원을 확인하고 보증해 주었습니다.

     

     

     

    위에서 알아본 예제는 각각 OAuth의 핵심인 인증과 인가를 나타낸것입니다.

     

    OAuth에서 Resource Server (리소스를 가지고 있는 서버)는 Resource Owner(리소스의 소유자)에게 인증을 받음으로써, 해당 Client(리소스가 필요한 사용자)가 Resource에 접근할 수 있는지 확인합니다.

     

    그리고 인증된 Client는 자신의 목적에 따라 허용된 정보에만 접근할 수 있습니다.

     

    만약 김일병의 가족이 자신에게 허용된 면회소를 넘어 병사 막사에 들어가려고 하거나, 보일러 수리공이 병기 창고에 들어가려고 하면 어떻게 될까요?

     

    당연히 헌병대가 찾아와 끌어낼 것입니다.

     

     

     


     

     

     

    자 이제 구글에 있는 사용자의 이름과 이메일에 OAuth에 따라 접근하는 과정을 알아보겠습니다.

     

    새로운 커뮤니티 서비스를 구축하는데, '구글로 로그인하기' 기능을 구현하려고 합니다.

     

    사용자에게 이름과 비밀번호를 입력받는 대신 구글에 저장된 사용자의 정보를 받아올 것입니다.

     

     

    여기서 OAuth의 참여자를 정리하면,

     

     

     

    Client (커뮤니티 서비스) = 리소스에 접근하려고 하는 주체, 서비스 제공자에 있는 특정 정보에 접근하여 사용하고자 한다.

     

    Resource (유저 정보, 이메일, 이름) = 서비스 제공자에 저장된 정보.

     

    Resoure Owner (커뮤니티 사용자) = Client에 제공하는 정보를 가지고 있는 사람. 여기서는 이메일과 이름을 제공해서 편리하게 로그인하고 싶어 하는 커뮤니티 사용자.

     

    Service Provider (구글) = 리소스를 저장하고 있는 제3의 주체. Client가 여기에 저장된 정보에 접근하고자 한다. 보통 구글이나 페이스북같이 큰 기업이 많다.

     

     

     

    1. Service Provider에 Client 정보 등록


     

    우선 Client는 Service Provider에 자신의 신원을 등록해야 합니다.

    보통 Service Provider에서 계정을 만든 후에 사용 등록을 하면 Client별로 고유로 식별할 수 있는 Client Id와 Secret Key가 생성됩니다.

    이 Id와 Key는 Client를 식별하고 신원을 확인하는 데 사용됩니다.

     

    위는 구글에서 Client로 등록하는 화면인데요.

    위에 보면 Client Id와 Client Secret Key를 확인할 수 있습니다.

    위의 키들은 노출되면 심각한 보안 문제가 생길 수 있으니 유의하세요.

     

    하단에 보면 Redirect URI를 등록하는 곳이 있는데요.

     

    이 부분은 Service Provider가 Client에게 임시출입증과 같은 Access Token과 토큰을 발급받기 위해 사용하는 Authentication Code를 전해주는 경로입니다.

     

    보통은 Client가 "만약 리소스를 가진 사람이 자기 정보를 써도 된다고 하면 발급된 토큰은 어디 어디로 보내줘! " 하고 Redirect URI를 요청 시에 같이 파라미터로 넘겨주는데요.

     

    Resource Owner가 Client가 해당 리소스를 사용해도 좋다고 허가를 한 후에, 응답 메시지 헤더에 302 상태 코드를 넣어서 이 경로로 Resource Owner를 거쳐 Client에게로 슬쩍 전달해주게 됩니다.

     

    이때 허용된 Redirect URI를 미리 정해놓고 검사하지 않은 채 Client가 그냥 달라는대로 보내준다면,

     

    나중에 악의적인 목적을 가진 사람이 Client인체 하고 토큰을 달라고 하면 그대로 보내주게 되겠죠.

     

    토큰이 탈취되면 큰 문제가 생길 수 있습니다.

     

     

     

     

    2. Client의 인증 요청 & 권한 부여 요청


     

     

    우리가 만든 커뮤니티 서비스에 반한 한 사람이 회원가입 페이지로 '구글 아이디로 가입' 버튼을 눌렀습니다.

     

    누름과 동시에 Client Page에서는 Service Provider에 권한 부여를 위해 Resource Owner의 승인을 요청하게 됩니다.

     

    Service Provider는 2개의 서버가 있는데요.

     

    인증 및 권한 부여를 담당하는 Authoriation Server (인증 서버)와 사용자의 데이터를 관리하는 Resource Server (리소스 서버)가 있습니다.

     

    이건 OAuth 2.0의 특징이긴 한데 참고하세요.

     

    권한 인증을 요청할 때는 처음에 등록한 Client Id와 사용할 리소스의 범위를 나타내는 Scope, 그리고 Resource Owner의 리소스 사용 승인 시 임시 토큰인 Authorization Code를 전달할 Redirect Url을 함께 파라미터로 넘겨줍니다.

     

    예를 들어 Client Id가 curiduck, 접근할 정보가 email, name이고 redirect url은 /myserivce/auth/success라고 하면, 쿼리 스트링으로 나타내면 이렇게 되겠죠.

     

    https://auth.google.com/profile?clientId=curiduck&scope=email,name&redirect_url=/myserivce/auth/success

     

    그러면 Service Provider에서는 Resource Owner가 로그인하여 리소스 사용을 승인할 수 있는 페이지로 302 응답을 통해 또 슬쩍 Resource Owner를 이동시킵니다.

     

    이 페이지는 Client가 사용할 권한 목록을 Resource Owner에게 명시적으로 보여주며,

    Resource Owner는 이에 동의 시 

    "나는 이 Client가 Scope에 명시한 범위 안에 있는 내 데이터에 접근할 권한을 부여하는 것에 동의합니다"라고 말하는 것과 같습니다.

     

     

     

    3. 인증 성공 시 Authentication Code 부여


     

     

    Resource Owner가 인증 및 권한 사용 승인까지 마치면, Service Provider의 인증 서버는 Access Token을 발행받기 위한 Authentication Code를 302 상태 코드를 통해 Resource Owner가 모르게 슬쩍 Client에게 전달해줍니다.

     

    * 302 코드는 URL을 Redirect 시킨다는 뜻으로 Response 헤더에 설정된 Location 필드에 있는 URL로 사용자를 이동시킬 수 있습니다.

     

    이 Authentication Code(인가 코드)는 "이 Client는 Resource Owner에게 사용 허락을 받았음"이라고 적혀있는 증서와 같습니다.

     

    이로써 Client는 정보에 접근하기 위한 출입증인 Access Token을 발행받을 준비가 되었습니다!

     

     

     

    4. Access Token 발행 요청

     


     

    Client는 서비스 제공자에게 Client Id와 Secret Key, Access Token이 발행되면 아까 Authentication Code를 발급 받을때 사용했던 Redirect Url, 그리고 아까 Resource Owner에게 받은 인가 코드를 가지고 Access Token을 발행 요청을 합니다.

     

    서비스 제공자의 인증 서버는 리소스에 접근할 수 있는 Access Token을 발행하고 Client에게 보내줍니다.

     

    이때 Refresh Token도 같이 넘겨주는데요.

     

    보통 Access Token은 보안을 위해 유효시간을 짧게 설정하기 때문에, 몇 시간에서 길어야 반나절 정도까지 유효하지 않습니다.

     

    이렇게 되면 자주 Resource Owner에게 사용 허가를 받아야 한다는 단점이 있죠.

     

    자동 로그인이 몇 시간만 유지되면 얼마나 불편할까요..

     

    이런 불편함을 개선하기 위해 Access Token을 다시 발급받을 수 있는 Refresh Token을 같이 넘겨줍니다.

     

    Refresh Token이 있으면 Resource Owner에게 다시 허락을 안 받고 Access Token을 발급받을 수 있죠.

     

    Refresh Token은 Access Token보다 유효시간이 훨씬 깁니다.

     

    이게 탈취되면 쉽게 Access Token을 가져올 수 있으므로, Client는 보안에 유의해야 하며 DB에 넣어두고 사용합니다.

     

     

     

    5. 리소스에 접근 요청


     

     

    Access Token을 받았으면 Client는 이 토큰을 통해 Resource Server에서 사용자의 정보에 접근합니다.

    이 Resource Server에 접근하면 바로 정보를 꺼내 주는 게 아니라, Access Token이 저장된 DB에 비교하여 지정된 Scope에 접근하는 게 맞는지 확인 후에 돌려줍니다.

     

    보통은 요청 헤더에 많이 세팅하는데요.

     

    Authorization: Bearer <ACCESS TOKEN>

     

    같은 형식으로 지정합니다.

     

    여기서 Bearer는 전달자, 운반자라는 뜻이 있습니다 (tmi입니다)

     

     

     

    6. Access Token 재발급 요청


     

    시간이 지나서 Access Token이 만료된다면 좀 전에 말했듯이 Refresh Token을 통해 새로 발급받을 수 있습니다.

    Access Token을 발급받을 때 보통 expires라는 항목으로 유효시간이 같이 넘어오는데요.

    이를 통해 유효시간이 지났는지 확인할 수 있고 지났으면 Refresh Token으로 재발급받습니다.

     

    오늘은 OAuth가 어떤 것이고, 어떤 방식으로 동작하는지 흐름을 쭉 살펴보았습니다.

    다음 시간에는 OAuth의 여러 가지 인증 방식들을 알아보겠습니다.

    감사합니다.

Designed by Tistory.