Example #1
0
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
Example #2
0
    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
Example #3
0
    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)
Example #4
0
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
Example #5
0
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