http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iii-security-architecture/
내가 보기 위하여 번역을 해 두었지만 다른 분들도 같이 보면 좋을것 같아서 블로그에 올립니다.
잘못된 번역이나 수정할 내용이 있으면 알려주시면 감사하겠습니다.
Beyond Basic
HTTP는
많은 사이트와 API에서 사용하는 Basic한 인증 방법만을 정의한다 - Basic한 인증 방법이란 사용자 아이디와 패스워드를
입력 받아서 인증을 처리하는 방식을 말한다.
Basic한 방법은 사용자 이름과 패스워드를 매 request 마다 plain text로 전송하여 동작한다.
HTTPS로 전송하지 않는 경우 이런 Basic한 방식은 중요한 보안적
결함을 가지게 되는데 여기서 우리는 세가지 점에 촛점을 맞추고자 한다.
첫번째는 전송되는 암호화 하지 않은 패스워드를 capture하여 재사용될 가능성이 있다는 점이다.
두번째는 자격증명서가 request에 연결되지 않는 다는
점인데 , 이것은 일단 한번 자격을 얻게 되면 어떤 request건 제약없이 사용을 할 수 있다는 의미이다.
세 번째는 Basic방식은 자격증명을 위임하기 위한 Placeholder를 제공하지 않고 오직 하나의 사용자 아이디, 패스워드의 쌍만을 지원한다는 점이다.
Consumer(Caller)의 자격증명과 User의 자격증명(Consumer access의 집합)을 동시에 전송하기 위하여서는 위임이 필수적이다.
OAuth 아키텍처는 이러한 세가지
제약사항에 주목하고 있다.
OAuth 의 signature method는 기본적으로 안전하지 않은 전송방식 - Non Https - 으로 설계되었다. MITM(man-in-the-middle attack) 같은 도청이나 다른 security risk를 막기 위하여서는 HTTPS가 좋은 솔루션이다.
그러나 HTTPS는 setup이나 유지보수 측면에서 매우 비싼 솔루션이다.
OAuth가 HTTPS위에 사용될때 대부분의 security에 대한 요구사항을 HTTPS에 맡기고 PLAINTEXT 방식이라는 훨씬 효율적이고 단순한 방법을 제공할수 있다.
물론 안전하지 않은 채널에서 PLAINTEXT방식을 사용하지 말아야 한다.
이 강의는 안전하지 않은 채널상에서 작업하기위한 HMAC-SHA1과 RSA-SHA1 에 좀더 집중하겠다.
Direct & Delegated Access
OAuth 의 명백한 목적은 Authorization Delegation Protocol(인증된 위임 프로토콜) 이다.
하나의 집단이 다른 사람의 리소스에 접근하기 위한 허가를 받는 것이 OAuth 프로토콜의 핵심이다.
이러한 위임 access 시나리오는 또한 3 - legged 시나리오로 알려져 있는데 Service Provider와 Consumer, 그리고 사용자 3자가 관련되어있다.
Consumer에 의하여서만 request가 생성되기 때문에 Service Provider를 스스로 인증하는 방법이 필요하지만 User data에 접근하는 데이터가 필요하게 된다. 이것은 OAuth가 HTTP 상에서 두개 셋의 자격조건을 지원해야 하는 요구사항이 된다.
OAuth는 2 legged 시나리오로 알려진 직접 접근 시나리오 에서도 동일하게 잘 동작한다.
이것은 대부분의 사람들이 친숙한 사용자이름과 패스워드로 로그인하는 인증방식이다. 이 시나리오에서는 다른 누구도 개입하지 않고 접근도 위임되지 않는다. Consumer는 리소스에 직접 접근하게 되고 Consumer와 User는 같은 Entity가 된다.
이것은 Consumer가 User측의 3-legged request와 Consumer측의 2-legged request를 각각 동시에 전송할때 약간의 혼란을 줄 수 있다.
Signature WorkFlow를 생각해 보면 각각의 자격증명이 무엇을 얻기 위하여 설계되었는지를 이해하는데 도움이 될 것이다.
Consumer의 자격증명은 request를 일으키는 집단을 인증하기 위한 것이기 때문에 만일 각 집단이 스스로 request를 만든다고 하더라도 그것은 end-user의 request 이기도 할것이기 때문이다. HTTP basic의 대안으로 OAuth를 사용하기를 원하는 application은 Consumer Key 와 Consumer Secret을 사용자 아이디와 패스워드대신 가지고 있어야만 하고, Token과 Token Secret을 비워둬야만 한다. 이것은 물론 직접적인 application 지원이 필요하다.
이 가이드는 인증을 위임하는 OAuth의 기본적인 use case에 집중하기 때문에 , 이 강의의 나머지 부분은 3-legged 시나리오에 더 살펴볼 것이다.
Credentials
매일 매일의 web 트랜잭션에서 가장 일반적인 자격증명은 사용자이름과 패스워드 조합이 사용되는 것이다.
OAuth의 기본적인 목적은 개인적인 리소스에 대하여 접근을 위임하도록 허락하는 것이다.
이것은 두셋의 자격증명으로 이루어진다.
Consumer identities은 Consumer Key와 Consumer Secret이고
User identities은 Token과 Token secret 이 그것이다.
각각의 셋은 사용자이름과 패스워드의 쌍과 동일하게 생각하면 된다. Consumer의 경우는 application의 경우와 동일하고 User의 경우는 end-user의 경우와 동일하기 때문이다.
Consumer의 자격증명이 더 사용자 이름 패스워드 인증 방식과 유사한데 User의 경우는 실제 사용자 이름과 패스워드와는 다른 Token으로 표현되기 때문이다. 이것은 Service Provider와 User가 Consumer의 접근을 허용함에 있어서 더 좋은 제어와 유연성을 가지게 해준다.
예를 들면 User는 패스워드의 변경없이도 Token을 폐지하여 다른 application에서의 접근을 막을 수 있다.
User의 사용자이름, 패스워드와 Token과의 Decoupling은 OAuth 아키텍처의 중요한 요소중의 하나이다.
OAuth는 두개의 중요한 Token을 포함하는데 이것은 Request Token과 Access Token이다.
각각은 OAuth의 위임 workflow에서 특정한 역할을 담당하고 있다.
OAuth specification이 진화하는 동안 이 2 Token 설계는 specification에 머물러 있던 것들을 살제 가치있는 사용성과 보안적 기능으로 바꾸는 역할을 하게 되었다. OAuth의 두개의 채널로 동작한다. 하나는 Front Channel이고 이것은 User와 인증 request를 연관짓기 위하여 사용되고, Back Channel은 Consumer에 의하여 Service Provider와 직접적으로 상호동작하기 위하여 사용되어진다. Access Token을 back channel로 제한함으로써 Token은 User를 은닉할수 있게 된다. 이것은 Access Token이 특별한 의미를 전달할 수 있도록 해주고, 인증을 요청하거나 Mobile이나 셋톱 박스 같이 수동으로 입력 해야 해서 User에게 노출되는 front channel 의 Request Token보다 더 큰 사이즈를 가지게 해준다.
request signing workflow는 모든 Token을 동일하게 처리하고 workflow 역시 동일하다. 두개의 Token은 Token들을 동일하게 사용하는 signature workflow가 아닌 인증 Workflow를 명시 하고 있다. 이것은 두개의 Token Type이 서로 대체할수 있음을 의미하는 것이 아니라, signing request시에 동일한 보안 기능을 제공함을 의미한다.
Signature and Hash
OAuth는 각 request 마다 패스워드 같은 전체 자격증명을 보내는 것 대신 Digital signatures 를 사용한다.
사람들이 특정 문서에 사인을 하는것으로 자신의 동의를 표현하는 것과 유사한 방식으로 Digital Signature는 요청을 받는 쪽에서 request의 content가 전송시에 변경되지 않았음을 확인할수 있게 한다. sender는 request의 수학적 알고리즘으로 구현된 signature를 계산하고 request에 그것을 포함시킨다.
반면 받는 쪽에서는 똑같은 workflow로 request의 signature를 계산하고 제공된 signature value와 비교한다. 만일 두개가 동일하면 전송중에 request가 변조되지 않았음을 확신(Confidence)하게 된다. 확신레벨 (Confidence level) 은 signature 알고리즘이 강력한 것인지 아닌지에 따라서 다르게 된다.
이 매커니즘은 양쪽에서 모두 똑같은 Signature 알고리즘과 과 똑같은 방식으로 적용되어야만 한다.
일반적인 디지털 콘텐츠를 Sign하는 방식은 Hash 알고리즘을 사용한다.
일반적으로 Hashing은 데이터를 받는 과정과 재현 가능한 방식으로 훨씬 작은 값으로 압축하는 과정으로 되어있다.
이것은 똑같은 Hash 알고리즘을 이용하면 똑같은 데이터는 항상 같은 값이 나오는 것을 의미한다. 원본 비압축 데이터를 보존하는 것이 목적인 압축과는 달리 Hashing은 작은 값에서 원래의 값으로 돌리는 것을 허용하지 않는다.
예를 들면 콘텐츠 길이에 상관없이 hash의 결과 값의 길이는 항상 일정하다.
이것 때문에 Hashing은 sender의 identity를 보증하지는 못한다. 오직 데이터의 무결점만을 보증할 뿐이다.
받는쪽에서 request가 인증된 sender에게서 온것이라는 것을 확인하기 위하여서는 hash 알고리즘은 shared Secret과 연관되어야 한다.
양 쪽 모두가 어떤 Shared Secret에 동의하였고 양쪽만 알고 있다면 그것을 콘텐츠에 붙여서 Hashing 할수 있다. 이것은 단순하게 이 비밀코드를 콘텐츠에 붙이는 것으로 완료될수도 있고 HMAC 같은 더 복잡한 알고리즘을 이용 할 수도 있다. Signature를 생성 하고 인증 할때는 request를 위조하고 수정하는 attack을 막기 위하여서는 양쪽모두 Shared secret에 접근하기 위한 권한이 필요하다.
HTTP Basic 인증 방식과 비교하여 이 방식의 장점은 실질적인 secret은 결코 request와 함께 전송되지 않는 다는 점이다.
secret은 request를 sign하는데만 사용되어지고 실제 그것의 일부분은 아니기 때문에 (제대로 구현이 되어있다면) 추출되어 질수 없다.
Signature는 안전하지 않은 channel을 통하여 Shared secret을 request와 함께 전송하는 것보다 같은 기능을 하지만 더 안전한 방식이다.
Secrets Limitations
OAuth 에서 Shared secret은 사용되는 Signature 방법에 의존적이다.
PLAINTEXT 와 HMAC-SHA1 방식에서는 shared secret은 Consumer Secret과 Token Secret의 조합이다.
RSA-SHA1 방식에서는 Consumer Private Key가 request를 sign할때
배타적으로 사용되고 비대칭 shared secret (Asymmetric shared secret) 으로 제공된다. 비대칭 키
페어는 Consumer와 Service provider 각 side에서 request를 sign할때 하나의 키를 사용하고
reqeust를 인증할때 또다른 키를 사용한다. Consumer를 위한 private Key와 Service Provider를
위한 Public Key는 반드시 일치해야 하고, 올바른 쌍의 경우에만 성공적으로 request를 sign하고 인증할 수 있다.
Asymmetric shared secrets을 사용할때의 장점은 Service Provider가 Consumer의 Private
Key를 가지고 있지 않아도 되므로 secret이 외부에 유출될때 발생할 수 있는 위험요소를 줄여줄 수 있다.
그러나, RSA-SHA1 방식이 Token
Secret을 사용하지 않기 때문에 , Private Key는 공격을 막기 위한 유일한 방식 이고, 한번 뚫리게 되면 모든
Token이 위험할수 있다.
OAuth
를 구현할때 대칭과 비대칭의 shared secrets의 제한사항을 이해 하는 것은 매우 중요하다.
Consumer secret (혹은 Private Key)은 Service Provider에 의하여
Consumer의 identity를 인증할때 사용된다. 웹서버 같은 web 기반의 Consumer의 경우 상대적으로
Consumer secret(Private Key)을 안전하게 유지하기가 쉽다. 반면 Consumer가 데스크탑 어플리케이션이나
모바일 어플리케이션 혹은 브라우저 어플리케이션 (Flash, java, silverlight , javascript 같은) 같은
client 소프트웨어라면 라면 Consumer의 자격증명은 각 application의 copy마다 포함되어야 한다. 이것은
Consumer secret (Private Key)가 application과 함께 배포 되어야 하고 이것은 상속적으로 그것들과
협의되어야 한다.(?)
이것이
그러한 application에서 OAuth의 사용을 막는것은 아니지만, 이러한 Public한 Secret을 가질수 있는
Service Provider에 대한 신뢰도에 대한 제약사항 가져다 준다. secret이 신뢰되어 질수 없기 때문에 Service
Provider는 그러한 application을 알수 있는 엔티티로 간주하고 Consumer Identity를 어떤 level의
trust도 필요없는 행위 (application의 상태를 수집한다 던가 하는..) 로 제약한다. 어떤 Serivce
Provider는 이러한 어플리케이션을 거부할수도 있고 다른 protocol이나 확장을 제공 할수도 있다. 그러나 지금 시점에서
이러한 제약 사항에 대하여 간단한 솔루션은 없는 상황이다.
Consumer에 대한 자격증명이 이러한 application에서의 취약함에도 불구하고 User의
자격증명(Token and Secret)이 보안 속성을 방어하는 각 Consumer 의 instance에 매우
specific하다는 것은 중요한 점이다. 물론 이것은 Consumer의 구현과 Token정보를 client 측에서 어떻게
저장하느냐에 따라서 의존적이다.
Consumer
자격증명으로 Token과 Token secret이 없고 단지 사용자 아이디와 패스워드를 사용하기 때문에 2-legged
시나리오와는 다르다.
HTTP Basic을 직접적으로 교체하는 방식으로
OAuth를 사용하게 되면 Consumer와 User는 같은 Entity이고, application은 즉각 User를 그들의
자격증명으로 집어넣을수 있다. 따라서 application자체에 그것을 하드코드 하는 것을 제거 할수 있다. 단순한
Sign-in을 위한 OAuth를 사용하는 것은 HTTP Basic과 동일한 사용자 경험을 줄수 있지만 안전하지 않은
Channel에서의 OAuth 사용은 훨씬 더 많은 안전성을 제공할수 있다.
Timestamp and Nonce
Signature와 Shared secret은 어느정도의 security level을 제공하고
있지만 여전히 공격으로 부터 안전하지 못하다.
Signature가 request의
conent 변조를 막고, shared secret이 권한이 있는 Consumer 로 부터의 request인지를 구분해 낸다.
Sniffing the network로 불리우는 권한이 없는 Party로 부터의
request를 가로채서 재사용하는 부분을 막기 위한 부분이 빠져있다. 이것은 replay attack으로 알려져 있는데,
shared secret이 보호되어진 상태로 있는한 네트웍상에 있는 어느 누구도 새로운 request를 변조할수 없다. 그렇지만
똑같은 sign을 이용하여 같은 request를 반복하여 보낼수는 있다.
만일
가로챈 request가 민감한 보호된 데이터를 access 하도록 제공되어진 것이라면 이것은 커다른 security risk
이다.
request를 재사용하는 replay를 막기 위하여 OAuth는
nonce와 Timestamp를 사용한다.
nonce는 한번 사용되는 숫자를
의미하고, 각 sign된 request를 유니크하게 구분하는 유니하고 랜덤하게 생성된 스트링을 의미한다.
각 request는 unique한 identifier를 가짐으로 인하여 Service
Provider는 request가 한번 이상 사용되는 것을 막을 수 있다. 이것은 Consumer가 각 request를
Service Provier에게 보낼때 유니크한 스트링을 생성해야 함을 의미한다. 그리고 Service Provider는 모든
nonce를 트래킹하여 두번 이상 사용되도록 막아야 한다는 것을 또한 의미한다. nonce는 Signature에 포함되기 때문에
shared secet에 대하여 알지 못하는 attacker에 의하여 변조될수 없다.
nonce를 사용하는것은 Service
Provider의 입장에서는 매우 cost가 드는 일이다. 왜냐하면 받은 nonce를 스트리지에 저장하는 것이 필요하기 때문이다.
이를 더 쉽게 구현하기 위하여 OAuth는 timestamp를 각
request마다 덧붙여서 Service Provider가 일정시간동안만 nonce를 저장하도록 하고 있다.
일정 시간보다 오래된 timestamp를 가진 request가 들어오는 경우 Service
Provider에 의하여 거부되고 저장할 필요가 없는 것이다. 허용된 일정 시간 이후에 들어오는 request를 replay로
간주하는 것이 안전 하기 때문이다. OAuth는 timestamp를 구현하기 위한 general mechanism을 제공하지만
실제 구현은 각 Service Provider에게 맡겨두고 있다. 보안 관점에서 실제 nonce는 timestamp값과 nonce
스트링 값과의 조합이다. 이 조합만이 유일한 값을 제공할수 있고 attacker에 의하여 재사용되는 것을 막을 수 있다.
Signature Methods
OAuth는 request를 sign하고 verify하는 3가지의 Signature 방법(
PLAINTEXT, HMAC-SHA1, RSA-SHA1)을 정의하고 있다.
PLAINTEXT는 자격증명을 encrypt하지 않는 HTTP BASIC 방식과 유사한 방식으로 HTTPS 상에서 동작하고자
의도된 것이다.
Basic 과는 달리 PLAINTEXT는
위임(Delegataion)을 지원한다. 다른 두가지 방식은 SHA1 해쉬 방식과 결합된 HMAC와 RSA Signature
알고리즘을 사용한다.
이 방식은 이 가이드에서 설명하기는 너무 복잡해서 설명을
하지는 않겠다. 그리고 이 알고리즘에 대한 가이드를 읽기전에는 직접 구현을 하기 보다 믿을만한 오픈 소스를 사용하는 것이
좋을것이다.
request를
sign할때, 어떤 singature 방식을 사용하여 request를 받는 쪽에서 인증을 위해 signature 재생산을 할 수
있는지를 명시해야 한다.
어떤 signature방식을 사용할지는 각
application에서 어떤 보안 요구 사항이 있는지에 따라서 다르다. 각각방식은 장점과 제한사항이 존재한다.
PLAINTEXT는 사용하기가 쉽고, 계산에 시간이 적게 걸린다. 그렇지만 오직 HTTPS나 비슷한
보안 channel에서만 안전하다.
HMAC-SHA1 은 대부분의 플랫폼에
적용가능한 단순하고 일반적인 알고리즘을 제공한다. 그러나 legacy device와 symmetric shared secret을
사용하는 모든곳에서는 사용할 수 없다.
RSA-SHA1 은 key-pairs를
사용하여 한층 강화된 보안을 제공한다. 그렇지만 더 복잡하고 키 생성이 필요하고 긴 학습곡선(?)이 필요하다.
Signature Base String
위의 예에서 살펴 봤듯이 양쪽 side에서는
똑같은 결과를 얻기 위하여 동일한 signature process를 행해야만 한다.
똑같은 알고리즘, share secret을 사용할 뿐만 아니라 같은 content를 사용해야 한다.
이것은 HTTP request를 signed content에 사용되는 하나의
string(Signature base string)으로 converting하는 일관된 방법이 필요하다.
이 base string을 만들기 위하여 많은 개발자가 specification에 노력을 했다.
다음 챕터에서 이 Signature base string을 만드는 것에 대한 예제를 제공한다.
'프로그래머로 살아가기 > OpenSocial' 카테고리의 다른 글
초보자를 위한 oAuth 가이드 - Workflow (6) | 2010.04.19 |
---|