def parse_authorization_header(header_value, param_delimiter=',', strict=True): """ Parses the OAuth Authorization header. :: 'OAuth realm="example.com",oauth_nonce="123456789",..." -> ({"oauth_nonce": ["123456789"], ...}, "example.com") :see: Authorization Header http://tools.ietf.org/html/rfc5849#section-3.5.1 :param header_value: Header value. :param param_delimiter: The delimiter used to separate header value parameters. According to the Specification, this must be a comma ",". However, certain services like Yahoo! use "&" instead. Comma is default. If you want to use another delimiter character, the ``strict`` argument to this function must also be set to ``False``. See https://github.com/oauth/oauth-ruby/pull/12 :param strict: When ``True``, more strict checking will be performed. The authorization header value must be on a single line. The param delimiter MUST be a comma. When ``False``, the parser is a bit lenient. :returns: A tuple of (Dictionary of parameter name value pairs, realm). realm will be ``None`` if the authorization header does not have a ``realm`` parameter. """ header_value = utf8_decode_if_bytes(header_value) realm = None params = {} for name, value \ in _parse_authorization_header_l(header_value, param_delimiter=param_delimiter, strict=strict): # We do keep track of multiple values because they will be # detected by the sanitization below and flagged as an error # in the Authorization header value. # #params[name] = [value] if not name == OAUTH_PARAM_REALM: # The ``realm`` parameter is not included into the protocol # parameters list. if name in params: params[name].append(value) else: params[name] = [value] else: realm = value # Sanitize and check parameters. Raises an error if # multiple values are found. Should help with debugging # clients. params = request_query_remove_non_oauth(params) return params, realm
def _generate_oauth_params(cls, oauth_consumer_key, oauth_signature_method, oauth_version, oauth_nonce, oauth_timestamp, oauth_token, **extra_oauth_params): """ Generates properly formatted ``oauth_params`` dictionary for use with an OAuth request. :param oauth_consumer_key: Your OAuth consumer key (client identifier). :param oauth_signature_method: The signature method to use. :param oauth_version: The version of OAuth to be used. "1.0" for standards-compliant. :param oauth_nonce: A unique randomly generated nonce value. :param oauth_timestamp: A unique timestamp since epoch. :param oauth_token: A response oauth_token if obtained from the OAuth server. :returns: A dictionary of protocol parameters. """ if oauth_signature_method not in SIGNATURE_METHOD_MAP: raise InvalidSignatureMethodError( "Invalid signature method specified: %r" % \ oauth_signature_method ) # Reserved OAuth parameters. oauth_params = dict( oauth_consumer_key=oauth_consumer_key, oauth_signature_method=oauth_signature_method, oauth_timestamp=oauth_timestamp, oauth_nonce=oauth_nonce, ) # If we have an oauth token. if oauth_token: oauth_params[OAUTH_PARAM_TOKEN] = oauth_token # If we have a version. if oauth_version: oauth_params[OAUTH_PARAM_VERSION] = oauth_version # Clean up oauth parameters in the arguments. extra_oauth_params = request_query_remove_non_oauth(extra_oauth_params) for k, v in extra_oauth_params.items(): if k == OAUTH_PARAM_SIGNATURE: raise IllegalArgumentError("Cannot override system-generated "\ "protocol parameter: %r" % k) else: oauth_params[k] = v[0] return oauth_params
def test_filter(self): params = { "a2": ["r b"], "b5": ["=%3D"], "a3": ["a", "2 q"], "c@": [""], "c2": [""], OAUTH_PARAM_CONSUMER_KEY: ["9djdj82h48djs9d2"], OAUTH_PARAM_TOKEN: ["kkk9d7dh3k39sjv7"], OAUTH_PARAM_SIGNATURE_METHOD: ["HMAC-SHA1"], OAUTH_PARAM_TIMESTAMP: ["137131201"], OAUTH_PARAM_NONCE: ["7d8f3e4a"], } query_string = """\ ?a2=r%20b\ &a3=2%20q\ &a3=a\ &b5=%3D%253D\ &c%40=\ &c2=\ &oauth_consumer_key=9djdj82h48djs9d2\ &oauth_nonce=7d8f3e4a\ &oauth_signature_method=HMAC-SHA1\ &oauth_timestamp=137131201\ &oauth_token=kkk9d7dh3k39sjv7""" expected_params = { OAUTH_PARAM_CONSUMER_KEY: ["9djdj82h48djs9d2"], OAUTH_PARAM_TOKEN: ["kkk9d7dh3k39sjv7"], OAUTH_PARAM_SIGNATURE_METHOD: ["HMAC-SHA1"], OAUTH_PARAM_TIMESTAMP: ["137131201"], OAUTH_PARAM_NONCE: ["7d8f3e4a"], } expected_result = urlencode_s(expected_params) self.assertEqual(urlencode_s(request_query_remove_non_oauth(params)), expected_result) self.assertEqual( urlencode_s(request_query_remove_non_oauth(query_string)), expected_result)
def generate_authorization_header(oauth_params, realm=None, param_delimiter=","): """ Builds the Authorization header value. Please note that the generated authorization header value will be on a single line. :: {"oauth_b": "http://example.com/c", ...}, "example foo" -> 'OAuth realm="example foo",oauth_b="http%3A%2F%2Fexample.com%2Fc"...' :see: Authorization Header http://tools.ietf.org/html/rfc5849#section-3.5.1 :param oauth_params: Protocol-specific parameters excluding the ``realm`` parameter. :param realm: If specified, the realm is included into the Authorization header. The realm is never percent-encoded according to the OAuth spec. :param param_delimiter: The delimiter used to separate header value parameters. According to the Specification, this must be a comma ",". However, certain services like Yahoo! use "&" instead. Comma is default. See https://github.com/oauth/oauth-ruby/pull/12 :returns: A properly formatted Authorization header value. """ param_delimiter = utf8_encode_if_unicode(param_delimiter) if realm: value = b('OAuth realm="') + utf8_encode_if_unicode(realm) + \ SYMBOL_INVERTED_DOUBLE_QUOTE + param_delimiter else: value = b("OAuth ") oauth_params = request_query_remove_non_oauth(oauth_params) normalized_param_pairs = urlencode_sl(oauth_params) value += param_delimiter.join([k + SYMBOL_EQUAL + SYMBOL_INVERTED_DOUBLE_QUOTE + v + SYMBOL_INVERTED_DOUBLE_QUOTE for k, v in normalized_param_pairs]) return value
def generate_base_string_query(url_query, oauth_params): """ Serializes URL query parameters and OAuth protocol parameters into a valid OAuth base string URI query string. :see: Parameter Normalization (http://tools.ietf.org/html/rfc5849#section-3.4.1.3.2) :param url_query: A dictionary or string of URL query parameters. Any parameters starting with ``oauth_`` will be ignored. :param oauth_params: A dictionary or string of protocol-specific query parameters. Any parameter names that do not begin with ``oauth_`` will be excluded from the normalized query string. ``oauth_signature``, ``oauth_consumer_secret``, and ``oauth_token_secret`` are also specifically excluded. :returns: Normalized string of query parameters. """ url_query = query_remove_oauth(url_query) oauth_params = request_query_remove_non_oauth(oauth_params) query_d = {} query_d.update(url_query) query_d.update(oauth_params) # Now encode the parameters, while ignoring 'oauth_signature' and obviously, # the secrets from the entire list of parameters. def allow_func(name, _): """Allows only protocol parameters that must be included into the signature. :param name: The name of the parameter. :returns: ``True`` if the parameter can be included; ``False`` otherwise. """ return name not in (OAUTH_PARAM_SIGNATURE, #OAUTH_PARAM_CONSUMER_SECRET, # Sanitized above. #OAUTH_PARAM_TOKEN_SECRET, # Sanitized above. ) query = urlencode_s(query_d, allow_func) return query