[RFC 6749] #05. Obtaining Authorization

undefcat·2020년 3월 26일
6

RFC 6749

목록 보기
5/5
post-thumbnail

Obtaining Authorization

OAuth 2.0에서는 4가지의 인증 권한 부여 타입이 존재하는데, 이전부터 언급했듯 Authorization CodeImplict에 대해서만 알아볼 것이다.

Authorization Code Grant

Authorization Code Flow

일반적으로 SNS로그인 등을 경험해봤다면, 이해하기가 수월할 것이다. RFC 6749는 HTTP를 전제로 작성되었으므로, 리다이렉션 과정이 필수적이다. 이제 각 단계에서 어떤 값들이 필요한지 살펴보자.

Authorization Request

처음 시작은 Resource OwnerClient로부터 페이지를 응답받아 어떤 버튼을 클릭하는 것으로 시작할 것이다(예를 들어 페이스북 로그인 등).

이 때, 이 링크에는 Resource OwnerAuthorization Server로 이동할 때 Authorization ServerClient에 대한 정보를 판단하기 위한 값들이 들어있을 것이다.

response_type

  • REQUIRED
  • Authorization Code에서는 반드시 code여야 한다.

client_id

  • REQUIRED
  • 사전에 ClientAuthorization Code에 등록하고 난 뒤 부여받은 값

redirect_uri

  • OPTIONAL
  • 등록시 약속된 redirect_uri 중 하나. 만약 기본값 설정같은 것이 있다면 따로 필요 없다.
  • Resource Owner가 인증 후 결과값을 처리할 페이지가 redirect_uri다.

scope

state

  • RECOMMENDED
  • 보통 CSRF를 막기 위한 값을 Client에서 전달해준다. 나중에 Authorization Server는 이 값을 그대로 돌려주면 된다.

Example

명세에서 예시로 드는 HTTP 메세지는 아래와 같다.

GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2A%2Aclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com

Authorization Response

Resource Owner가 인증 후, Clientredirect_uri로 리다이렉트 되어 이동할 때 Authorization Server에서 바인딩해준 값들은 아래와 같아야 한다.

code

  • REQUIRED
  • 이는 수명주기가 최대 10분 이내로 매우 짧은 값이어야 한다(유출 방지).
  • 한 번만 사용되고 폐기되어야 하는 값이다. 두 번 이상 사용될 수 없다.

state

  • Client가 요청했을 때 있었다면 반드시 응답되어야 한다.
  • 정확히 요청받은 그 값 그대로 응답해야 한다.

Example

HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=Splx1OBeZQQYbYS6WxSbIA&state=xyz

Error Response

Authorization Server에 필요한 정보가 없이(예를 들어 client_id 등) Resource Owner가 넘어온 경우, Authorization Server는 이에 대한 에러를 Resource Owner에게 알려주는 것이 좋다(SHOULD). 그리고 절대로 redirect_uri로는 리다이렉트 시키면 안 된다. 보통 이런 경우는 없어야 하므로 Client 개발자는 신경써서 구현해야 한다.

Resource Owner가 인증 후 발생한 에러의 경우, Authorization Server는 에러 정보와 함께 Resource Ownerredirect_uri로 리다이렉트 시켜주면 된다.

참고로 URI에 바인딩 되는 값들이므로, 오직 ASCII만을 허용한다. (Unicode는 허용하지 않음)

error

  • REQUIRED
  • 아래의 값 중 하나면 된다.
    • invalid_request
      • 필수값들이 빠져있거나 등의 경우
    • unauthorized_client
      • 등록되지 않은 client의 경우
    • unsupported_response_type
      • response_type=code 를 지원하지 않는 경우
    • invalid_scope
      • scope값이 유효하지 않은 경우
    • server_error
      • 500 에러인 경우
    • temporarily_unavailable
      • 503 에러인 경우

error_description

  • OPTIONAL
  • 사람이 읽을 수 있는 값이면 된다.

error_uri

  • OPTIONAL
  • Client 개발자가 에러 메세지를 확인할 수 있는 문서화된 URI가 존재한다면, 그 링크 주소를 나타낸다.

state

  • Client가 요청했을 때 있었다면 반드시 응답되어야 한다.
  • 정확히 요청받은 그 값 그대로 응답해야 한다.

Example

HTTP/1.1 302 Found
Location: https://client.example.com/cb?error=access_denied&state=xyz

Access Token Request

Resource Owner가 얻어온 Authorization Code값을 이용해서 ClientToken EndpointAccess TokenRefresh Token을 얻을 수 있다.

이 때의 요청은 이전에도 언급했지만, POST 메서드만을 허용한다.

grant_type

  • REQUIRED
  • 반드시 authorization_code여야 한다.

code

  • REQUIRED
  • 위 프로세스에서 발급받은 code값이어야 한다.

redirect_uri

  • Authorization Request시에 redirect_uri를 명시했었다면, 반드시 똑같은 값으로 포함되어야 한다.

client_id

보통의 경우, Client는 반드시 Client Authentication 과정을 거쳐야 한다.

Example

Post /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code\SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

이 과정에서 Authorization Server반드시 아래의 과정을 처리해야한다.

  • Client Authentication
  • Authorization Code 인증
  • redirect_uri값 유효성 검증 및 비교(최초 Authorization Request 과정에서 포함되었던 경우)

Access Token Response

Access Token 응답에 대한 스펙은 여러 섹션(#5 Issuing an Access Token, #7 Accessing Protected Resources)에 걸쳐 정의되어 있는데, 이를 한 번에 정리하도록 하겠다.

인증이 완료되면 Authorization Server는 기본적으로 Access Token과 함께 필요한 경우 Refresh Token 등 여러 정보를 응답해주면 된다.

응답 바디의 Content-Type반드시 application/json이어야 한다.

access_token

  • REQUIRED

token_type

token_typeRFC 6750을 따른다. 우린 그 중 Bearer 타입만을 사용할 것이므로, 일반적인 경우 bearer이 될 것이다.

  • REQUIRED
  • 토큰 타입명
  • case insensitive다.

expires_in

  • RECOMMENDED
  • 단위는 second다.
  • 토큰의 유효시간

refresh_token

  • OPTIONAL

scope

  • OPTIONAL
  • 계속 언급했으므로 생략

Example

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"2YotnFZFEjrlzCsicMWpAA",
  "token_type":"bearer",
  "expires_in":3600,
  "refresh_token":"tGzv3JOkF0XG5Qx2T1KWIA",
  "example_parameter":"example_value"
}

Implict Grant

Authorization Code Grant를 지금까지 알아보았는데, Implict Grant는 거의 대부분의 과정이 Authorization Code Grant와 비슷하다. 다만, 한가지 차이가 있다면 Authorization Code를 발급받아 Client가 다시 Authorization ServerAccess Token을 요청하는 것이 아닌, Resource Owner가 애초에 Access Token값을 갖고 온다는 차이가 있다.

이는 추가적인 요청이 1회 줄어듦을 의미한다.

Implict Grant Flow

플로우 다이어그램을 보면 알 수 있듯, Resource Owner가 이미 Access Token을 갖고 오기 때문에 Client는 바로 Access Token을 사용할 수 있다.

이는 Authorization Code Grant방식에서 필수로 존재하는 Client Authentication 과정이 생략된 것이라고 볼 수 있다.

이러한 방식은 요청의 횟수가 줄어든다는 장점과, Access TokenResource Owner에게 노출된다는 단점이 있다.

Access Token Response

Authroization Request 과정은 Authorization Code GrantAuthorization Request과 같다. 다만 Implict Grant에서는 Authorization Request의 결과로 Access Token Response를 받는 다는 점에 차이가 있다.

Access Token Response 스펙 역시 Authorization Code Grant와 같다. 단, 몇 가지 명심해야 할 점이 있다.

  1. refresh_token을 응답하면 안 된다.
  2. Authoriation Request는 보통의 경우 GET 메서드로 요청되므로, 이 때에는 결괏값이 URI에 바인딩 되어야 한다.

다음엔

OAuth 2.0에서 가장 중요하다고 볼 수 있는 스펙에 대해서 알아보았다. 이제, OAuth 2.0을 구현하는데 필요한 기초정보는 모두 알아보았으므로 이제 다음 챕터부터는 Golang을 이용해서 OAuth 2.0을 직접 구현해볼 것이다!

(다음 챕터가 언제 발행될지는 잘 모르겠다🤣)

profile
undefined cat

2개의 댓글

comment-user-thumbnail
2020년 3월 26일

좋은 글 감사합니다.

1개의 답글