Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/oauthlib/oauth1/rfc5849/endpoints/signature_only.py: 21%
33 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:22 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:22 +0000
1# -*- coding: utf-8 -*-
2"""
3oauthlib.oauth1.rfc5849.endpoints.signature_only
4~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6This module is an implementation of the signing logic of OAuth 1.0 RFC 5849.
7"""
9import logging
11from .. import errors
12from .base import BaseEndpoint
14log = logging.getLogger(__name__)
17class SignatureOnlyEndpoint(BaseEndpoint):
19 """An endpoint only responsible for verifying an oauth signature."""
21 def validate_request(self, uri, http_method='GET',
22 body=None, headers=None):
23 """Validate a signed OAuth request.
25 :param uri: The full URI of the token request.
26 :param http_method: A valid HTTP verb, i.e. GET, POST, PUT, HEAD, etc.
27 :param body: The request body as a string.
28 :param headers: The request headers as a dict.
29 :returns: A tuple of 2 elements.
30 1. True if valid, False otherwise.
31 2. An oauthlib.common.Request object.
32 """
33 try:
34 request = self._create_request(uri, http_method, body, headers)
35 except errors.OAuth1Error as err:
36 log.info(
37 'Exception caught while validating request, %s.' % err)
38 return False, None
40 try:
41 self._check_transport_security(request)
42 self._check_mandatory_parameters(request)
43 except errors.OAuth1Error as err:
44 log.info(
45 'Exception caught while validating request, %s.' % err)
46 return False, request
48 if not self.request_validator.validate_timestamp_and_nonce(
49 request.client_key, request.timestamp, request.nonce, request):
50 log.debug('[Failure] verification failed: timestamp/nonce')
51 return False, request
53 # The server SHOULD return a 401 (Unauthorized) status code when
54 # receiving a request with invalid client credentials.
55 # Note: This is postponed in order to avoid timing attacks, instead
56 # a dummy client is assigned and used to maintain near constant
57 # time request verification.
58 #
59 # Note that early exit would enable client enumeration
60 valid_client = self.request_validator.validate_client_key(
61 request.client_key, request)
62 if not valid_client:
63 request.client_key = self.request_validator.dummy_client
65 valid_signature = self._check_signature(request)
67 # log the results to the validator_log
68 # this lets us handle internal reporting and analysis
69 request.validator_log['client'] = valid_client
70 request.validator_log['signature'] = valid_signature
72 # We delay checking validity until the very end, using dummy values for
73 # calculations and fetching secrets/keys to ensure the flow of every
74 # request remains almost identical regardless of whether valid values
75 # have been supplied. This ensures near constant time execution and
76 # prevents malicious users from guessing sensitive information
77 v = all((valid_client, valid_signature))
78 if not v:
79 log.info("[Failure] request verification failed.")
80 log.info("Valid client: %s", valid_client)
81 log.info("Valid signature: %s", valid_signature)
82 return v, request