docs: def validate(self, request):
      """ Checks a request for proper authentication details.
  
      Returns a tuple of ``(access_token, error_response_arguments)``, which are
      designed to be passed to the :py:meth:`make_error_response` method.
  
      For example, to restrict access to a given endpoint:
  
      .. code-block:: python
  
          def foo_bar_resource(request, *args, **kwargs):
            authenticator = AccessTokenAuthenticator(
                required_scope_names=('foo', 'bar'))
  
            access_token, error_args = authenticator.validate(request)
            if not access_token:
              return authenticator.make_error_response(*error_args)
  
            # ... can now return use access_token
  
  
      :rtype: When the request validates successfully, returns a
          a tuple of (:py:class:`djoauth2.models.AccessToken`, ``None``).  If the
          request fails to validate, returns a tuple of (``None``,
          ``error_details_tuple``). The ``error_details_tuple`` is a tuple of
          arguments to use to call the :py:func:`make_error_response` method.
  
      """
      # Ensure that all of the scopes that are being checked against exist.
      # Otherwise, raise a ValueError.
      for name in self.required_scope_names:
        if not Scope.objects.filter(name=name).exists():
          raise ValueError('Scope with name "{}" does not exist.'.format(name))
  
      # From http://tools.ietf.org/html/rfc6750#section-3.1 :
      #
      #        If the request lacks any authentication information (e.g., the
      #        client was unaware that authentication is necessary or attempted
      #        using an unsupported authentication method), the resource server
      #        SHOULD NOT include an error code or other error information.
      #
      # In the case that the request fails to validate, this flag will
      # be returned and should be passed to the 'make_error_response' method
      # in order to comply with the specification and restrict error information.
      expose_errors = False
  
      try:
        # From http://tools.ietf.org/html/rfc6750#section-1 :
        #
        #     This specification defines the use of bearer tokens over HTTP/1.1
        #     [RFC2616] using Transport Layer Security (TLS) [RFC5246] to access
        #     protected resources.  TLS is mandatory to implement and use with
        #     this specification; other specifications may extend this
        #     specification for use with other protocols.  While designed for use
        #     with access tokens
        #
        # and later, from http://tools.ietf.org/html/rfc6750#section-5.3 :
        #
        #    Always use TLS (https):  Clients MUST always use TLS [RFC5246]
        #    (https) or equivalent transport security when making requests with
        #    bearer tokens.  Failing to do so exposes the token to numerous
        #    attacks that could give attackers unintended access.
        #
        if settings.DJOAUTH2_SSL_ONLY and not request.is_secure():
          raise InvalidRequest('insecure request: must use TLS')
  
        http_authorization = request.META.get('HTTP_AUTHORIZATION', '')
        if not http_authorization:
          raise InvalidRequest('missing HTTP_AUTHORIZATION header')
  
        try:
          auth_method, auth_value = http_authorization.strip().split(' ', 1)
        except ValueError:
          raise InvalidRequest('malformed HTTP_AUTHORIZATION header')
  
        if auth_method != 'Bearer':
          raise InvalidRequest('authentication method is not "Bearer"')
  
        # Used in the case that the request does not validate. See comment above.
        # At this point in the validation, it is certain that the Client
        # attempted to authenticate via the 'Bearer' method.
        expose_errors = True
  
        try:
          access_token = AccessToken.objects.get(value=auth_value)
        except AccessToken.DoesNotExist:
          raise InvalidToken('access token does not exist')
  
        if access_token.is_expired():
          raise InvalidToken('access token is expired')
  
        if not access_token.has_scope(*self.required_scope_names):
          raise InsufficientScope('access token has insufficient scope')
  
        return (access_token, None)
  
      except AuthenticationError as validation_error:
        return (None, (validation_error, expose_errors))