Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PUT Implementation Broken #70

Closed
Jberlinsky opened this issue May 9, 2011 · 4 comments
Closed

PUT Implementation Broken #70

Jberlinsky opened this issue May 9, 2011 · 4 comments

Comments

@Jberlinsky
Copy link

When signing the OAuth request, it seems that PUT requests are not properly signed. I am able to properly authenticate to any number of APIs via GET and POST, but PUT fails to authenticate properly.

This is a function of the API that I am accessing, but reproducing with the Assistly API is something like this:

PUT requests are seen as GET requests (specifically when updating an object). When the form-urlencoded header is manually added, the API sees the request as PUT, but throws a 401 Unauthorized error, indicating that the signing is incorrect, because a GET request right before that PUT with the same OAuth credentials succeeds.

@joestump
Copy link
Owner

joestump commented May 9, 2011

We use PUT in the SimpleGeo client. Works fine.
https://github.com/simplegeo/python-simplegeo/blob/master/simplegeo/storage/__init__.py#L27

Can you write a test or show some example code that exercises this issue you're experiencing?

@Jberlinsky
Copy link
Author

Working GET request:

def check_credentials(self, client_key, client_secret, subdomain):
    url = 'https://%s.assistly.com/api/v1/account/verify_credentials.json' % subdomain

    try:
        request, response = model.oauth_request(
                url=url, 
                key=client_key, 
                secret=client_secret, 
                consumer_key=self.__consumer_key, 
                consumer_secret=self.__consumer_secret, 
                http_method="GET",
                post_body="")
    except urllib2.HTTPError, e:
            return False

    if request['status'] != '200':
        raise BadCredentialsException('Invalid token or secret')

    ret_dict = simplejson.loads(response)
    return ret_dict

Working POST request:

    url = 'https://%s.assistly.com/api/v1/interactions.json' % subdomain

    data = {}
    data['customer_email'] = visitor_email
    if subject == '':
        data['interaction_subject'] = 'Interaction with %s' % visitor_email
    else:
        data['interaction_subject'] = subject
    data['interaction_body'] = description
    if visitor_name != '':
        data['customer_name'] = visitor_name

    try:
        request, response = model.oauth_request(
            url=url, 
            key=client_key, 
            secret=client_secret, 
            consumer_key=self.__consumer_key, 
            consumer_secret=self.__consumer_secret, 
            http_method="POST",
            post_body=urlencode(data))
    except urllib2.HTTPError, e:
        request = e

    if request['status'] != '200':
        raise ValueError(request)

    ret_dict = simplejson.loads(response)

    return ret_dict['results']['case']['id']

Failing PUT request with no change to headers (API receives and processes as GET):

def update_case(self, client_key, client_secret, subdomain,
        id, chat_description):

    url = 'https://%s.assistly.com/api/v1/cases/%i.json' % (subdomain, id)

    print '\033[92m', url, '\033[0m'

    data = {}
    data['description'] = chat_description

    try:
        httplib2.debuglevel = 1   
        request, response = model.oauth_request(
            url=url, 
            key=client_key, 
            secret=client_secret, 
            consumer_key=self.__consumer_key, 
            consumer_secret=self.__consumer_secret, 
            http_method='PUT',
            post_body=urlencode(data))
        print urlencode(data)
    except urllib2.HTTPError, e:
        request = e

    print request
    print type(request)
    print response

    if request['status'] != '200':
        raise ValueError(request)

    ret_dict = simplejson.loads(response)

    return ret_dict['results']['case']['description']

Failing PUT request with change to headers (API returns 401 Unauthorized):

    Changing the line in __init__.py which checks for method=="POST" to method=="POST" or method=="PUT" to inject the Content-Type header results in a 401.

@Jberlinsky
Copy link
Author

Sorry, forgot about the calling method...

def oauth_request(url, key, secret, consumer_key, consumer_secret, http_method="GET", post_body=None, http_headers=None):
    consumer = oauth.Consumer(key=consumer_key, secret=consumer_secret)
    token = oauth.Token(key=key, secret=secret)
    client = oauth.Client(consumer, token)
    resp, content = client.request(
        url,
        method=http_method,
        body=post_body,
        headers=http_headers)
    return resp, content

Jberlinsky pushed a commit to Jberlinsky/python-oauth2 that referenced this issue May 10, 2011
Jberlinsky pushed a commit to Jberlinsky/python-oauth2 that referenced this issue May 10, 2011
@Jberlinsky
Copy link
Author

With the assistance of Joslyn Esser at Assistly, I have tracked down the issue and submitted a pull request (issue #71).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants