OAuth와 파일 업로드 - 서명된 요청의 진실
October 6th, 2008
모든 OAuth 요청은 컨슈머가 만든 서명을 포함해야하고, 서비스 프로바이더는 정해진 약속에 따라 서명을 검증한다.
OAuth 요청에는 자신이 사용한 oauth_signature_method와 그 결과인 oauth_signature를 파라메터가 포함되어야 한다. 그러면 서버에서는 요청이 적절한 signature를 담고 있는지 확인하고, 그렇지 않다면 적절히 무시한다.
여기서 가장 중요한 점은 Signature를 생성하는 일관된 규칙이다. 이 규칙이 잘 설명되지 않았던 초기에는 파일 업로드, XML 요청 등이 OAuth로 처리하기에 까다로운 부분으로 여겨졌다. 1.0 최종 스펙을 보며 이 규칙을 조금 정리해보자.
Signature
signature는 signature base string에 signature method(ex. HMAC-SHA1)를 적용한 값이다.
- oauth_signature = oauth_signature_method(signature_base_string)
signature method는 어느 플랫폼이나 동일하므로, 중요한 점은 Signature Base String을 생성하는 방법이다.
Signature Base String (SBS)
SBS를 만들때는 아래 3가지 요소를 각각 퍼센트 인코딩한 다음 &로 묶어준다.
-
Method
- 대문자로 GET, POST 등
-
URL
- 정규화하고 query는 제외한다.
- 포트를 생략할 수 있으면 생략한다
-
Parameter
-
아래 파라메터를 모아 정렬한 다음 하나의 문자열로 연결한다
- HTTP Authorization Header - realm 제외
- URL의 query 부분
- POST 요청의 본문. 단, 요청 형식이 application/x-www-form-urlencoded인 경우만
-
그렇다면 파일 업로드는?
Signature Base String을 만들때 multipart/form-data로 이뤄진 POST 본문은 포함하지 않는다. 따라서 문제없이 처리할 수 있다.
XML을 담은 요청은?
예를 들어 액티브리소스에서 POST를 하면 요청 형식은 application/xml이고, POST 본문에 리소스를 표현하는 XML이 들어간다. 이 경우도 SBS를 만들때 POST 본문이 포함되지 않아야 한다는 사실에만 주의하면 큰 문제는 없다.
_method 트릭
특정 환경(ex. 브라우저)은 PUT, DELETE 요청을 활용하지 못하지만, REST 스타일에서는 이런 메서드은를 의미있게 사용하고 있다. 이 때 메서드의 한계를 피해갈 수 있는 방법으로 _method를 사용하고 있다. POST 요청을 하면서 _method 파라메터에 put을 담으면 서버에서는 부디 PUT 요청으로 봐달라는 것이다. 레일스에서 특히 잘 쓰고 있는 트릭이다.
그런데 이 경우 SBS를 이루는 Method를 뭘로 해야할까?
- 컨슈머는 POST 요청인가? _method에 담긴 PUT 요청인가
- 프로바이더는 이걸 POST 요청으로 봐야하나 PUT 요청으로 봐야하나.
스프링노트는 REST API를 존중한다는 의미에서 컨슈머, 프로바이더 모두 PUT 요청(서버에서 인식하는 요청)으로 보도록 하고 있다. 예를 들어 DELETE 메서드를 사용할 수 없는 환경에서 특정 페이지를 지우고 싶을 때는 POST와 _method=delete 파라메터를 사용할텐데 SBS를 만들때는 method를 POST가 아닌 DELETE로 넣어주기를 바란다는 것이다. 논란의 여지는 있는 것 같다.
이 글을 쓰는 이유는?
글을 마치는 시점에 글의 동기가 나온다니 좀 이상하지만.. 그래도 이 글의 계기가 있으니 소개한다.
- http://github.com/pelle/oauth/commit/5cabd84b3c712cd3f615af174f127a47d7010561 - Fixed behavior where POST params in the request body were being included in the SBS even when not encoded as application/x-www-form-urlencoded.
ruby-oauth 라이브러리의 최근 버전에서야 SBS를 만드는 방법을 잘 지키게 되었기 때문이다. 그 전에는 파일 업로드를 하는 것, XML 요청을 보내는 것 모두 제약이 있었다. 한참을 뜯어보며 드디어 patch를 만들었는데, 리포트하려고 gem update를 해 최신버전을 내려받으니 비슷한 코드가 이미 들어있어 좀 황당했다. ^^
최근 humbroll님이 iPhone 환경에서 OAuth 인증을 하느라 꽤 많은 고생을 했다. 곧 고생담을 들을 수 있기를 기대해본다. (updated: 고생담은 여기)
끝으로
OAuth 인증을 지원하는 오픈 API를 사용하는 일이 쉽지않다. 특히나 요청 사이닝때문에 더 어려울 수 있다. 되도록 OAuth 요청을 직접 만들지 말고, 미리 만들어진 라이브러리의 최신 버전을 사용하는 편이 장수할 수 있는 비결이다. 그리고 프로바이더에서는 구글처럼 적절한 디버깅 도구를 제공해야하면 좋겠다.
참고자료




October 1st, 2008 at 02:54 PM 이번 건은 블로그 포스팅 해야겠어요. ㅎㅎ 도와주셔서 감사합니다.
October 1st, 2008 at 05:21 PM 험브롤// 포스팅 기대할께요