Ejemplo n.º 1
0
    def make_error_response(self, validation_error, expose_errors):
        """ Return an appropriate ``HttpResponse`` on authentication failure.

    In case of an error, the specification only details the inclusion of the
    ``WWW-Authenticate`` header. Additionally, when allowed by the
    specification, we respond with error details formatted in JSON in the body
    of the response. For more information, read the specification:
    http://tools.ietf.org/html/rfc6750#section-3.1 .

    :param validation_error: A
      :py:class:`djoauth2.access_token.AuthenticationError` raised by the
      :py:meth:`validate` method.
    :param expose_errors: A boolean describing whether or not to expose error
      information in the error response, as described by the section of the
      specification linked to above.

    :rtype: a Django ``HttpResponse``.
    """
        authenticate_header = [
            'Bearer realm="{}"'.format(settings.DJOAUTH2_REALM)
        ]

        if not expose_errors:
            response = HttpResponse(status=400)
            response['WWW-Authenticate'] = ', '.join(authenticate_header)
            return response

        status_code = 401
        error_details = get_error_details(validation_error)

        if isinstance(validation_error, InvalidRequest):
            status_code = 400
        elif isinstance(validation_error, InvalidToken):
            status_code = 401
        elif isinstance(validation_error, InsufficientScope):
            error_details['scope'] = ' '.join(self.required_scope_names)
            status_code = 403

        # TODO(peter): should we return response details as JSON? This is not
        # touched upon by the spec and may limit use of this library.  Many
        # programmers use other transport languaes such as YAML or XML. All of the
        # error information is already included in the headers.
        response = HttpResponse(content=json.dumps(error_details),
                                content_type='application/json',
                                status=status_code)

        for key, value in error_details.iteritems():
            authenticate_header.append('{}="{}"'.format(key, value))

        response['WWW-Authenticate'] = ', '.join(authenticate_header)
        return response
Ejemplo n.º 2
0
  def make_error_response(self, validation_error, expose_errors):
    """ Return an appropriate ``HttpResponse`` on authentication failure.

    In case of an error, the specification only details the inclusion of the
    ``WWW-Authenticate`` header. Additionally, when allowed by the
    specification, we respond with error details formatted in JSON in the body
    of the response. For more information, read the specification:
    http://tools.ietf.org/html/rfc6750#section-3.1 .

    :param validation_error: A
      :py:class:`djoauth2.access_token.AuthenticationError` raised by the
      :py:meth:`validate` method.
    :param expose_errors: A boolean describing whether or not to expose error
      information in the error response, as described by the section of the
      specification linked to above.

    :rtype: a Django ``HttpResponse``.
    """
    authenticate_header = ['Bearer realm="{}"'.format(settings.DJOAUTH2_REALM)]

    if not expose_errors:
      response = HttpResponse(status=400)
      response['WWW-Authenticate'] = ', '.join(authenticate_header)
      return response

    status_code = 401
    error_details = get_error_details(validation_error)

    if isinstance(validation_error, InvalidRequest):
      status_code = 400
    elif isinstance(validation_error, InvalidToken):
      status_code = 401
    elif isinstance(validation_error, InsufficientScope):
      error_details['scope'] = ' '.join(self.required_scope_names)
      status_code = 403

    # TODO(peter): should we return response details as JSON? This is not
    # touched upon by the spec and may limit use of this library.  Many
    # programmers use other transport languaes such as YAML or XML. All of the
    # error information is already included in the headers.
    response = HttpResponse(content=json.dumps(error_details),
                            content_type='application/json',
                            status=status_code)

    for key, value in error_details.iteritems():
      authenticate_header.append('{}="{}"'.format(key, value))

    response['WWW-Authenticate'] = ', '.join(authenticate_header)
    return response
Ejemplo n.º 3
0
  def make_error_redirect(self, authorization_error=None):
    """ Return a Django ``HttpResponseRedirect`` describing the request failure.

    If the :py:meth:`validate` method raises an error, the authorization
    endpoint should return the result of calling this method like so:

      >>> auth_code_generator = (
      >>>     AuthorizationCodeGenerator('/oauth2/missing_redirect_uri/'))
      >>> try:
      >>>   auth_code_generator.validate(request)
      >>> except AuthorizationError as authorization_error:
      >>>   return auth_code_generator.make_error_redirect(authorization_error)

    If there is no known Client ``redirect_uri`` (because it is malformed, or
    the Client is invalid, or if the supplied ``redirect_uri`` does not match
    the regsitered value, or some other request failure) then the response will
    redirect to the ``missing_redirect_uri`` passed to the :py:meth:`__init__`
    method.

    Also used to signify user denial; call this method without passing in the
    optional ``authorization_error`` argument to return a generic
    :py:class:`AccessDenied` message.

      >>> if not user_accepted_request:
      >>>   return auth_code_generator.make_error_redirect()

    """
    if not self.redirect_uri:
      return HttpResponseRedirect(self.missing_redirect_uri)

    authorization_error = (authorization_error or
                           AccessDenied('user denied the request'))
    response_params = get_error_details(authorization_error)

    # From http://tools.ietf.org/html/rfc6749#section-4.1.2.1 :
    #
    #     REQUIRED if the "state" parameter was present in the client
    #     authorization request.  The exact value received from the
    #     client.
    #
    if self.state is not None:
      response_params['state'] = self.state
    return HttpResponseRedirect(
        update_parameters(self.redirect_uri, response_params))