docs: def access_token_endpoint(request):
    """ Generates :py:class:`djoauth2.models.AccessTokens` if provided with
    sufficient authorization.
  
    This endpoint only supports two grant types:
      * ``authorization_code``: http://tools.ietf.org/html/rfc6749#section-4.1
      * ``refresh_token``: http://tools.ietf.org/html/rfc6749#section-6
  
    For further documentation, read http://tools.ietf.org/html/rfc6749#section-3.2
    """
    # TODO(peter): somehow implement the anti-brute-force requirement specified
    # by http://tools.ietf.org/html/rfc6749#section-2.3.1 :
    #
    #     Since this client authentication method involves a password, the
    #     authorization server MUST protect any endpoint utilizing it against
    #     brute force attacks.
    #
  
    try:
      # From http://tools.ietf.org/html/rfc6749#section-3.2 :
      #
      #     Since requests to the token endpoint result in the transmission of
      #     clear-text credentials (in the HTTP request and response), the
      #     authorization server MUST require the use of TLS as described in
      #     Section 1.6 when sending requests to the token endpoint.
      #
      if settings.DJOAUTH2_SSL_ONLY and not request.is_secure():
        raise InvalidRequest('all token requests must use TLS')
  
      # From http://tools.ietf.org/html/rfc6749#section-3.2 :
      #
      #     The client MUST use the HTTP "POST" method when making access token
      #     requests.
      #
      if not request.method == 'POST':
        raise InvalidRequest('all posts must use POST')
  
      client_id = None
      client_secret = None
  
      # Allow client Authentication via HTTP Basic Authentication (
      # http://tools.ietf.org/html/rfc2617#section-2 ) as described by
      # http://tools.ietf.org/html/rfc6749#section-2.3.1 :
      #
      #     Clients in possession of a client password MAY use the HTTP Basic
      #     authentication scheme as defined in [RFC2617] to authenticate with
      #     the authorization server.  The client identifier is encoded using the
      #     "application/x-www-form-urlencoded" encoding algorithm per Appendix
      #     B, and the encoded value is used as the username; the client password
      #     is encoded using the same algorithm and used as the password.  The
      #     authorization server MUST support the HTTP Basic authentication
      #     scheme for authenticating clients that were issued a client password.
      #
      # by accepting an 'Authorization' header like so:
      #
      #      Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3
      #
      # where 'czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3' is the result of
      #
      #     base64encode('{client_id}:{client_secret}')
      #
      if 'HTTP_AUTHORIZATION' in request.META:
        try:
          http_authorization = request.META.get('HTTP_AUTHORIZATION', '')
          auth_method, auth_value = http_authorization.strip().split(' ', 1)
        except ValueError:
          raise InvalidRequest('malformed HTTP_AUTHORIZATION header')
  
        if not auth_method == 'Basic':
          raise InvalidRequest('unsupported HTTP_AUTHORIZATION method')
  
        try:
          client_id, client_secret = b64decode(auth_value).split(':')
        except (TypeError, ValueError):
          raise InvalidRequest('malformed HTTP_AUTHORIZATION value')
  
  
      # The 'client_id' and 'client_secret' parameters MUST NOT be included in
      # the request URI (GET parameters), as specified by
      # http://tools.ietf.org/html/rfc6749#section-2.3.1 :
      #
      #     The parameters can only be transmitted in the request-body and MUST
      #     NOT be included in the request URI.
      #
      if 'client_id' in request.GET or 'client_secret' in request.GET:
        raise InvalidRequest(
            'must not include "client_id" or "client_secret" in request URI')
  
  
      # Allow Clients to authenticate via POST request data, as specified by
      # http://tools.ietf.org/html/rfc6749#section-3.2.1 :
      #
      #     A client MAY use the "client_id" request parameter to identify itself
      #     when sending requests to the token endpoint.  In the
      #     "authorization_code" "grant_type" request to the token endpoint, an
      #     unauthenticated client MUST send its "client_id" to prevent itself
      #     from inadvertently accepting a code intended for a client with a
      #     different "client_id".  This protects the client from substitution of
      #     the authentication code. (It provides no additional security for the
      #     protected resource.)
      #
      # Please note that this is NOT RECOMMENDED, and that the client should
      # instead authenticate via the HTTP_AUTHORIZATION header -- see
      # http://tools.ietf.org/html/rfc6749#section-2.3.1 :
      #
      #     Alternatively, the authorization server MAY support including the
      #     client credentials in the request-body using the following parameters:
      #
      #     client_id
      #           REQUIRED.  The client identifier issued to the client during
      #           the registration process described by Section 2.2.
      #
      #     client_secret
      #           REQUIRED.  The client secret.  The client MAY omit the
      #           parameter if the client secret is an empty string.
      #
      #     Including the client credentials in the request-body using the two
      #     parameters is NOT RECOMMENDED and SHOULD be limited to clients unable
      #     to directly utilize the HTTP Basic authentication scheme (or other
      #     password-based HTTP authentication schemes).  The parameters can only
      #     be transmitted in the request-body and MUST NOT be included in the
      #     request URI.
      #
      # In the case that the Client has already authenticated with the
      # HTTP_AUTHORIZATION method, ensure that they do not also attempt to
      # authenticate via POST data, as required by
      # http://tools.ietf.org/html/rfc6749#section-2.3 :
      #
      #     The client MUST NOT use more than one authentication method in each
      #     request.
      #
      if client_id and client_secret:
        if 'client_id' in request.POST or 'client_secret' in request.POST:
          raise InvalidRequest('must use only one authentication method')
      else:
        client_id = request.POST.get('client_id')
        client_secret = request.POST.get('client_secret')
  
      if not (client_id and client_secret):
        raise InvalidRequest('no client authentication provided')
  
      try:
        client = Client.objects.get(key=client_id, secret=client_secret)
      except Client.DoesNotExist:
        raise InvalidClient('client authentication failed')
  
      # The two supported grant types
      grant_type = request.POST.get('grant_type')
      if not grant_type:
        raise InvalidRequest('no "grant_type" provided')
  
      if grant_type == 'authorization_code':
        access_token = generate_access_token_from_authorization_code(request,
                                                                     client)
      elif grant_type == 'refresh_token':
        access_token = generate_access_token_from_refresh_token(request, client)
      else:
        raise UnsupportedGrantType(
            '"{}" is not a supported "grant_type"'.format(grant_type))
  
      # Successful response documentation:
      # http://tools.ietf.org/html/rfc6749#section-5.1
      response_data = {
          'access_token': access_token.value,
          'expires_in': access_token.lifetime,
          'token_type': 'bearer', # http://tools.ietf.org/html/rfc6749#section-7.1
          'scope': ' '.join(access_token.get_scope_names_set()),
        }
      if access_token.refreshable:
        response_data['refresh_token'] = access_token.refresh_token
  
      response = HttpResponse(content=json.dumps(response_data),
                              content_type='application/json')
      response.status_code = 200
      response['Cache-Control'] = 'no-store'
      response['Pragma'] = 'no-cache'
      return response
  
    except AccessTokenError as generation_error:
      # Error response documentation:
      # http://tools.ietf.org/html/rfc6749#section-5.2
      error_name = getattr(generation_error,
                           'error_name',
                           'invalid_request')
      error_description = str(generation_error) or 'Invalid Request.'
      response_data = {
          'error':  error_name,
          'error_description': error_description,
        }
  
      response = HttpResponse(content=json.dumps(response_data),
                              content_type='application/json')
      if isinstance(generation_error, InvalidClient):
        response.status_code = 401
      else:
        response.status_code = 400
  
      return response