File: base_server.py

package info (click to toggle)
python-authlib 1.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,016 kB
  • sloc: python: 26,998; makefile: 53; sh: 14
file content (115 lines) | stat: -rw-r--r-- 3,972 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import time

from .errors import InvalidNonceError
from .errors import InvalidRequestError
from .errors import InvalidSignatureError
from .errors import MissingRequiredParameterError
from .errors import UnsupportedSignatureMethodError
from .signature import SIGNATURE_HMAC_SHA1
from .signature import SIGNATURE_PLAINTEXT
from .signature import SIGNATURE_RSA_SHA1
from .signature import verify_hmac_sha1
from .signature import verify_plaintext
from .signature import verify_rsa_sha1


class BaseServer:
    SIGNATURE_METHODS = {
        SIGNATURE_HMAC_SHA1: verify_hmac_sha1,
        SIGNATURE_RSA_SHA1: verify_rsa_sha1,
        SIGNATURE_PLAINTEXT: verify_plaintext,
    }
    SUPPORTED_SIGNATURE_METHODS = [SIGNATURE_HMAC_SHA1]
    EXPIRY_TIME = 300

    @classmethod
    def register_signature_method(cls, name, verify):
        """Extend signature method verification.

        :param name: A string to represent signature method.
        :param verify: A function to verify signature.

        The ``verify`` method accept ``OAuth1Request`` as parameter::

            def verify_custom_method(request):
                # verify this request, return True or False
                return True


            Server.register_signature_method("custom-name", verify_custom_method)
        """
        cls.SIGNATURE_METHODS[name] = verify

    def validate_timestamp_and_nonce(self, request):
        """Validate ``oauth_timestamp`` and ``oauth_nonce`` in HTTP request.

        :param request: OAuth1Request instance
        """
        timestamp = request.oauth_params.get("oauth_timestamp")
        nonce = request.oauth_params.get("oauth_nonce")

        if request.signature_method == SIGNATURE_PLAINTEXT:
            # The parameters MAY be omitted when using the "PLAINTEXT"
            # signature method
            if not timestamp and not nonce:
                return

        if not timestamp:
            raise MissingRequiredParameterError("oauth_timestamp")

        try:
            # The timestamp value MUST be a positive integer
            timestamp = int(timestamp)
            if timestamp < 0:
                raise InvalidRequestError('Invalid "oauth_timestamp" value')

            if self.EXPIRY_TIME and time.time() - timestamp > self.EXPIRY_TIME:
                raise InvalidRequestError('Invalid "oauth_timestamp" value')
        except (ValueError, TypeError) as exc:
            raise InvalidRequestError('Invalid "oauth_timestamp" value') from exc

        if not nonce:
            raise MissingRequiredParameterError("oauth_nonce")

        if self.exists_nonce(nonce, request):
            raise InvalidNonceError()

    def validate_oauth_signature(self, request):
        """Validate ``oauth_signature`` from HTTP request.

        :param request: OAuth1Request instance
        """
        method = request.signature_method
        if not method:
            raise MissingRequiredParameterError("oauth_signature_method")

        if method not in self.SUPPORTED_SIGNATURE_METHODS:
            raise UnsupportedSignatureMethodError()

        if not request.signature:
            raise MissingRequiredParameterError("oauth_signature")

        verify = self.SIGNATURE_METHODS.get(method)
        if not verify:
            raise UnsupportedSignatureMethodError()

        if not verify(request):
            raise InvalidSignatureError()

    def get_client_by_id(self, client_id):
        """Get client instance with the given ``client_id``.

        :param client_id: A string of client_id
        :return: Client instance
        """
        raise NotImplementedError()

    def exists_nonce(self, nonce, request):
        """The nonce value MUST be unique across all requests with the same
        timestamp, client credentials, and token combinations.

        :param nonce: A string value of ``oauth_nonce``
        :param request: OAuth1Request instance
        :return: Boolean
        """
        raise NotImplementedError()