summaryrefslogtreecommitdiff
path: root/oauthlib/oauth1
diff options
context:
space:
mode:
Diffstat (limited to 'oauthlib/oauth1')
-rw-r--r--oauthlib/oauth1/rfc5849/__init__.py46
-rw-r--r--oauthlib/oauth1/rfc5849/parameters.py47
-rw-r--r--oauthlib/oauth1/rfc5849/signature.py13
3 files changed, 63 insertions, 43 deletions
diff --git a/oauthlib/oauth1/rfc5849/__init__.py b/oauthlib/oauth1/rfc5849/__init__.py
index 7744a48..4fb4a49 100644
--- a/oauthlib/oauth1/rfc5849/__init__.py
+++ b/oauthlib/oauth1/rfc5849/__init__.py
@@ -96,13 +96,11 @@ class Client(object):
def _render(self, request, formencode=False):
"""Render a signed request according to signature type
- Returns a 3-tuple containing the request URI, headers, and body.
+ Returns a rendered Request instance.
If the formencode argument is True and the body contains parameters, it
is escaped and returned as a valid formencoded string.
"""
- # TODO what if there are body params on a header-type auth?
- # TODO what if there are query params on a body-type auth?
return parameters.prepare_request(request, self.signature_type)
def sign(self, uri, http_method=u'GET', body=None, headers=None):
@@ -190,29 +188,6 @@ class Server(object):
def get_resource_owner_secret(self, resource_owner_key):
raise NotImplementedError("Subclasses must implement this function.")
- def get_signature_type_and_params(self, uri_query, headers, body):
- signature_types_with_oauth_params = filter(lambda s: s[1], (
- (constants.SIGNATURE_TYPE_AUTH_HEADER, utils.filter_oauth_params(
- signature.collect_parameters(headers=headers,
- exclude_oauth_signature=False))),
- (constants.SIGNATURE_TYPE_BODY, utils.filter_oauth_params(
- signature.collect_parameters(body=body,
- exclude_oauth_signature=False))),
- (constants.SIGNATURE_TYPE_QUERY, utils.filter_oauth_params(
- signature.collect_parameters(uri_query=uri_query,
- exclude_oauth_signature=False))),
- ))
-
- if len(signature_types_with_oauth_params) > 1:
- raise ValueError('oauth_ params must come from only 1 signature type but were found in %s' % ', '.join(
- [s[0] for s in signature_types_with_oauth_params]))
- try:
- signature_type, params = signature_types_with_oauth_params[0]
- except IndexError:
- raise ValueError('oauth_ params are missing. Could not determine signature type.')
-
- return signature_type, dict(params)
-
def check_client_key(self, client_key):
raise NotImplementedError("Subclasses must implement this function.")
@@ -234,13 +209,11 @@ class Server(object):
.. _`section 3.2`: http://tools.ietf.org/html/rfc5849#section-3.2
"""
- headers = headers or {}
- signature_type = None
- # FIXME: urlparse does not return unicode!
- uri_query = urlparse.urlparse(uri).query
-
- signature_type, params = self.get_signature_type_and_params(uri_query,
- headers, body)
+ request = Request(uri, http_method=http_method, body=body,
+ headers=headers)
+ signature_type = parameters.get_signature_type(request)
+ params = signature.collect_parameters(request,
+ exclude_oauth_signature=False)
# the parameters may not include duplicate oauth entries
filtered_params = utils.filter_oauth_params(params)
@@ -307,10 +280,11 @@ class Server(object):
signature_type=signature_type,
verifier=verifier)
- request = Request(uri, http_method, body, headers)
- request.oauth_params = params
+ new_request = request.clone()
+ new_request.oauth_params = params.items()
- client_signature = oauth_client.get_oauth_signature(request)
+ client_signature = oauth_client.get_oauth_signature(new_request)
# FIXME: use near constant time string compare to avoid timing attacks
return client_signature == request_signature
+
diff --git a/oauthlib/oauth1/rfc5849/parameters.py b/oauthlib/oauth1/rfc5849/parameters.py
index 315cccf..b0e6459 100644
--- a/oauthlib/oauth1/rfc5849/parameters.py
+++ b/oauthlib/oauth1/rfc5849/parameters.py
@@ -14,6 +14,53 @@ from urlparse import urlparse, urlunparse
from . import constants, utils
from oauthlib.common import extract_params, urlencode
+def get_signature_type(request):
+ """**Determine the signature type of a request**
+ Per `section 3.5`_ of the spec.
+
+ .. _`section 3.5`: http://tools.ietf.org/html/rfc5849#section-3.5
+ """
+ signature_types = []
+
+ # When making an OAuth-authenticated request, protocol parameters as
+ # well as any other parameter using the "oauth_" prefix SHALL be
+ # included in the request using one and only one of the following
+ # locations, listed in order of decreasing preference:
+
+ # 1. The HTTP "Authorization" header field as described in
+ # `Section 3.5.1`_.
+ #
+ # .. _`Section 3.5.1`: http://tools.ietf.org/html/rfc5849#section-3.5.1
+ if request.headers:
+ headers_lower = dict(
+ (k.lower(), v) for k, v in request.headers.items())
+ authorization_header = headers_lower.get(u'authorization')
+ if authorization_header is not None:
+ header_oauth_params = utils.filter_oauth_params(
+ utils.parse_authorization_header(authorization_header))
+ if header_oauth_params:
+ signature_types.append(constants.SIGNATURE_TYPE_AUTH_HEADER)
+
+ # 2. The HTTP request entity-body as described in `Section 3.5.2`_.
+ #
+ # .. _`Section 3.5.2`: http://tools.ietf.org/html/rfc5849#section-3.5.2
+ if utils.filter_oauth_params(extract_params(request.body) or []):
+ signature_types.append(constants.SIGNATURE_TYPE_BODY)
+
+ # 3. The HTTP request URI query as described in `Section 3.5.3`_.
+ #
+ # .. _`Section 3.5.3`: http://tools.ietf.org/html/rfc5849#section-3.5.3
+ if utils.filter_oauth_params(request.uri_query_params):
+ signature_types.append(constants.SIGNATURE_TYPE_QUERY)
+
+ if len(signature_types) > 1:
+ raise ValueError('oauth_ params must come from only 1 signature type but were found in %s' % ', '.join(
+ signature_types))
+ try:
+ return signature_types[0]
+ except IndexError:
+ raise ValueError('oauth_ params are missing. Could not determine signature type.')
+
def prepare_headers(request, realm=None):
"""**Prepare the Authorization header.**
diff --git a/oauthlib/oauth1/rfc5849/signature.py b/oauthlib/oauth1/rfc5849/signature.py
index 99101d4..edd553b 100644
--- a/oauthlib/oauth1/rfc5849/signature.py
+++ b/oauthlib/oauth1/rfc5849/signature.py
@@ -167,8 +167,7 @@ def normalize_base_string_uri(uri):
#
# .. _`section 3.4.1.3`: http://tools.ietf.org/html/rfc5849#section-3.4.1.3
-def collect_parameters(uri_query='', body=[], headers=None,
- exclude_oauth_signature=True):
+def collect_parameters(request, exclude_oauth_signature=True):
"""**Parameter Sources**
Parameters starting with `oauth_` will be unescaped.
@@ -226,7 +225,7 @@ def collect_parameters(uri_query='', body=[], headers=None,
.. _`section 3.4.1.3.1`: http://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
"""
- headers = headers or {}
+ headers = request.headers or {}
params = []
# The parameters from the following sources are collected into a single
@@ -240,9 +239,9 @@ def collect_parameters(uri_query='', body=[], headers=None,
# `W3C.REC-html40-19980424`_, Section 17.13.4.
#
# .. _`RFC3986, Section 3.4`: http://tools.ietf.org/html/rfc3986#section-3.4
- # .. _`W3C.REC-html40-19980424`: http://tools.ietf.org/html/rfc5849#ref-W3C.REC-html40-19980424
- if uri_query:
- params.extend(urlparse.parse_qsl(uri_query, keep_blank_values=True))
+ # .. _`W3C.REC-html40-19i980424`: http://tools.ietf.org/html/rfc5849#ref-W3C.REC-html40-19980424
+ if request.uri_query:
+ params.extend(urlparse.parse_qsl(request.uri_query, keep_blank_values=True))
# * The OAuth HTTP "Authorization" header field (`Section 3.5.1`_) if
# present. The header's content is parsed into a list of name/value
@@ -271,7 +270,7 @@ def collect_parameters(uri_query='', body=[], headers=None,
# .._`W3C.REC-html40-19980424`: http://tools.ietf.org/html/rfc5849#ref-W3C.REC-html40-19980424
# TODO: enforce header param inclusion conditions
- bodyparams = extract_params(body) or []
+ bodyparams = extract_params(request.body) or []
params.extend(bodyparams)
# ensure all oauth params are unescaped