OAuth 란 무엇일까

아래와 같은 로그인 창을 보셨을 것입니다. 별도의 회원가입 없이 로그인을 제공하는 플랫폼의 아이디만 있으면 서비스를 이용 할 수 있습니다. 외부 서비스에서도 인증을 가능하게 하고 그 서비스의 API를 이용하게 해주는 것, 이것을 바로 OAuth라고 합니다.

Inline-image-2017-02-19 16.56.18.979.png 출처: naver developer

OAuth 란

OAuth 2.0은 다양한 플랫폼 환경에서 권한 부여를 위한 산업 표준 프로토콜입니다.

간단하게 인증(Authentication)과 권한(Authorization)을 획득하는 것으로 볼 수 있습니다.

OAuth의 배경

third party Application에 아이디와 비밀번호를 제공하고 싶지 않은 요구가 첫번째입니다. 개인정보를 여러 곳에 입력하면서 피싱에 둔감해지고 무엇보다 Application이 안전하다는 보장이 없기 때문에 보안에 취약했습니다.

당시에는 인증과 권한을 부여하는 요구를 만족 시킬 수 있는 인증방식이 없어서 Twitter의 주도로 OAuth 1.0이 탄생하였습니다.

비밀번호 인증방식의 문제

OAuth 구성 (1.0a)

3-legged-auth

유저(user), 컨슈머(consumer), 서비스 프로바이더(service provider)

그런데 OAuth1.0은..

구현이 복잡하고 웹이 아닌 어플리케이션에서의 지원이 부족하였습니다. HMAC을 통해 암호화를 하는 번거로운 과정을 겪습니다. 또한 인증토큰(access token)이 만료되지 않습니다

OAuth 2.0

달라진 점

OAuth2.0 구성

Inline-image-2017-02-19 17.02.51.198.png

인증과정

설명적기

출처: 페이코 개발자센터 OAuth 2.0 프로세스

OAuth 인증프로세스 (Authorization Code Grant)

발급받은 Access Token은 서비스에서 자체적으로 저장, 관리해야함

인증 종류

OAuth 2.0의 인증종류는 아래 4가지 입니다.

  Confidential Client Public Client
3-legged Authorization Code Implicit
2-legged Resource Owner Password Credentials Client Credentials

(2-legged는 잘 쓰이지 않습니다)

Authorization Code Grant

Implicit Grant

Password Credentials Grant

Client Credentials Grant

Token

Access Token

앞서 말한 4가지 권한 요청 방식 모두, 요청 절차를 정상적으로 마치면 클라이언트에게 Access Token이 발급됩니다. 이 토큰은 보호된 리소스에 접근할 때 권한 확인용으로 사용됩니다. 문자열 형태이며 클라이언트에 발급된 권한을 대변하게 됩니다. 계정 아이디와 비밀번호 등 계정 인증에 필요한 형태들을 이 토큰 하나로 표현함으로써, 리소스 서버는 여러 가지 인증 방식에 각각 대응 하지 않아도 권한을 확인 할 수 있게 됩니다.

Refresh Token

한번 발급받은 Access Token 은 사용할 수 있는 시간이 제한되어 있습니다. 사용하고 있던 Access Token 이 유효기간 종료 등으로 만료되면, 새로운 액세스 토큰을 얻어야 하는데 그때 이 Refresh Token 이 활용됩니다. 권한 서버가 Access Token 을 발급해주는 시점에 Refresh Token 도 함께 발급하여 클라이언트에게 알려주기 때문에, 전용 발급 절차 없이 Refresh Token을 미리 가지고 있을 수 있습니다. 토큰의 형태는 Access Token과 동일하게 문자열 형태입니다. 단 권한 서버에서만 활용되며 리소스 서버에는 전송되지 않습니다.

토큰의 갱신 과정

클라이언트가 권한 증서를 가지고 권한서버에 Access Token 을 요청하면, 권한 서버는 Access Token과 Refresh Token 을 함께 클라이언트에 알려줍니다. 그 후 클라이언트는 Access Token을 사용하여 리소스 서버에 각종 필요한 리소스들을 요청하는 과정을 반복합니다. 그러다가 일정한 시간이 흐른 후 액세스 토큰이 만료되면, 리소스 서버는 이후 요청들에 대해 정상 결과 대신 오류를 응답하게 됩니다. 오류 등으로 액세스 토큰이 만료됨을 알아챈 클라이언트는, 전에 받아 두었던 Refresh Token을 권한 서버에 보내어 새로운 액세스 토큰을 요청합니다. 갱신 요청을 받은 권한 서버는 Refresh Token 의 유효성을 검증한 후, 문제가 없다면 새로운 액세스 토큰을 발급해줍니다. 이 과정에서 옵션에 따라 Refresh Token 도 새롭게 발급 될 수 있습니다.

출처 [http://widencode.com/3]

API 권한 제어 (scope)

써드파티 어플리케이션의 권한을 설정하기 위한 기능입니다. scope의 이름이 스펙에 정의되어 있지는 않아 각 OAuth지원 플랫폼마다 다르게 설정 됩니다. 여러 개의 권한을 요청할 때에는 콤마등을 사용해서 로그인 시에 scope를 넘겨주게 됩니다.

http://example.com/oauth?….&scope=read_article,update_profile

token_type

OAuth 응답에는 token_type이 필수로 넘어오는데 이 token_type이 뭔지 궁금해서 RFC 문서를 뒤져봤습니다. 대부분 Bearer이 넘어오는데 단어가 생소해서 찾아보니 무언가를 옮기는 사람이라고 하네요. token_type: beareraccess_tokenbearer_token으로 준다는 의미입니다.

RFC에는 아래와 같이 나와있습니다.

A security token with the property that any party in possession of the token (a “bearer”) can use the token in any way that any other party in possession of it can. Using a bearer token does not require a bearer to prove possession of cryptographic key material (proof-of-possession).

키 인증없이 resource에 접근 할 수 있도록 하는 의미로 access_token이 만료되면 refresh_token으로 갱신해야 하기 때문에 bearer_token을 씁니다. RFC에는 mac_token이라고 타입이 하나 더 나오긴하는데 설명은 제대로 쓰여있지 않습니다.

인증 예시 (Authorization Code Grant)

인증서버에 authority code를 요청

GET
https://alpha-id.payco.com/oauth2.0/authorize?
    client_id={client_id}&
    redirect_uri=http://nhnent.dooray.com/auth/signin/process/payco?nextUrl=%2F&
    response_type=code&
    serviceProviderCode=DOORAY&
    termsYN=Y&
    state={random_string}

발급받은 authority code로 client에 요청

GET
http://nhnent.dooray.com/auth/signin/process/payco?
    nextUrl=/&
    code=NyP8aIFKIS6r8tm2&
    state={random_string}

client는 인증서버에 access-token 요청

POST
https://alpha-id.payco.com/oauth2.0/token

grant_type=authorization_code&
code=NyP8aIFKIS6r8tm2&
client_id={client_id}&
client_secret={client_secret}&
state={random_string}

응답 예제

{
"access_token_secret" :  "32321vveerrer2fv",
"state" :  null,
"expires_in" :  "11111",
"token_type" :  "Bearer",
"access_token" :  "AAAA4NV74n+ns623iceBu343424C4cMZ0A5T5pGjwfMF5b/Yj+LyDBqK8+/jvVTIKHbzM47wFw8qUf0fTCw4+/ko+hSgAGClMLykvaDJ7/0B/OxlM99999AqkvAw4niLVho14Izga2c5IksQOjTTv5L8keM4yTplN50xzGzYJpV1vmj3NGWtPKHaJL3fLVa41hvZmxOw00edQeOYAw/vhLW7iQDuJjpTciWgmgEUd9if7EL+tqIJmE6fRSH42b4aNOX5XgiaEr6hUDisUoHG5kqOd",
"refresh_token" :  "AAAAb7F2pdU0FZuxHreJD12wefvber/LIsbLGHdW85lVuJ3OaNDguDnGx5+FZeZaIbBTDRBcaneT9WlrDNORX8eyVf5bgL6RrENn5tKhjdjQlmsXxH1wCJDUa2J2QtQOHRTxAg="
}
관련 문서 더보기
blog comments powered by Disqus