Search code examples
pythonyelpoauth-1.0a

Yelp API Produces Invalid Signature Error


After looking at several articles online, StackOverflow, and the Yelp Google Group, I've been unable to figure out the problem to an Invalid Signature error being produced from my Yelp API request.

Here is the exact error:

{'error': {'text': 'Signature was invalid', 'description': 'Invalid signature. Expected signature base string: [some text here with keys]}}

And the code I've written to go along with it:

import rauth
import time

def get_results():

    #Obtain these from Yelp's manage access page
    consumer_key = ''
    consumer_secret = ''
    token = ''
    token_secret = ''

    session = rauth.OAuth1Session(
            consumer_key = consumer_key
            ,consumer_secret = consumer_secret
            ,access_token = token
            ,access_token_secret = token_secret)

    request = session.get("http://api.yelp.com/v2/search?location=Boston&term=food")

    #Transforms the JSON API response into a Python dictionary
    data = request.json()
    print(data)
    session.close()

    return data

if __name__=="__main__":
    print(get_results())

So what exactly is causing this error? I've done some modifications prior to this attempt, and the previous attempts I made I got similar errors; except one time I only got a "Invalid Signature" error, with no "Expect signature base string" message


Solution

  • There are more steps to authentication as per the docs

    Making a Request

    Each request must contain the following OAuth protocol parameters:

    OAuth Parameter Value
    oauth_consumer_key  Your OAuth consumer key (from Manage API Access).
    oauth_token The access token obtained (from Manage API Access).
    oauth_signature_method  hmac-sha1
    oauth_signature The generated request signature, signed with the oauth_token_secret obtained (from Manage API Access).
    oauth_timestamp Timestamp for the request in seconds since the Unix epoch.
    oauth_nonce A unique string randomly generated per request.
    

    These parameters may be passed in the HTTP (Authorization) header as URL query keys or in the POST data. Generating the OAuth signature is done by applying the HMAC-SHA1 with the oauth_token_secret. You may view your OAuth consumer key at Manage API Access. OAuth libraries are available to generate these requests.

    You are not passing oauth_timestamp which is required or applying the HMAC-SHA1 so you get an Invalid Signature error, it is clearly outlined in the docs above what you need to send.

    There is also an actual python yelp api you could use but to make a request you can use the example below based on the request function from the example code: to make a request using oauth2 and requests:

    import requests
    import oauth2
    
    def request(url, url_params=None):
        consumer_key = ""
        consumer_secret = ""
        token = ""
        token_secret =""
        url_params = url_params or {}
        consumer = oauth2.Consumer(consumer_key, consumer_secret)
        oauth_request = oauth2.Request(method="GET", url=url, parameters=url_params)
    
        oauth_request.update(
            {
                'oauth_nonce': oauth2.generate_nonce(),
                'oauth_timestamp': oauth2.generate_timestamp(),
                'oauth_token': token,
                'oauth_consumer_key': consumer_key
            }
        )
        token = oauth2.Token(token, token_secret)
        oauth_request.sign_request(oauth2.SignatureMethod_HMAC_SHA1(), consumer, token)
        signed_url = oauth_request.to_url()
    
        print(u'Querying {0} ...'.format(url))
    
        return requests.get(signed_url).json()
    

    Which using your url outputs a whole load of json, the start of which is:

    Querying http://api.yelp.com/v2/search?location=Boston&term=food ...
    {'region': {'center': {'longitude': -71.05460875, 'latitude': 42.35028894954365}, 'span': {'latitude_delta': 0.0325510910039668, 'longitude_delta': 0.04668455000000904}}, 'total': 8351, 'businesses': [{'name': "Giacomo's Ristorante", 'url': 'http://www.yelp.com/biz/giacomos-ristorante-boston', 'mobile_url': 'http://m.yelp.com/biz/giacomos-ristorante-boston', 'rating_img_url_large': 'http://s3-media2.fl.yelpcdn.com/assets/2/www/img/ccf2b76faa2c/ico/stars/v1/stars_large_4.png', 'phone': 
    ...............................................................
    ...............................................................
    

    I am not sure if the api supports python 3 but the code above was tested with python3 and python2 and it works fine, to install oauth2 you can simple pip install oauth2 and the same with requests if you don't have it installed.