OAuth 2는 보안 토큰을 사용한 재생 공격과 같은 것들로부터 어떻게 보호합니까?


564

내가 이해했듯이에서 OAuth 2에서 다음과 같은 일련의 이벤트가 발생하여 의 사용자 정보 Site-A에 액세스 합니다.Site-B

  1. Site-A에 등록 Site-B하고 비밀과 ID를 얻습니다.
  2. 사용자가Site-A액세스 Site-B, 사용자가 전송됩니다 Site-B그들이 말해 어디에 Site-B그들이 것 참 좋아하는 줄 것을 Site-A특정 정보에 대한 권한을.
  3. Site-B인증 코드와 함께 사용자를 (으)로 다시 리디렉션 Site-A합니다.
  4. Site-A그런 다음 Site-B보안 토큰에 대한 대가 로 해당 인증 코드를 비밀과 함께 전달합니다 .
  5. Site-A그런 다음 보안 토큰을 요청과 함께 번들하여 사용자Site-B 를 대신하여 요청합니다.

보안 및 암호화 측면에서이 모든 것이 어떻게 작동합니까? OAuth 2는 보안 토큰을 사용한 재생 공격과 같은 것들로부터 어떻게 보호합니까?


49
oauth2는 여기서 간단히 설명합니다 : gist.github.com/mziwisky/10079157
Paolo

4
사양을 읽으십시오 : tools.ietf.org/html/rfc6749 당신은 그것이 얼마나 이해 가능한지 놀랄 것입니다. 너무 나쁘지 않을 수도 있습니다.
Kris Vandermotten

1
이 질문과 그 (현재) 답변은 모두 OAuth 2.0의 특정 "grant type"에 중점을두고 code있지만 OAuth 2.0에는 다른 사용 사례와 관련이있는 다른 grant 유형이 있습니다 (예 : 비 사용자 관련 사례).
Hans Z.

4
아, "사이트 B"를 "IdProvider 사이트"와 같이 더 읽기 쉬운 것으로 바꾸지 않겠습니까?
Yurii

답변:


1378

OAuth 2.0의 실제 작동 방식 :

나는 창에서 가장 맛있는 도넛을 보았을 때 출근길에 올라프 빵집에서 운전을했습니다. 그래서 안으로 들어가서 "도넛이 있어야 해요!" 그는 "30 달러가 될 것"이라고 말했다.

네, 도넛 한 개에 30 달러입니다! 맛 있어야합니다! 요리사가 갑자기“아니오! 나는 물었다 : 왜? 그는 은행 송금 만 허용한다고 말했다.

진심이야? 네, 그는 진지했습니다. 나는 거의 바로 그곳으로 걸어 갔지만 도넛이 내게 불렀다. "저는 맛있어요 ...". 도넛을 주문한 사람은 누구입니까? 나는 말했다.

그는 나에게 그의 이름이 적힌 메모 (도넛이 아닌 요리사)를 나눠 주었다. 그의 이름은 이미 메모에 있었으므로 그 말의 요점이 무엇인지 모르겠지만 괜찮습니다.

나는 1 시간 반을 내 은행으로 몰았다. 나는 그 메모를 텔러에게 건네 주었다. 나는 그녀의 올라프가 나를 보냈다고 말했다. 그녀는 저에게 "읽을 수 있습니다"라는 외모 중 하나를 주었다.

그녀는 내 메모를하고, 신분을 물었고, 돈을 얼마나 주면 좋을지 물었다. 나는 그녀에게 $ 30 달러를 말했다. 그녀는 낙서를하고 나에게 또 다른 메모를 건네 주었다. 이 숫자에는 많은 숫자가 있었는데, 그것이 그들이 메모를 추적하는 방법이라고 생각했습니다.

그 시점에서 나는 굶주리고 있습니다. 나는 한 시간 반 후에 서서히 올라와 올라프 앞에 서서 메모를 확장했다. 그는 그것을 가져 가서 살펴보고 "돌아 올게요"라고 말했다.

나는 그가 내 도넛을 받고 있다고 생각했지만 30 분 후에 나는 의심스러워지기 시작했다. 그래서 카운터 뒤에있는 사람에게 "Olaf는 어디에 있습니까?"라고 물었습니다. 그는 "돈을 얻으 러 갔다"고 말했다. "무슨 소리 야?" "그는 은행에 메모합니다".

허프 .. 그래서 올라프는 은행이 저에게 줬다는 기록을 가지고 은행으로 돌아와서 내 계좌에서 돈을 얻었습니다. 은행이 나에게 준 메모를했기 때문에 은행은 내가 말하고있는 사람이라는 것을 알았고, 은행과 이야기했기 때문에 그들은 단지 그에게 30 달러 만 주겠다고 알았습니다.

올라프가 내 앞에 서서 마침내 내 도넛 을 나에게 줬기 때문에 그것을 알아내는 데 오랜 시간이 걸렸다 . 내가 떠나기 전에 나는 "올라프, 당신은 항상 이런 식으로 도넛을 팔았습니까?"라고 물어야했습니다. "아니오, 저는 다르게 했어요."

허. 차에 걸어 가면서 전화가 울렸다. 나는 대답을 귀찮게하지 않았다, 아마 내 직업은 나를 해고 전화, 내 상사는 그런 ***입니다. 게다가, 나는 방금 겪었던 과정에 대해 생각했다.

Olaf가 계좌 정보를 제공하지 않고도 은행 계좌에서 30 달러를 인출 할 수있었습니다. 그리고 이미 은행에 $ 30 만 가져가도된다고 말했기 때문에 돈이 너무 많이 들지 않을까 걱정할 필요가 없었습니다. 그리고 은행은 그가 올라프에게 나에게 준 메모를했기 때문에 그가 올바른 사람이라는 것을 알았습니다.

알았어. 내 주머니에서 30 달러를 주겠다. 그러나 이제 그는 은행에 매주 $ 30를 가져 오라고 할 수 있다는 점을 알게되었으므로 빵집에 나타나서 더 이상 은행에 갈 필요가 없었습니다. 원한다면 전화로 도넛을 주문할 수도 있습니다.

물론 나는 그렇게하지 않을 것입니다. 도넛은 역겨 웠습니다.

이 접근 방식이 더 넓은 응용 프로그램인지 궁금합니다. 그는 이것이 그의 두 번째 접근법이라고 언급했습니다. Olaf 2.0이라고 부를 수 있습니다. 어쨌든 나는 집으로 돌아가는 것이 좋으며 새로운 일자리를 찾기 시작해야한다. 그러나 도시의 새로운 곳에서 딸기 쉐이크 중 하나를 얻기 전에는 그 도넛의 맛을 씻어 낼 무언가가 필요합니다.


41
실제로 Olaf는 도넛을 주문하지 않더라도 원할 때마다 계정에서 30 달러를받을 수 있어야합니다. 흥미롭게도 그것은 실제 oauth2.0 시나리오의 주요 목표입니다 :) 이것은 분명히 훌륭한 대답이지만, 이것을 읽는 사람은 Paolo가 질문에 대한 그의 의견 ( gist.github.com/mziwisky/ 10079157 ). 개념을 명확하게하기위한 좋은 보충 자료.
Samiron

4
@Samiron이 지적했듯이 Olaf는 언제든지 원할 때 30 $를받을 수 있습니다. 2. 실제 OAuth2.0 시나리오에서 Olaf는 은행에서 돈을 꺼내기 전에 도넛을 제공 할 수 없습니다. 이 예에서 그는 수표를 보관하고 잘 익힌 도넛을 루이스에게 건네 줄 수있었습니다. 따라서 우리가 Olaf에게 내가 아는 제 3 자로부터 반죽을 얻도록 허가하도록 예제를 변경하면 Olaf가 도넛을 굽기 전에 반죽을 가져와야합니다 (고독한 도넛 Olaf 가정) 표시 목적으로 만 사용되었습니다!).
티커 23

4
도너 스토리는 유감스럽게도 귀하의 기술적 정정을 능가합니다-나는 그것을 읽을 때 스토리에 팔렸습니다. 호머 심슨이 썼습니다.
shevy

4
@Prageeth Olaf는 항상 훼손 될 경우 잉크가 새는 안전한 상자에 은행에주고받는 메모를 보관합니다. 메모를 복원하는 데 많은 시간이 걸립니다. Olaf는 베이킹 사고로 손가락을 잃어버린 경우 Luis에게 은행 송금을 다시 설정하도록 요청해야하며 다음 번에 Breaking Bread 문신으로 Olaf를 식별해야합니다. .
Chris

11
나는 다음 사람만큼이나 귀여운 답변을 좋아하며, 그들의 귀여움이 대답을 더 쉽게 접근 할 수있게 도와 주면 ...하지만 하루가 끝날 때 스택 오버플로는 사람들을 교육하는 것이므로이 귀여운 이야기는 그렇게하지 않습니다. 도넛 비유를 이해하기 위해서는 OAuth2의 작동 방식을 이미 이해해야하지만 정답의 요점은 정확히 설명해야했습니다. 개념을 실제로 설명하기 위해이 (상단) 답변을 편집하는 것이 좋습니다. 농담을 두 번이나 비용이 들더라도 끝에서 간접적으로 참조하는 것이 아닙니다.
machineghost

133

내가 읽은 내용에 따라 다음과 같이 작동합니다.

질문에 요약 된 일반적인 흐름이 맞습니다. 2 단계에서 사용자 X가 인증되고 사이트 B가 사이트 B에 대한 사용자 X의 정보에 액세스 할 수있는 권한을 부여합니다. 4 단계에서 사이트는 자신의 비밀을 사이트 B로 다시 전달하여 인증 코드뿐만 아니라 자체를 인증합니다. (사용자 X의 액세스 토큰)을 요구하고 있습니다.

전반적으로 OAuth 2는 실제로 매우 간단한 보안 모델이며 암호화는 직접 적용되지 않습니다. 대신 비밀 및 보안 토큰은 모두 기본적으로 비밀번호이며 전체는 https 연결의 보안으로 만 보호됩니다.

OAuth 2는 보안 토큰 또는 비밀의 재생 공격에 대한 보호 기능이 없습니다. 대신, 사이트 B는 전적으로 이러한 항목을 책임지고 내 보내지 않도록하고 사이트가 전송되는 동안 https를 통해 전송되는 사이트 B에 의존합니다 (https는 URL 매개 변수를 보호합니다).

인증 코드 단계의 목적은 편의상 간단하며 인증 코드는 그 자체로 특별히 민감하지 않습니다. 사이트 B에 사용자 X의 액세스 토큰을 요청할 때 사이트 A에 대한 사용자 X의 액세스 토큰에 대한 공통 식별자를 제공합니다. 사이트 B에있는 사용자 X의 사용자 ID만으로는 작동하지 않았을 것입니다. 동시에 여러 사이트에 전달되기 위해 대기중인 많은 액세스 토큰이있을 수 있기 때문입니다.


28
인증 코드의 중요한 기능을 간과했습니다. 인증 코드를 교체하는 추가 단계를 거치지 않고 새로 고침 토큰 (보안 토큰이라고 함)을 즉시 반환하지 않는 이유는 무엇입니까? 새로 고침 토큰을 캡처하면 재생 공격이 허용되지만 인증 코드는 한 번만 사용할 수 있기 때문입니다.
모리스 Naftalin

3
좋아, @mauricen, 그 말이 맞아 .... 그러나 각 요청마다 전달되는 것이기 때문에 새로 고침 토큰으로도 재생 공격이 일어날 수 없었습니까?
Mr Mikkél

15
인증 코드는 사용자를 통해 전달되므로 (예를 들어) 쿠키로 저장 될 수 있습니다 ( stackoverflow.com/questions/4065657/… 참조 ). 새로 고침 토큰은 두 사이트간에 직접 전달되므로 훨씬 덜 취약합니다.
모리스 Naftalin

호기심에서 OAuth는 프로그램이 사용할 고유 식별자를 반환합니까? 예를 들어, 현재 사용자 식별을 위해 MAC 주소를 사용하고 있지만 MAC은 신뢰할 수 없으며 쉽게 스푸핑 등입니다. MAC 주소 식별 메커니즘을 폐기하고 사용자를 고유하게 식별 할 수 있으면 OAuth로 이동할 수 있습니다.
theGreenCabbage

1
이 다이어그램에서 tools.ietf.org/html/rfc6749#section-4.1 "비밀"은 표시되지 않으며 클라이언트 식별자 (질문의 ID) 만 표시됩니다. 비밀이 중요한 이유와 RFC에 포함되지 않은 이유는 무엇입니까? 또한 질문에는 클라이언트 ID (A)의 초기 전송에서 전달되고 XSSF로부터 보호하기 위해 인증 코드와 함께 클라이언트로 다시 리디렉션되는 것이 권장되는 로컬 상태도 있습니다.
David Williams

104

OAuth는 3 자 앱이 계정 및 비밀번호없이 다른 웹 사이트에 저장된 데이터에 액세스 할 수있는 프로토콜입니다. 보다 공식적인 정의는 Wiki 또는 사양을 참조하십시오.

유스 케이스 데모는 다음과 같습니다.

  1. LinkedIn에 로그인하여 내 Gmail 연락처에있는 친구를 연결하고 싶습니다. LinkedIn은이를 지원합니다. Gmail에서 보안 리소스 (내 gmail 연락처 목록)를 요청합니다. 그래서이 버튼을 클릭합니다 :
    연결 추가

  2. 계정과 비밀번호를 입력하면 웹 페이지가 팝업되고 Gmail 로그인 페이지가 표시됩니다.
    연결 추가

  3. 그런 다음 Gmail은 "동의"를 클릭하는 동의 페이지를 표시합니다. 연결 추가

  4. 이제 LinkedIn에서 Gmail의 내 연락처에 액세스 할 수 있습니다. 연결 추가

아래는 위 예제의 순서도입니다.

연결 추가

1 단계 : LinkedIn은 Gmail Authorization Server에 토큰을 요청합니다.

2 단계 : Gmail 인증 서버가 리소스 소유자를 인증하고 사용자에게 동의 페이지를 표시합니다. (사용자는 아직 로그인하지 않은 경우 Gmail에 로그인해야합니다)

3 단계 : 사용자가 LinkedIn이 Gmail 데이터에 액세스하도록 요청합니다.

4 단계 : Gmail 인증 서버가 액세스 토큰으로 응답합니다.

5 단계 : LinkedIn은이 액세스 토큰으로 Gmail API를 호출합니다.

6 단계 : 액세스 토큰이 유효한 경우 Gmail 리소스 서버가 연락처를 반환합니다. (토큰은 Gmail 리소스 서버에서 확인합니다)

OAuth에 대한 자세한 내용은 여기 를 참조 하십시오 .


모든 이미지가 사라졌습니다. stack.imgur에로드 할 수 있습니까?
ChrisF

1
어떻게이 문제를 해결할 수 있습니까? 이 프로세스는 LinkedIn이 아닌 사용자 앞에 앉아 시작한 것이 아닙니다. 그러나 당신은 3 단계로 그것을 가지고 있습니다. 이것은 내가 얻지 못한 것입니다.
Matt

17
가장 쉬운 설명. 고마워, 나는 다시 도넛을 사지 않을 것이다
OverCoder

링크 된 4 단계는 인증 토큰과 함께 반환됩니다. 이것은 5 단계에서 제공되어야하며 여기서 보호 토큰에 추가로 사용될 수있는 액세스 토큰과 새로 고침 토큰을 얻게됩니다.
amesh

@amesh 감사합니다. 맞습니다. 인증 코드 흐름입니다. 여기서는 OAuth 2의 기본 개념을 간단하게 설명했습니다.
Owen Cao

24

RFC6750 에서 해제 된 그림 1 :

     +--------+                               +---------------+
     |        |--(A)- Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        |<-(B)-- Authorization Grant ---|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(C)-- Authorization Grant -->| Authorization |
     | Client |                               |     Server    |
     |        |<-(D)----- Access Token -------|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(E)----- Access Token ------>|    Resource   |
     |        |                               |     Server    |
     |        |<-(F)--- Protected Resource ---|               |
     +--------+                               +---------------+

13

이것이 Oauth 2.0의 작동 방식이며, 이 기사 에서 잘 설명되어 있습니다.

여기에 이미지 설명을 입력하십시오


페이스 북이나 다른 타사를 사용하지 않고 전화 앱과 함께 비밀 키 및 TOTP 토큰을 사용하여 webapp를 보호하는 관점에서 OAUTH2를 설명 할 수 있습니까?
Al Grant

Facebook은이 예제에서 권한 부여 서버이며 모든 클라이언트에 액세스 토큰을 발행하여 Facebook API에 액세스 할 수 있습니다. API를 보호하려면 고유 한 권한 부여 서버를 구현해야합니다. 그런 다음 액세스 토큰을 얻는 데 사용할 부여 유형을 결정합니다. 정확히 당신이 원하는 것을 말해? 설명 할 것이다.
Suraj

springboot 보안 설정을 찾고 있습니다. 등록시 클라이언트 (전화) 및 webapp 교환 비밀번호-Google 인증자를 사용하여 비밀번호 외에 로그인시 입력 할 시간 / 비밀 기반 코드를 생성하십시오.
Al Grant

내 마지막 코멘트가 더 이상 당신을 밝히나요? 트위터 정보 내 프로필보기
Al Grant

등록시 고객 ID와 비밀을 얻을 수 있습니다. 그런 다음 전화는 클라이언트 ID로 webapp (authorization server)에 로그인 요청을합니다. 웹 응용 프로그램은 클라이언트 ID를 확인하고 OTP를 전화로 보냅니다. 전화는 클라이언트 토큰으로 webapp에 대한 다른 요청을하여 OTP와 액세스 토큰을 교환합니다. 전화는이 accss 토큰을 사용하여 webapp의 보호 된 리소스에 액세스합니다. 나는 이것이 주어진 시나리오에 대한 Oauth2 흐름이라고 생각합니다. 도움이되는지 알려주세요.
Suraj

10

이것은 보석입니다.

https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2

아주 간단한 요약 :

OAuth는 다음과 같은 네 가지 역할을 정의합니다.

  1. 자원 소유자
  2. 고객
  3. 리소스 서버
  4. 인증 서버

귀하 (자원 소유자)에게 휴대폰이 있습니다. 여러 개의 다른 이메일 계정이 있지만 모든 이메일 계정을 하나의 앱에 포함 시키려고하므로 계속 전환 할 필요가 없습니다. 따라서 GMail (클라이언트)은 Yahoo의 Authorization Server를 통해 Yahoo 이메일 (Resource Server)에 액세스하도록 요청하므로 GMail 응용 프로그램에서 두 이메일을 모두 읽을 수 있습니다.

OAuth가 존재하는 이유는 GMail이 Yahoo 사용자 이름과 비밀번호를 저장하는 것이 안전하지 않기 때문입니다.

여기에 이미지 설명을 입력하십시오


8

다른 답변은 매우 상세하며 OP가 제기 한 대부분의 질문을 다룹니다.

"OAuth 2가 보안 토큰을 사용한 재생 공격과 같은 것들로부터 어떻게 보호합니까?"라는 OP의 질문을 구체적으로 설명하기 위해 OAuth 2를 구현 하기위한 공식 권장 사항에는 두 가지 추가 보호 기능이 있습니다 .

1) 토큰은 일반적으로 만료 기간이 짧습니다 ( http://tools.ietf.org/html/rfc6819#section-5.1.5.3 ).

토큰의 짧은 만료 시간은 다음 위협으로부터 보호하는 수단입니다.

  • 다시 하다...

2) 사이트 A에서 토큰을 사용하는 경우 URL 매개 변수로 표시되지 않고 권한 부여 요청 헤더 필드 ( http://tools.ietf.org/html/rfc6750 )에 토큰이 표시되는 것이 좋습니다 .

클라이언트는 "베어러"HTTP 인증 체계와 함께 "인증"요청 헤더 필드를 사용하여 베어러 토큰으로 인증 된 요청을 작성해야합니다. ...

"application / x-www-form-urlencoded"방법은 참여 브라우저가 "Authorization"요청 헤더 필드에 액세스 할 수없는 응용 프로그램 컨텍스트를 제외하고는 사용하지 않아야합니다. ...

URI 쿼리 매개 변수 ...는 현재 사용을 문서화하기 위해 포함됩니다. 보안 결함으로 인해 사용하지 않는 것이 좋습니다


3

다음은 OAuth2가 4 가지 보조금 유형, 즉 앱이 액세스 토큰을 얻을 수있는 4 개의 다른 흐름에서 작동하는 방법에 대한 가장 간단한 설명입니다.

유사성

모든 보조금 유형 흐름에는 두 부분이 있습니다.

  • 액세스 토큰 받기
  • 액세스 토큰 사용

두 번째 부분 '사용 액세스 토큰' 은 모든 흐름에서 동일합니다.

각 부여 유형에 대한 흐름 '액세스 토큰 가져 오기' 의 첫 번째 부분은 다양합니다.

그러나 일반적으로 '액세스 토큰 받기' 부분은 5 단계로 구성됩니다.

  1. OAuth 제공자 (예 : Twitter 등)에 앱 (클라이언트)을 사전 등록하여 클라이언트 ID / 비밀을 확보하십시오.
  2. 클릭 한 사용자가 OAuth 공급자로 리디렉션되어 인증되도록 페이지에 클라이언트 ID 및 필수 범위 / 권한이있는 소셜 로그인 버튼을 만듭니다.
  3. OAuth 공급자가 사용자에게 앱 (클라이언트)에 권한을 부여하도록 요청
  4. OAuth 제공자 문제 코드
  5. 앱 (클라이언트)이 액세스 토큰을 얻습니다.

다음은 5 단계를 기반으로 각 부여 유형 흐름이 어떻게 다른지 비교 한 단계별 다이어그램입니다.

이 다이어그램은 https://blog.oauth.io/introduction-oauth2-flow-diagrams/ 에서 가져온 것입니다.

여기에 이미지 설명을 입력하십시오

각기 다른 수준의 구현 난이도, 보안 및 사용 사례가 있습니다. 필요와 상황에 따라 그 중 하나를 사용해야합니다. 어느 것을 사용해야합니까?

클라이언트 자격 증명 : 앱이 단일 사용자에게만 서비스하는 경우

리소스 소유자 비밀번호 자격 증명 : 사용자가 자신의 자격 증명을 앱에 전달해야하는 최후의 수단으로 만 사용해야합니다. 즉, 앱이 사용자가 할 수있는 모든 것을 할 수 있습니다

인증 코드 : 사용자 인증을 얻는 가장 좋은 방법

암시 적 : 앱이 모바일 또는 단일 페이지 앱인 경우

여기에 선택에 대한 자세한 설명이 있습니다 : https://blog.oauth.io/choose-oauth2-flow-grant-types-for-app/

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.