remove readme from the non-solutions
[twitter-api-cdsw-solutions] / oauthlib / oauth1 / rfc5849 / endpoints / signature_only.py
1 # -*- coding: utf-8 -*-
2 """
3 oauthlib.oauth1.rfc5849.endpoints.signature_only
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 This module is an implementation of the signing logic of OAuth 1.0 RFC 5849.
7 """
8
9 from __future__ import absolute_import, unicode_literals
10
11 import logging
12
13 from .base import BaseEndpoint
14 from .. import errors
15
16 log = logging.getLogger(__name__)
17
18
19 class SignatureOnlyEndpoint(BaseEndpoint):
20
21     """An endpoint only responsible for verifying an oauth signature."""
22
23     def validate_request(self, uri, http_method='GET',
24                          body=None, headers=None):
25         """Validate a signed OAuth request.
26
27         :param uri: The full URI of the token request.
28         :param http_method: A valid HTTP verb, i.e. GET, POST, PUT, HEAD, etc.
29         :param body: The request body as a string.
30         :param headers: The request headers as a dict.
31         :returns: A tuple of 2 elements.
32                   1. True if valid, False otherwise.
33                   2. An oauthlib.common.Request object.
34         """
35         try:
36             request = self._create_request(uri, http_method, body, headers)
37         except errors.OAuth1Error:
38             return False, None
39
40         try:
41             self._check_transport_security(request)
42             self._check_mandatory_parameters(request)
43         except errors.OAuth1Error:
44             return False, request
45
46         if not self.request_validator.validate_timestamp_and_nonce(
47                 request.client_key, request.timestamp, request.nonce, request):
48             return False, request
49
50         # The server SHOULD return a 401 (Unauthorized) status code when
51         # receiving a request with invalid client credentials.
52         # Note: This is postponed in order to avoid timing attacks, instead
53         # a dummy client is assigned and used to maintain near constant
54         # time request verification.
55         #
56         # Note that early exit would enable client enumeration
57         valid_client = self.request_validator.validate_client_key(
58             request.client_key, request)
59         if not valid_client:
60             request.client_key = self.request_validator.dummy_client
61
62         valid_signature = self._check_signature(request)
63
64         # We delay checking validity until the very end, using dummy values for
65         # calculations and fetching secrets/keys to ensure the flow of every
66         # request remains almost identical regardless of whether valid values
67         # have been supplied. This ensures near constant time execution and
68         # prevents malicious users from guessing sensitive information
69         v = all((valid_client, valid_signature))
70         if not v:
71             log.info("[Failure] request verification failed.")
72             log.info("Valid client: %s", valid_client)
73             log.info("Valid signature: %s", valid_signature)
74         return v, request

Benjamin Mako Hill || Want to submit a patch?