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
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
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))