티스토리 뷰
출처 : http://devx.tistory.com/entry/OAuth-인증방식-이해하기
OAuth 인증방식 이해하기
본 문서는 OAuth의 이해를 돕기 위해 작성되었습니다.
OAuth 학습을 뛰어넘고 바로 예제 소스를 보며 개발을 하고 싶다면, 튜토리얼를 참고하시기 바랍니다.
본 문서 내의 용어 일관성을 위해 OAuth스팩에 있는 용어를 사용하였습니다. 본 문서에서 용어는 모두 이탤릭체로 표시됩니다.
용어정의
- 서비스 프로바이더(Service Provider) – API를 제공하는 서비스를 말합니다. 예> 스프링노트
- 사용자(users) - 서비스 프로바이더 혹은(그리고) 컨수머를 사용하는 이를 말합니다.
- 컨수머(Consumer) – API를 사용하여 개발된 애플리케이션 서비스를 말합니다. 예> 스프링노트의 API를 이용하여 개발된 매시업
- 보호된 자원(Protected Resources): 서비스 프로바이더에 존재하는 사용자의 데이터를 의미합니다. 예> 스프링노트의 페이지 혹은 첨부 데이터들
- 컨수머 개발자(Consumer Developer) : 컨수머를 개발하는 개인 혹은 단체
- 컨수머 키(Consumer Key) : 서비스 프로바이더에게 컨수머 자신임을 인증하기 위한 키
- 컨수머 시크릿(Consumer Secret) : 컨수머의 컨수머 키 소유권한이 있는지 인증하기 위한 키
-
토큰(Tokens) – 컨수머에서 서비스 프로바이더에 있는 사용자의 보호된 자원에 접근하기 위해 사용되는 사용자의 인증정보입니다. 예를들어 스프링노트의 API를 사용해 개발된 매시업 M이 스프링노트(서비스 프로바이더)에 있는 사용자 U의 보호된 데이터에 접근하기 위해서는 사용자 U의 인증정보(credential)가 필요합니다. 그 인증정보를 위해 사용되는 것이 토큰입니다.
- 리퀘스트 토큰(Request Token) : 컨수머가 사용자에게 접근권환을 획득하는 과정에서 사용하는 값이며, 이것은 차후 액세스 토큰으로 교환됩니다.
- 리퀘스트 토큰 시크릿(Request Token Secret) : 리퀘스트토큰이 사용자의 것임을 인증하기 위한 값입니다.
- 액세스 토큰(Access Token) : 컨수머가 사용자의 서비스 프로바이더를 통해서가 아닌 컨수머를 통해서 보호된 자원에 접근할 수 있는 권한을 받기 위한 값입니다.
- 액세스 토큰 시크릿(Access Token Secret) : 액세스토큰이 사용자의 것임을 인증하기 위한 값입니다.
용어를 숙지 하셨다면, 이해를 쉽게 하기 위해 두 가지 관점에서 인증과정을 살펴보겠습니다.
사용자 관점에서 바라보았을 때의 인증과정을 학습하셨다면, 개발을 하기 위해 OAuth프로토콜 관점에서 바라보았을 때의 OAuth 인증과정을 통해 좀 더 자세히 OAuth인증 과정 학습 및 개발을 할 수 있습니다.
사용자 관점에서 본 OAuth 인증과정
본 문서는 사용자 관점에서 본 OAuth 인증과정을 설명하며, OAuth 공식 홈페이지의 Getting Started Part-2 의 내용을 기반으로 작성되었습니다.
OAuth는 실제 예제로 잘 설명될 수 있습니다. OAuth 스펙에 있는 Appendix A와 유사한 예제이지만, 스펙에서는 HTTP 호출 문법에 초점을 맞춘 반면, 여기에서는 사용자, 컨수머, 그리고 서비스 프로바이더 의 관점에서 OAuth세션을 중심으로 설명합니다.
2주동안 스코트랜드의 여행을 마치고 돌아온 Jane은, 여행을 하며 찍은 사진들을 친구들과 공유하고 싶습니다. Jane은 여행 사진을 공유하기 위해 사진 공유사이트인 Faji를 사용 합니다. 그녀는 faji.com에 로그인하고 비공개로 설정한 두 장의 사진을 업로드 합니다.
OAuth에서 쓰이는 용어에 따르면 Jane은 사용자이고 Faji는 서비스 프로바이더입니다. Jane이 업로드한 2장의 사진은 보호된 데이터(Protected Resource)가 되겠죠.
그녀의 몇몇 친구들과 사진을 공유한 다음, Jane은 그녀의 할머니와도 사진을 공유하려 합니다. 희귀한 스코트랜드의 병 사진을 다른 사람들과 공유하고 싶지는 않지만, 할머니는 인터넷에 접속할 수 없기때문에 Jane은 그 사진을 인쇄해서 할머니에게 보내려 합니다. 이를 위해 Jane은 Beppa라는 온라인 인쇄 서비스를 사용하려 합니다.
OAuth에서 쓰이는 용어에 따르면 Beppa는 컨수머입니다. Jane이 사진을 비공개로 해 놓은 이상, Beppa가 그 사진을 인쇄하기 위해 사진을 얻기 위해서는 OAuth인증을 해야 합니다.
beppa.com에 방문한 Jane은 인쇄 명령을 내립니다. Beppa는 Faji를 포함한 많은 외부의 사진공유 사이트들에 잇는 사진들을 가져올 수 있는 기능을 지원합니다. Jane은 사진이 있는 곳의 서비스를 선택하고 continue버튼을 누릅니다.
Beppa가 Faji 사진을 가져올 수 있도록 지원하고자 한다면, Beppa 개발자는 Faji의 OAuth인증을 사용하는 API를 사용하기 위하여 Faji로부터 컨수머 키(Consumer Key)와 컨수머 시크릿(Consumer Secret)을 사전에 받아와야 합니다.
Jane이 continue버튼을 누른 후, 뒷단에서는 Beppa와 Faji 사이에 중요한 일들이 일어납니다. Beppa는 Faji에게 리퀘스트 토큰(Request Token)을 요청합니다. 리퀘스트 토큰(Request Token)은 사용자와는 전혀 상관이 없으며, Beppa가 Faji에 있는 Jane의 비공개 사진에 접근하는 것을 승인하기 위하여 사용될 뿐입니다.
Jane은 continue버튼을 누르고 화면이 바뀌길 기다립니다.
Beppa가 리퀘스트 토큰(Request Token)을 받으면, Faji의 OAuth 사용자 인증 URL로 방금 받은 리퀘스트 토큰(Request Token)과 함께 리다이렉트 시키고, Jane이 승인을 하면 http://beppa.com/order로 되돌아오게 할 것을 요청합니다.
Jane은 Faji로 리다이렉트되고 사이트에 로그인할 것을 요청받습니다. OAuth는 서비스 프로바이더가 먼저 사용자를 인증하고, 컨수머에게 접근권한을 줄 것인지 승인을 받습니다.
Jane은 브라우저에 있는 URL을 통해 그녀는 지금 Faji사이트에 있다는 것을 알게 되며, 아이디와 비밀번호를 입력합니다.
OAuth는 Jane이 그녀의 아이디와 비밀번호를 Beppa나 다른 사이트들이 공유하지 않게끔 해줍니다. Jane이 그녀의 faji에 대한 비밀정보(아이디,비밀번호)를 beppa.com에 입력하는 과정이 없기 때문이죠.
Faji에서 로그인에 성공하면, Jane은 Beppa에게 Faji에 접근할 수 있는 권한을 부여하기 위한 승인을 하게 됩니다. Faji는 Jane에게 누가 접근요청을 하는지(여기서는 Beppa가 되겠죠) 알려주며 승인을 할 것인지 묻습니다. Jane은 승낙하거나 거절할 수 있습니다.
Jane은 Beppa가 필요한 만큼만 제한적으로 접근할 수 있게 해줍니다. 그녀는 Beppa가 그녀의 사진을 수정하거나 다른 일들을 하는 것을 원하지 않습니다. 또한, Beppa가 Faji에 있는 그녀의 사진을 가져오는데는 1시간이면 충분하다는 것을 알고 있습니다.
Jane이 요청을 승낙하면 Faji는 리퀘스트 토큰(Request Token)을 Jane으로부터 "사용자 승인이 된" 토큰으로 표시합니다. Jane의 브라우저는 리퀘스트 토큰(Request Token)과 함께 보내온 http://beppa.com/order 주소로 리다이렉트 시킵니다. 이는 Beppa가 Jane의 사진을 가져오는 작업을 계속 할 수 있다는 것을 알려주는 것입니다.
Jane은 Beppa가 Faji 계정으로부터 사진을 가져오는 것을 기다립니다.
Jane이 기다리는 동안, Beppa는 인증된 리퀘스트 토큰(Request Toekn)과 액세스 토큰(Access Token)을 교환홥니다. 리퀘스트 토큰(Request Token)은 사용자의 승인을 얻어내기 위해 사용될 뿐이며, 액세스 토큰(Access Token)은 보호된 자원(Protected Resource : 여기에서는 Jane의 사진이 되겠죠)에 접근하기 위해 사용됩니다. 첫 번째 요청에서, Beppa는 리퀘스트 토큰(Request Token)을 액세스 토큰(Access Token)으로 바꾸고, 두 번째로 사진을 요청(여러번 요청이 될 수 있겠죠. 한번은 사진의 리스트를, 다른한번은 각 사진을 가지고 오는 등...)합니다.
Beppa가 작업을 마치면 Jane의 브라우저는 작업을 다 마쳤음을 보여주는 화면으로 바뀝니다.
Beppa는 성공적으로 Jane의 사진을 가져왔습니다. 그녀의 사진을 선택할 수 있도록 썸네일로 보여줍니다.
Jane은 Beppa가 그녀의 아이디와 비밀번호를 모르는데도 불구하고 그녀의 사진을 가져왓다는 것에 놀랍니다. 그녀는 화면에서 시키는데로 인쇄요청을 합니다.
여기까지 사용자 관점에서 본 OAuth 인증과정을 살펴보았습니다. 이제 이러한 인증과정에 맞춘 컨수머 개발을 하기 위해서 OAuth프로토콜 관점에서본 OAuth인증 과정을 살표보시기 바랍니다.
OAuth프로토콜 관점에서 본 OAuth 인증과정
본 문서는 OAuth프로토콜 관점에서 본 OAuth 인증과정을 설명하며, OAuth 스팩의 Appendix A - Protocol Example의 내용을 기반으로 작성되었습니다.
각 과정은 아래에 나온 순서도에 기반하여 이루어지기 때문에 그림과 함께 보면 이해하는데 도움이 될 것입니다.
* 이 사진에 나오는 A,B,C.. 단계는 아래의 단계와 관련이 없습니다.
A. 프로토콜 예제
본 예제에서 서비스 프로바이더인 photos.example.net 는 사진 공유 사이트이며, 컨수머인 printer.example.com은 사진 출력 사이트입니다. Jane은 사용자이며 photos.example.com에 저장되어 있는 비공개 사진인 vacation.jpg를 출력하기 위하여 printer.example.com 서비스를 사용할 것입니다.
Jane이 그녀의 아이디와 비밀번호를 입력하여 photos.example.net 에 로그인하면, 그녀는 http://photos.example.net/photo?file=vacation.jpg URL을 통해 그녀의 사진에 접근할 것입니다. 다른 사용자들은 그 사진에 접근할 수 없으며, Jane은 그녀의 아이디와 비밀번호를 printer.example.com에 공유하고 싶지 않습니다.
이 예제에서 파라미터를 전송할 때 사용하는 요청은 URL 쿼리 메소드를 사용합니다. 이는 단순한 예제를 위해 사용되며 한개의 메소드가 다른 용도로 사용되어서는 안됩니다.
A.1. 문서화와 등록
서비스 프로바이더의 문서에서는 컨수머 키와 컨수머 시크릿을 등록하는 방법을 설명하며, 다음과 같은 URL들을 선언해 주어야 합니다.
- Request Token URL:
- https://photos.example.net/request_token, HTTP POST 사용
- User Authorization URL:
- http://photos.example.net/authorize, HTTP GET 사용
- Access Token URL:
- https://photos.example.net/access_token, HTTP POST 사용
- Photo (Protected Resource) URL:
- http://photos.example.net/photo , file파라미터와 size파라미터(선택적)와 함께 전송
서비스 프로바이더는 모든 요청에 대하여 HMAC-SHA1 시그네쳐를 지원하며, 보안(HTTPS)요청일 경우에만 PLAINTEXT을 사용할 수 있음을 말해줍니다.
컨수머인 printer.example.com은 이미 컨수머 키와 컨수머 시크릿을 photos.example.net으로 부터 부여 받았으며, 출력할 사진은 photos.example.net에 저장되어 있음을 명시합니다. 컨수머 등록을 하면 다음과 같은 값들을 부여받습니다:
- Consumer Key:
- dpf43f3p2l4k3l03
- Consumer Secret:
- kd94hf93k423kf44
A.2. 리퀘스트 토큰 얻기
Jane이 printer.example.com에게 photos.example.net에 저장되어 있는 그녀의 휴가사진을 출력할 것임을 알려주면, 출력 웹사이트는 사진에 접근을 시도할 것이며, 그 사진은 비공개이기 때문에 HTTP 401 Unauthorized 메시지를 받습니다. 서비스 프로바이더는 응답과 함께 다음과 같은 헤더를 포함합니다:
WWW-Authenticate: OAuth realm="http://photos.example.net/"
컨수머는 서비스 프로바이더에게 다음과 같은 HTTP POST를 보내야 합니다.
https://photos.example.net/request_token?oauth_consumer_key=dpf43f3p2l4k3l03&oauth_signature_method=PLAINTEXT&oauth_signature=kd94hf93k423kf44%26&oauth_timestamp=1191242090&oauth_nonce=hsu94j3884jdopsl&oauth_version=1.0
서비스 프로바이더는 signature를 검사하고, HTTP 응답의 body에 인증되지 않은 리퀘스트 토큰과 함께 응답합니다.
oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03
A.3. 사용자 인증 요청하기
컨수머는 Jane의 비공개 사진으로 접근을 승인을 얻기 위하여 브라우저를 서비스 프로바이더의 Authoirization URL로 리다이렉트 시킵니다.
http://photos.example.net/authorize?oauth_token=hh5s93j4hdidpola&oauth_callback=http%3A%2F%2Fprinter.example.com%2Frequest_token_ready
서비스 프로바이더는 Jane이 그녀의 아이디와 비밀번호를 사용해 로그인 할 것을 요청하고, 성공적으로 로그인을 했으면, printer.example.com이 그녀의 비공개 사진에 접근할 권한을 줄 것인지 묻습니다. Jane이 요청을 승인하면, 서비스 프로바이더는 컨수머의 callback URL로 리다이렉트 시킵니다:
http://printer.example.com/request_token_ready?oauth_token=hh5s93j4hdidpola
A.4. 액세스 토큰 얻기
이제 컨수머는 Jane이 승인한 리퀘스트 토큰을 알고 있으며, 서비스 프로바이더에게 그것을 액세스 토큰으로 교환해 줄 것을 요청합니다:
https://photos.example.net/access_token?oauth_consumer_key=dpf43f3p2l4k3l03&oauth_token=hh5s93j4hdidpola&oauth_signature_method=PLAINTEXT&oauth_signature=kd94hf93k423kf44%26hdhd0244k9j7ao03&oauth_timestamp=1191242092&oauth_nonce=dji430splmx33448&oauth_version=1.0
서비스 프로바이더는 시그네쳐를 검사하고 HTTP 응답의 바디에 액세스 토큰을 넘겨줍니다:
oauth_token=nnch734d00sl2jdk&oauth_token_secret=pfkkdhi9sl3r4s00
A.5. 보호된 자원에 접근하기
컨수머는 이제 비공개 사진을 요청할 준비가 되었습니다. 사진 URL이 HTTPS가 아니라면, 반드시 HMAC-SHA1을 사용해야 합니다.
A.5.1. Signature Base String 생성하기
signature를 생성하기 위해, Signature Base String을 생성해야 합니다. 요청은 다음과 같은 파라미터들(oauth_signature를 제외한)을 순서대로 노멀라이즈된 문자열로 연결한 것을 포함해야 합니다.
- oauth_consumer_key:
- dpf43f3p2l4k3l03
- oauth_token:
- nnch734d00sl2jdk
- oauth_signature_method:
- HMAC-SHA1
- oauth_timestamp:
- 1191242096
- oauth_nonce:
- kllo9940pd9333jh
- oauth_version:
- 1.0
- file:
- vacation.jpg
- size:
- original
다음과 같은 것들이 Signatrue Base String을 생성하기 위해 사용됩니다.
- GET
- http://photos.example.net/photos
- file=vacation.jpg&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=kllo9940pd9333jh&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1191242096&oauth_token=nnch734d00sl2jdk&oauth_version=1.0&size=original
Signature Base String 은 다음과 같습니다:
GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal
A.5.2. Signature 값 암호화 하기
HMAC-SHA1은 Signature Base String을 text로, kd94hf93k423kf44&pfkkdhi9sl3r4s00(컨수머 시크릿&액세스토큰시크릿)를 key로 사용하여 base64-encoding된 문자열로 변환된 값을 만들어 냅니다:
tR3+Ty81lMeYAr/Fid0kMTYa/WM=
A.5.3. 보호된 자원 요청하기
사진을 요청하기 위한 컨수머의 요청내용을 정리해 보면 :
http://photos.example.net/photos?file=vacation.jpg&size=original
Authorization: OAuth realm="http://photos.example.net/",
oauth_consumer_key="dpf43f3p2l4k3l03",
oauth_token="nnch734d00sl2jdk",
oauth_signature_method="HMAC-SHA1",
oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D",
oauth_timestamp="1191242096",
oauth_nonce="kllo9940pd9333jh",
oauth_version="1.0"
쿼리 파라미터를 사용한다면:
http://photos.example.net/photos?file=vacation.jpg&size=original&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_token=nnch734d00sl2jdk&oauth_signature_method=HMAC-SHA1&oauth_signature=tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D&oauth_timestamp=1191242096&oauth_nonce=kllo9940pd9333jh&oauth_version=1.0
photos.example.net은 signature를 검사하고 나서 요청한 사진을 응답으로 돌려줄 것입니다.
여기까지 OAuth프로토콜 관점에서 본 OAuth인증 과정을 살펴보았습니다. 이제 OAuth의 이해를 바탕으로 실제 컨수머 개발을 위해 튜토리얼을 참고하시기 바랍니다.
- Total
- Today
- Yesterday
- 타루 예뻐할께
- dom vs sax
- MySQL
- 문자열자르기
- 스크린세이버
- marry you 프로포즈
- Split
- java 객체
- 자바 객체
- 갈릴레오 svn
- bruno mars marry you
- 자바정의
- javascript강의
- java파일삭제
- 체크박스
- eclipse svn
- Marry You
- 자바스크립트강의
- 불독맨션 좋아요
- Mysql명령어
- java 인스턴스
- lol 서포터
- jason marz im yours
- java파일복사
- 이클립스 단축키
- sax vs dom
- This Android SDK requires An...e ADT to the latest version
- eclipse 단축키
- jason maraz
- 펌방지해제
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |