OAuth 인증
이 것은 OAuth 1.0 spec 을 기반으로 정리한 내용입니다.
스토리큐는 open api 를 지원하면서 사용자 인증을 위해 OAuth를 사용하고 있습니다.
openmaru팀이 제공하고 있는 OAuth 인증방식 이해하기 를 참조하셔도 매우 좋은 설명을 얻을 수 있습니다.
3. 용어 설명
서비스 제공자(Service Provider) : OAuth를 통해 Open API를 제공하는 웹 애플리케이션. 예를 들면 StoryQ
사용자(User) : Service Provider에 계정을 가지고 있는 개인
컨슈머(Consumer) : Service Provider의 Open API를 이용하는 웹사이트 혹은 애플리케이션
보호된 자원(Protected Resources) : 인증과정을 통해서 Consumer가 접근할 수 있는 Service Provider에게 있는 자원, 예를 들면 스토리큐의 한 슬라이드 큐
컨슈머 개발자(Consumer Developer) : Consumer를 개발하는 프로그래머
컨슈머 키(Consumer Key) : Service Provider가 Consumer를 확인할 수 있는 값.
컨슈머 비밀번호(Consumer Secret) : Consumer를 증명하기 위한 비밀번호
요청 토큰(Request Token) : 사용자로부터 위임 권한(Authorization)을 얻기 위해 Consumer가 사용하는 토큰, Access Token으로 교환된다.
접근 토근(Access Token) : 사용자의 보호된 자원에 접근하기 위해 Consumer가 사용하는 값
OAuth Protocol Parameters : 'oauth_'로 시작되는 OAuth 관련 파라미터들
4. 문서화와 등록
OAuth는 컨슈머와 사용자를 인증하기 위해 컨슈머 키와 컨슈머 비밀번호를 포함한다. 이렇게 컨슈머를 확인함으로써 서비스 제공자는 컨슈머들에게 접근 조절(Access Control)을 할 수 있다.
서비스 제공자는 컨슈머 키와 비밀번호가 노출될 염려가 있는 경우에는 키와 비밀번호만으로 컨슈머를 100% 확신해서는 안된다. 컨슈머 비밀번호는 비어 있을 수도 있다.(예를들어 컨슈머 확인이 필요없는 경우, 컨슈머 확인을 RSA같은 다른 방법으로 할 수 있는 경우)
4.1 요청 URL(Request URLs)
OAuth는 다음 세개의 URL들을 정의한다.
- Request Token URL
=> 인증되지 않은 요청 토큰(Request Token)을 얻기 위한 URL. 6.1 참조 - User Authorization URL
=> 컨슈머의 접근을 허가하기 위한 사용자 인증을 얻기 위한 URL, 6.2 참조 - Access Token URL
=> 사용자 읹증된 요청 토큰을 접근 토큰(Access Token)으로 교환해 줄 것을 요청하는 URL, 6.3 참조.
4.2 서비스 제공자(Service Providers)
서비스 제공자는 다음과 같은 것을 공지해야 한다.
- Oauth URL ( Request Token URL, User Authorization URL, Access Token URL), HTTP methods
- 서비스 제공자가 제공하는 서명 방법(Signatuer Method)
- 서비스 제공자가 토큰을 얻기 위해 필요한 추가적인 파라미터들. 이 파라미터들은 'oauth_' 로 시작해서는 안된다.
4.3 컨슈머(Consumer)
컨슈머 개발자는 컨슈머 키와 비밀번호로를 서비스 제공자에게 제공해야 한다.
5. 파라미터
OAuth 프로토콜 파라미터는 대문자를 구분한다. 모든 OAuth 프로토콜 파라미터들은 특별한 언급이 없는한 필수이며, 한 요청에 한 번 이상 있어서는 안된다.
5.1. 파라미터 인코딩
모든 파라미터 이름과 값들은 [RFC3986] 의 percent-encoding(%xx) 방법에 의해서 이스케이프(escaped)된다. Unreserved 문자 집합 밖의 문자 ([RFC3986]section 2.3)들은 인코딩 되어야만 한다. Unreserved 문자집합 안의 문자들은 인코딩되어서는 안된다. 16진법의 문자들은 대문자여야 한다. 텍스트(text) 이름과 값들은 percent-encoding이전에 UTF-8로 인코딩([RFC3629]) 되어야 한다.
- unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
5.2. 컨슈머 요청 파라미터
OAuth 프로토콜 파라미터들은 컨슈머로부터 서비스제공자에게 다음 세가지 중 하나의 방법으로 전송된다. 상위의 방법이 더 선호된다.
- HTTP Authorization 헤더 안에 포함한다.( 5.4 OAuth HTTP Authorization Scheme을 이용)
- HTTP POST 요청의 body 에 포함한다. (content-type = application/x-www-form-urlencoded 로 한다.)
- URL의 쿼리부분에 포함한다.([RFC3986])
5.3. 서비스 제공자의 응답 파라미터
서비스 제공자는 컨슈메에게 토큰이나 다른 정보를 응답할 때, HTTP body를 이용한다. 파라미터 이름과 값들은 파라미터 인코딩(5.1 참조) 에 의하 먼저 인코딩되고, '&'를 이용해 합쳐진다.(일반적인 방법이군.)
예를 들면,
- oauth_token=ab3cd9j4ks73hf7g&oauth_token_secret=xyz4992k83j47x0b
5.4. OAuth HTTP 인증 설계(Scheme)
OAuth 프로토콜 파라미터들을 전하기 위해 표준 HTTP Authorization과 WWW-Authenticate 헤더를 이용한다.
서비스 제공자가 HTTP Authorization 헤더를 수락하기를 권한다. 컨슈머는 OAuth 프로토콜 파라미터들을 OAuth Authorization 헤더에 넣어 보낼 수 있어야 한다.
5.4.1 Authorization 헤더를 이용할 때
OAuth 프로토콜 파라미터들은 다음과같은 방법으로 Authorization 헤더에 담겨져 보내진다.
- 파라미터 이름과 값들은 파라미터 인코딩(5.1 참조)에 의해 인코딩된다.
- 각각의 파라미터는 NAME="VALUE" 형식이다.
- 파라미터들은 ", " 에 의해 분리된다.
- realm 파라미터가 추가될 수 있고(optional) [RFC2617] 에 의해 해석된다.
예를 들면 :
- Authorization: OAuth realm="http://sp.example.com/",
oauth_consumer_key="0685bd9184jfhq22",
oauth_token="ad180jjd733klru7",
oauth_signature_method="HMAC-SHA1",
oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
oauth_timestamp="137131200",
oauth_nonce="4572616e48616d6d65724c61686176",
oauth_version="1.0"
5.4.2 WWW-Authenticate 헤더
뭔소린지.. 당췌..
6. OAuth를 이용해서 인증하기
OAuth 인증은 사용자가 비밀번호(credential)를 공유함 없이 컨슈머에게 보호된 자원에 접근을 허가하는 과정이다. OAuth는 사용자의 비밀번호(credential) 대신 서비스 제공자에 의해 생성되는 토큰을 사용한다. 인증과정은 두 가지 종류의 토큰을 사용해서 진행된다.
요청 토큰(Request Token) :
- 사용자의 보호된 자원에 접근을 위해서 컨슈머는 사용자의 권한 위임이 필요한데, 권한 위임을 얻기 위한 과정에서 사용된다.
- 사용자의 인증을 마친 요청토큰(Request Token)은 접근토큰(Access Token)으로 교환된다.
- 한번만 사용되어야 하고, 위 용도가 아닌 다른 용도로 사용되면 안된다.
- 만료시간을 가지고 있는 것이 좋다.
접근 토큰(Access Token) :
- 컨슈머가 사용자의 보호된 자원에 접근하기 위해 사용된다.
- 만료시간을 가질 수 있고, 접근 정도에 차이가 있을 수 있다.(예를 들어 한시간만, 레벨 1 수준의 자원만 허가)
- Service Provider는 사용자가 이 Token을 파기할 수 있도록 해 주어야 한다.(should)
- Access Token은 보호된 자원에 접근하는 목적으로만 사용되어야 한다.(must)
OAuth 인증은 다음 세 단계에 의해 이루어진다.
- 컨슈머가 인증이 안된 요청토큰을 획득한다.
- 사용자는 요청토큰을 인증한다.
- 컨슈머는 인증토큰을 접근 토큰으로 교환한다.

다음부터는 인증 과정에 대해 자세히 설명한다.( 위 그림의 내용이다.)
6.1. 컨슈머가 인증이 안된 요청토큰을 획득한다.
컨슈머는 서비스 제공자에게 토큰을 발행해줄 것을 요청해서 인증이 안된 요청토큰을 획득한다. 요청 토큰을 단 한가지 목적은 사용자의 승인을 얻은 후 접근 토큰으로 교환되는 것이다. 요청토큰을 얻는 과정은 다음과 같다.
6.1.1. 컨슈머가 요청토큰을 요청한다.
- 컨슈머는 서비스 제공자의 요청토큰 URL(Request Token URL)에 요청토큰을 달라는 HTTP 요청을 한다.
- HTTP POST를 사용할 것을 권장한다.
- 요청은 서명되어(signed) 있어야 한다.(서명에 대해서는 아래 9. 서명하기를 참조)
-
다음과 같은 파라미터들을 가지고 있어야 한다. 이 파라미터들은 Authorization Header 에 포함되기를 권장한다.
- oauth_cosumer_key : 컨슈머 키
- oauth_signature_method : 컨슈머가 요청에 사용한 서명 방법
- oauth_signature : 서명, 9. 서명하기를 참조
- oauth_timestamp : 아래 8. timestamp를 참조
- oauth_nonce : 아래 8. nonce를 참조
- oauth_version : 1.0
- 추가적인 파라미터들
6.1.2. 서비스 제공자는 인증이 안된 요청토큰을 발급한다.
- 서비스 제공자는 서명과 컨슈머 키를 확인한다.
- 서명에 문제가 없으면, 서비스 제공자는 요청토큰과 토큰 비밀번호(Token Secret)을 생성해서 컨슈머에게 리턴한다.
- 응답은 HTTP body를 이용한다.(5.3.서비스 제공자의 응답 파라미터 참조)
- 응답에 포함되는 내용은 다음과 같다.
- oauth_token : 요청 토큰 키
- oauth_token_secret : 요청 토큰 비밀번호
- 추가적인 파라미터들
6.2. 사용자의 인증을 획득하기
컨슈머는 사용자가 요청토큰의 인증을 해줄 때까지 요청토큰을 사용할 수 없다. 사용자 인증은 다음과 같은 과정을 거친다.
6.2.1. 컨슈머는 인증을 위해 사용자를 서비스 제공자쪽으로 보낸다.(redirect)
- 컨슈머가 요청토큰을 접근 토큰으로 교환하기 위해서는 요청토큰에 사용자의 승인을 얻어야 한다. 그러기 위해서 컨슈머는 사용자를 서비스 제공자의 인증 URL(Authorize URL)로 보낸다.
- 컨슈머가 인증 URL로 리다이렉트를 할 수 없는 경우에는 사용자에게 인증을 위해 Authorize URL로 접속할 것을 알려준다.
- Authorize URL의 예
- http://www.storyq.net/oauth/authorize?oauth_token=IBj0dAl57LnuWfiRKitNw
-
인증 URL로의 요청은 다음과 같은 파라미터들를 포함한다.(GET 요청 파라미터로)
- oauth_token : 인증 안된 요청토큰
- oauth_callback : 인증을 마친 후 되돌아갈 URL, 없을 수도 있다.
- 추가적인 파라미터들
6.2.2. 서비스 제공자는 사용자를 확인하고, 사용자가 컨슈머를 사용할 것에 대한 동의를 받는다.
-
OAuth는 어떻게 서비스 제공자가 사용자를 인증해야 되는지에 대해서는 세세히 설명하지 않는다. 다만 다음과 같은 과정을 거쳐야 한다.
- 서비스 제공자는 컨슈머 사용 동의를 얻기전에 사용자의 신분을 확인한다. 필요한 경우 회원가입을 하도록 할 수도 있다.
- 서비스 제공자는 사용자에게 컨슈머에 대한 적절한 정보를 보여준다. 이 정보는 보호된 자원에 접근 가능한 기간을 포함한다.
- 사용자는 서비스제공자에게 컨슈머가 보호된 자원을 사용할 것을 허가하거나 거부할 수 있다. 만약 사용자가 거부한다면, 서비스 제공자는 보호된 자원으로의 접근을 허가해서는 안된다.
6.2.3. 서비스 제공자는 사용자를 컨슈머에게 돌려 보낸다.
- 사용자의 동의를 얻은 후 서비스 제공자는 사용자를 callback URL로 리다이렉트 시켜서 컨슈머에게 사용자의 인증이 끝났음을 알려준다.
- 컨슈머가 oauth_callback 으로 callback URL을 제공한 경우에는 서비스 제공자는 callback URL로 HTTP GET 요청을 만들어 리다이렉트 시킨다.
-
callbak URL 요청은 다음과 같은 파라미터를 포함한다.
-
oauth_token : 사용자가 승인(혹은 거부)을 거친 요청토큰
-
- 서비스 제공자는 컨슈머에 의해 제공된 callback URL(oauth_callback)을 수정해서는 안되며, 그 뒤에 oauth_token 파라미터만 추가한다.
- callback URL이 없는 경우에는 사용자에게 인증이 끝났으며, consumer로 돌아가 계속 진행할 것을 공지한다.
6.3. 접근토큰 획득하기
접근토큰을 얻는 과정은 다음과 같다.
6.3.1. 컨슈머가 접근토큰을 요청한다.
- 컨슈머는 서비스 제공자가 제공하는 접근토큰 URL에 교환 요청을 한다.
- HTTP POST를 사용할 것을 권장한다.
- 요청은 서명되어(signed) 있어야 한다. (서명에 대해서는 아래 9. 서명하기를 참조)
-
다음과 같은 파라미터들을 가지고 있어야 한다. 이 파라미터들은 Authorization Header 에 포함되기를 권장한다.
- oauth_cosumer_key : 컨슈머 키
- oauth_token : 인증된 요청토큰
- oauth_signature_method : 컨슈머가 요청에 사용한 서명 방법
- oauth_signature : 서명, 9. 서명하기를 참조
- oauth_timestamp : 아래 timestamp를 참조
- oauth_nonce : 아래 nonce를 참조
- oauth_version : 1.0
6.3.2. 서비스 제공자는 접근토큰을 발급한다.
-
서비스 제공자는 다음을 꼭 확인해야 한다.
- 서명이 맞는지
- 요청토큰이 처음으로 사용되고 있는지
- 요청토큰이 컨슈머 키와 맞는지.
- 맞다면, 서비스 제공자는 접근 토큰과 비밀번호를 생성해서 HTTP body에 넣어서 응답한다. (5.3.서비스 제공자의 응답 파라미터 참조)
-
응답에는 다음과 같은 파라미터들이 포함된다.
- oauth_token : 접근 토큰
- oauth_token_secret : 토큰 비밀번호
- 추가적인 파라미터들
- 접근 토큰과 비밀번호는 컨슈머에의해 저장되어서 보호된자원의 접근을 위한 서면에 사용되어진다.
- 요청이 실패하는 경우 Service Provider는 적절한 HTTP Respond Code로 응답을 한다.(should) 그리고 왜 실패했는지에 대한 설명을 HTTP Response body에 추가할 수 있다.
7. 보호된 자원에 접근하기
- 접근토큰을 발급받은 후 컨슈머는 사용자의 보호된 자원에 접근할 수 있다.
- 요청은 서명되어(signed) 있어야 한다.
-
다음과 같은 파라미터들을 가지고 있어야 한다. 이 파라미터들은 Authorization Header 에 포함되기를 권장한다.
- oauth_cosumer_key : 컨슈머 키
- oauth_token : 접근 토큰
- oauth_signature_method : 컨슈머가 요청에 사용한 서명 방법
- oauth_signature : 서명, 9. 서명하기를 참조
- oauth_timestamp : 아래 timestamp를 참조
- oauth_nonce : 아래 nonce를 참조
- oauth_version : 1.0
- 추가적인 파라미터
8.1 Timestamp
- 1970년 1월 1일 0시 0분 0초 GMT 부터의 초
- 양수이어야 하며, 전에 사용된 timestamp 보다 커야한다.
8.2 nounce
- 매 요청마다 randon string으로 생성
- reply attack을 막기 위해, 요청이 유일함을 보장하기 위해서 사용된다.
9, 서명하기(HMAC-SHA1을 이용)
- 모든 토큰요청과 보호된 자원에 대한 요청은 컨슈머에 의해 서명되어져야 한고 서비스 제공자가 확인해야 한다.
- 서명을 하는 이유는 믿음직스럽지 못한 녀석들이 컨슈머 키와 토큰을 사용하는 것을 방지하기 위함이다.
- 서명은 컨슈머 비밀번호와 토큰 비밀번호를 사용한다.
- 서명의 방법은 HMAC-SHA1, RSA-SHA1, PLAINTEXT(HTTPS를 사용)이 있다 (스토리큐는 HMAC-SHA1 방식만 지원한다.)
- 서명의 방법은 oauth_signature_method 파라미터에 적어 준다.
- 서명의 내용은 oauth_signature 파라미터에 적어준다.
- 서비스 제공자는 서명을 확인하고, nonce가 처음으로 사용되는 것인지 검사해야 한다.
9.1 서명 기반 문자열(Signature Bse String)
- Request 의 구성요소로부터 만들어진다. 즉, 같은 Request는 같은 Signature Base String을 만든다.
- 이 문자열은 서명 알고리즘 혹은 해싱의 입력값으로 사용된다.
- 모든 요청 파라미터들은 서명 기반 문자열을 만들기에 앞서 파라미터 인코딩(5.1)에 의해 인코딩되어 있어야 한다.
Signature Base Stging 만들기
- 형식은 다음과 같다.
HTTP Request Method&Request URL&파라미터 문자열 -
파라미터 문자열
- 파라미터들은 이름 순으로 정렬한다. 이름이 같으면 값 순서로 정렬한다.
-
포함되는 파라미터들은 다음과 같다.
- OAuth 파라미터들( HTTP Authorization HEADER에 포함되어 있는) : realm 과 oauth_signature는 제외된다.
- HTTP POST에 포함되어 있는 파라미터들(content-type 이 application/x-www-form-urlencoded 인 경우)
=> content-type이 multipart인 경우는 파라미터에 포함되지 않는다. 예를 들어, 스토리큐의 파일 업로드 요청은 content-type이 multipart 이거나 application/octec-stream이기 때문에 파라미터에 포함되지 않는다. - HTTP GET 요청의 URL query 부분
- 정렬된 파라미터들을 'NAME=VALUE&NAME=VALUE...' 이런 형식으로 합쳐서 한 문자열을 만든다.
-
Request URL
- query 부분(?와 그 뒷부분)은 제외한 URL 부분.
- 모두 소문자로 변경한다.
- 예를 들면 http://www.storyq.net/boxes.xml
-
HTTP request method
- POST, GET, PUT, DELETE
예를 들면 다음과 같다.
- POST&http%3A%2F%2Fwww.storyq.net%2Fslide_boxes.xml&oauth_consumer_key%3Dzca6j7uX18d8TIlM0gOOQ%26oauth_nonce%3Dh8IYMaqJlfczhVDjeQC4g5H46sx9agCmtOYrgkWgRU%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1212403314%26oauth_token%3DkaX8Vhl5Gq3YKAKiYsSGg%26oauth_version%3D1.0
9.2. HMAC-SHA1
-
HMAC-SHA1 서명방법은 [RFC2104] 에 정의된 HMAC-SHA1 서명 알고리즘을 사용한다.
- text는 서명기반 문자열이다.
- key는 컨슈머 비밀번호(Consumer Secret)과 토큰 비밀번호(Token Secret)를 "&"로 연결한 값이된다.
예) ConsumerSecret&TokenSecret
kLs1KsFJp9F5l7kEuF2HKRWe8Y14eGLZZxFELFRg&QqrM4Yl6IHhJE6HnDELvYhWn7XGHjkgcLbr08mLaH8
9.2.1 서명을 생성하기
- oauth_signature 에는 HMAC-SHA1 서명 알고리즘의 결과를 base64-encoding 을 한 후 다시 URL-encoding해서 넣는다.
9.2.2. 서명한 값을 확인
서비스 제공자는 요청을 기반으로 서명 기반 문자열(Signature Base String) 를 만들고, 또 자신이 저장하고 있는 컨슈머 비밀번호과 토큰 비밀번호를 이용해서 서명(signature)를 만든다.
이 서명 를 파라미터로 받은 oauth_signature 의 값과 비교해서 올바른 요청인지 검증한다.
9.3 RSA-SHA1
은 생략
10. HTTP response codes(Token Request 에 대해서)
-
HTTP 400 Bad Request
- 모르는 파라미터
- 모르는 signature method
- 필수 파라미터 없음
- oauth 파라미터가 중복
-
HTTP 401 Unauthorized
- Consumer Key가 잘못됨
- Token이 만료되었음
- Signature가 맞지 않음
- nonce가 이미 사용되었음.
History
Last edited on 08/28/2008 19:35 by 창
Comments (0)