1. David Larlet
  2. django-oauth-plus
Issue #24 resolved

utils.py initialize_server_request should have an "and" instead of "or"

Atle Frenvik Sveen
created an issue

When using the django-oauth-plus on a django project with the test Client and django-rest-framework with OAuth I get an error on POST-requests with content-type application/json ("Invalid signature. [..]").

If I change the "or" between the check for content-type form-urlencoded and server name testerver to an "and" my tests pass. It seems strange to me that all POST requests that are either form-urlencoded OR to testerver should apply what I understand as a hack to deal with form-urlencoded POSTS on django testserver.

Is there some reason I don't understand why there should be an "or", or should this be changed to an "and"?

Comments (8)

  1. Atle Frenvik Sveen reporter

    Hello again!

    I started trying to write some tests to show my point, but as I dug deeper I figured that the behaviour depends on Django version.

    First things first: The case I mentioned earlier means that all POST requests passed to initialize_server_request that either has content type application/x-www-form-urlencoded OR to the server "testserver" has a special case applied, namely:

    all parameters in the request:REQUEST are gathered in the "parameters" dict, which is passed to oauth.Request.from_request.

    In my case, running Django 1.4, this means that the parameters dict looks something like:

    { u'oauth_body_hash': 'hash', u'{"data": {"foo": "bar"}': '', u'oauth_nonce': 'nonce', u'oauth_timestamp': 'timestamp', u'oauth_consumer_key': 'key', u'oauth_signature_method': 'HMAC-SHA1', u'oauth_version': '1.0', u'oauth_token': 'the_key', u'oauth_signature': 'signature' }

    (Note the second entry: a json-string as key and an empty value)

    This in turn means that the signature check fails, because the second entry, the json-string that shouldn't be there, wasn't part of the string when the client signed it.

    This means that I cannot produce a failing test using Django 1.5, because they in 1.5 changed HttpRequest (which in turn is used by WSGIRequest and RequestFactory) so that the post-data is not set when the content-type is not multipart-formencoded. The json-data is just sent in the body, as it should.

    However, my initial point still holds for django 1.4, but only because they DO put non-form-encoded data in the REQUEST. This then messes up the signature, as oauth_provider includes this in the parameters (and then leads to the signatures not matching, as described earlier)

    The main point is thus this: If you use django 1.5, this hack won't matter (at least not for json-data in the request BODY), but for the same case with Django 1.4 it does matter.

    The problem is that the hack might work for form-urlencoded data in a POST (I'm not sure, haven't tested this), but due to the fact that the if is so "broad" (by using an "or") the hack is applied to ALL post-requests made using the django-test client, instead of only those that are actually form-urlencoded.

    This latter case, which I guess the hack is in place for, is thus not the only case it applies, it also applies to json-data (which it shoudn't, at least from my understanding)

  2. Michał Jaworski

    I merged your pull request and tests actually fails for django<=1.4.

             py2.7-django1.5: commands succeeded
             py2.6-django1.5: commands succeeded
    ERROR:   py2.7-django1.4: commands failed
    ERROR:   py2.6-django1.4: commands failed
    ERROR:   py2.7-django1.3: commands failed
    ERROR:   py2.6-django1.3: commands failed
  3. Log in to comment