summaryrefslogtreecommitdiffhomepage
path: root/libs/oauthlib/oauth1/rfc5849/parameters.py
blob: 2f068a7c7860f21bce2536b417dfa12726dfa536 (plain)
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# -*- coding: utf-8 -*-
"""
oauthlib.parameters
~~~~~~~~~~~~~~~~~~~

This module contains methods related to `section 3.5`_ of the OAuth 1.0a spec.

.. _`section 3.5`: https://tools.ietf.org/html/rfc5849#section-3.5
"""
from __future__ import absolute_import, unicode_literals

from oauthlib.common import extract_params, urlencode

from . import utils

try:
    from urlparse import urlparse, urlunparse
except ImportError:
    from urllib.parse import urlparse, urlunparse


# TODO: do we need filter_params now that oauth_params are handled by Request?
#       We can easily pass in just oauth protocol params.
@utils.filter_params
def prepare_headers(oauth_params, headers=None, realm=None):
    """**Prepare the Authorization header.**
    Per `section 3.5.1`_ of the spec.

    Protocol parameters can be transmitted using the HTTP "Authorization"
    header field as defined by `RFC2617`_ with the auth-scheme name set to
    "OAuth" (case insensitive).

    For example::

        Authorization: OAuth realm="Example",
            oauth_consumer_key="0685bd9184jfhq22",
            oauth_token="ad180jjd733klru7",
            oauth_signature_method="HMAC-SHA1",
            oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
            oauth_timestamp="137131200",
            oauth_nonce="4572616e48616d6d65724c61686176",
            oauth_version="1.0"


    .. _`section 3.5.1`: https://tools.ietf.org/html/rfc5849#section-3.5.1
    .. _`RFC2617`: https://tools.ietf.org/html/rfc2617
    """
    headers = headers or {}

    # Protocol parameters SHALL be included in the "Authorization" header
    # field as follows:
    authorization_header_parameters_parts = []
    for oauth_parameter_name, value in oauth_params:
        # 1.  Parameter names and values are encoded per Parameter Encoding
        #     (`Section 3.6`_)
        #
        # .. _`Section 3.6`: https://tools.ietf.org/html/rfc5849#section-3.6
        escaped_name = utils.escape(oauth_parameter_name)
        escaped_value = utils.escape(value)

        # 2.  Each parameter's name is immediately followed by an "=" character
        #     (ASCII code 61), a """ character (ASCII code 34), the parameter
        #     value (MAY be empty), and another """ character (ASCII code 34).
        part = '{0}="{1}"'.format(escaped_name, escaped_value)

        authorization_header_parameters_parts.append(part)

    # 3.  Parameters are separated by a "," character (ASCII code 44) and
    #     OPTIONAL linear whitespace per `RFC2617`_.
    #
    # .. _`RFC2617`: https://tools.ietf.org/html/rfc2617
    authorization_header_parameters = ', '.join(
        authorization_header_parameters_parts)

    # 4.  The OPTIONAL "realm" parameter MAY be added and interpreted per
    #     `RFC2617 section 1.2`_.
    #
    # .. _`RFC2617 section 1.2`: https://tools.ietf.org/html/rfc2617#section-1.2
    if realm:
        # NOTE: realm should *not* be escaped
        authorization_header_parameters = ('realm="%s", ' % realm +
                                           authorization_header_parameters)

    # the auth-scheme name set to "OAuth" (case insensitive).
    authorization_header = 'OAuth %s' % authorization_header_parameters

    # contribute the Authorization header to the given headers
    full_headers = {}
    full_headers.update(headers)
    full_headers['Authorization'] = authorization_header
    return full_headers


def _append_params(oauth_params, params):
    """Append OAuth params to an existing set of parameters.

    Both params and oauth_params is must be lists of 2-tuples.

    Per `section 3.5.2`_ and `3.5.3`_ of the spec.

    .. _`section 3.5.2`: https://tools.ietf.org/html/rfc5849#section-3.5.2
    .. _`3.5.3`: https://tools.ietf.org/html/rfc5849#section-3.5.3

    """
    merged = list(params)
    merged.extend(oauth_params)
    # The request URI / entity-body MAY include other request-specific
    # parameters, in which case, the protocol parameters SHOULD be appended
    # following the request-specific parameters, properly separated by an "&"
    # character (ASCII code 38)
    merged.sort(key=lambda i: i[0].startswith('oauth_'))
    return merged


def prepare_form_encoded_body(oauth_params, body):
    """Prepare the Form-Encoded Body.

    Per `section 3.5.2`_ of the spec.

    .. _`section 3.5.2`: https://tools.ietf.org/html/rfc5849#section-3.5.2

    """
    # append OAuth params to the existing body
    return _append_params(oauth_params, body)


def prepare_request_uri_query(oauth_params, uri):
    """Prepare the Request URI Query.

    Per `section 3.5.3`_ of the spec.

    .. _`section 3.5.3`: https://tools.ietf.org/html/rfc5849#section-3.5.3

    """
    # append OAuth params to the existing set of query components
    sch, net, path, par, query, fra = urlparse(uri)
    query = urlencode(
        _append_params(oauth_params, extract_params(query) or []))
    return urlunparse((sch, net, path, par, query, fra))