Generates a new AccessToken from a request containing a refresh token.

  Read the specification: http://tools.ietf.org/html/rfc6749#section-6.

def generate_access_token_from_refresh_token(request, client):
  """ Generates a new AccessToken from a request containing a refresh token.

  Read the specification: http://tools.ietf.org/html/rfc6749#section-6.
  """
  refresh_token_value = request.POST.get('refresh_token')
  if not refresh_token_value:
    raise InvalidRequest('no "refresh_token" provided')

  try:
    existing_access_token = AccessToken.objects.get(
        refresh_token=refresh_token_value,
        client=client)
  except AccessToken.DoesNotExist:
    raise InvalidGrant('"{}" is not a valid "refresh_token"'.format(
      refresh_token_value))

  if existing_access_token.invalidated:
    refresh_token_used_after_invalidation.send(
        sender='djoauth2',
        access_token=existing_access_token,
        request=request)
    raise InvalidGrant('"{}" is not a valid "refresh_token"'.format(
      refresh_token_value))

  if not existing_access_token.refreshable:
    raise InvalidGrant('access token is not refreshable')

  # The specification (http://tools.ietf.org/html/rfc6749#section-6) describes
  # the scope parameter as follows:
  #
  #     scope
  #           OPTIONAL.  The scope of the access request as described by
  #           Section 3.3.  The requested scope MUST NOT include any
  #           scope not originally granted by the resource owner, and if
  #           omitted is treated as equal to the scope originally granted
  #           by the resource owner.
  #
  # This opens the possibility that a Client might successfully request a
  # subset of the existing scopes, but later in the same section comes the
  # following:
  #
  #      If a new refresh token is issued, the refresh token scope MUST be
  #      identical to that of the refresh token included by the client in the
  #      request.
  #
  # Confusingly, http://tools.ietf.org/html/rfc6749#section-1.5 includes the
  # following:
  #
  #     Refresh tokens are credentials used to obtain access tokens.  Refresh
  #     tokens are issued to the client by the authorization server and are
  #     used to obtain a new access token when the current access token becomes
  #     invalid or expires, or to obtain additional access tokens with
  #     identical or narrower scope (access tokens may have a shorter lifetime
  #     and fewer permissions than authorized by the resource owner).
  #
  # This last section explicitly allows tokens with narrower scope than
  # originally granted, which is in direct contradiction with the directive
  # that the scope must be equivalent to that granted earlier.
  #
  # Because the specification seems to contradict itself, I tend towards
  # observing the stricter directive (not allowing a subset of scope,) even
  # though to me there seems to be no reason to disallow that feature. That
  # said, I'm not sure why a client would ever ask for less scope than
  # originally granted.
  scope_objects = existing_access_token.scopes.all()
  new_scope_names = request.POST.get('scope', '')
  if new_scope_names:
    new_scope_names = new_scope_names.split(' ')
    if not existing_access_token.has_scope(*new_scope_names):
      raise InvalidScope('requested scopes exceed initial grant')

    scope_objects = []
    for scope_name in new_scope_names:
      try:
        scope_objects.append(Scope.objects.get(name=scope_name))
      except Scope.DoesNotExist:
        raise InvalidScope('"{}" is not a valid scope'.format(scope_name))

  requested_scope_string = request.POST.get('scope', '')
  if requested_scope_string:
    requested_scope_names = set(requested_scope_string.split(' '))
    if not requested_scope_names == existing_access_token.get_scope_names_set():
      raise InvalidScope('requested scopes do not match initial grant')


  # The new AccessToken is only refreshable if at the time of refresh the
  # server is configured to create refreshable tokens by default. It DOES NOT
  # inherit the existing token's 'refreshability' automatically. No behavior is
  # described in the specification; I believe this to be a sane decision.
  new_access_token = AccessToken.objects.create(
      user=existing_access_token.user,
      client=existing_access_token.client)
  new_access_token.authorization_code = existing_access_token.authorization_code
  new_access_token.scopes = scope_objects
  new_access_token.save()

  existing_access_token.invalidate()

  return new_access_token