Python Authentication Errors

Discussion in 'Shapeways API' started by 469069_deleted, Feb 7, 2016.

  1. I just installed the Shapeways API for Python using "pip install shapeways" and then building the docs. When I try to run the application, after updating the example with my user id and password, I get the following error:

    {"reason": "Authentication Error", "result": "failure", "oauth_error_message": " oauth_problem=parameter_absent&oauth_parameters_absent=o auth_token "}

    What gives?
     
  2. Message is asking for an oauth_token so I gave it one. The example clearly did not have one but hey. So I add the oauth_token and oauth_secret using my Shapeways account name and password (not being sure what else to use). Now the error message is:

    {"reason": "Authentication Error", "result": "failure", "oauth_error_message": "oauth_problem=token_rejected"}

    Thanks in advance,
    Will
     
  3. stonysmith
    stonysmith Well-Known Member Moderator
    Which library are you using? If you are using the code that I uploaded, I'm not sure that I got everything in there to allow pip to install it "right".

    Your token(s) need to be generated. They will look something like this:
    client_key=u'9aad5bd0e989dbd7a785f14ab9ab822935fb007c'
    client_secret=u'70cfc456a15beaf4b9a7be9be22e79c11008342f'
    resource_owner_token=u'06af2b8daaeb98a4e4e45bab4dad004e7f621 4c7'
    resource_owner_secret=u'4b30000ac21911ab9cbd865402f32fd638e4 13d7'

    Did you follow the steps in the file "Directions.txt"?
     
  4. Can you please point me to your upload as I am not finding directions.txt on what I have found to date!

    Tx/Will
     
  5. stonysmith
    stonysmith Well-Known Member Moderator
  6. Thanks thanks thanks. Not working yet but at least I have a directions.txt with a step that gets me Oauth keys! Not sure why I had not found that post as that is what I was searching for!
     
  7. Unfortunately ... I am back as I am still getting an authorization error. I ran GetKeys and it completed nicely after updating the lower part of the keys file. However, when I run the program to list models it failed (with the print statement uncommented):

    Code:
    u'reason': u'Authentication Error', u'result': u'failure', u'oauth_error_message': u'oauth_problem=signature_invalid&debug_sbs=GET&http%3A%2F%2Fapi.shapeways.com%2Fmodel%2Fv1&oauth_consumer_key%xxxx%26oauth_nonce%xxxx%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1454880344%26oauth_token%xxxx%26oauth_version%3D1.0%26page%3D1'}
    Traceback (most recent call last):
      File "GetListOfModels.py", line 25, in <module>
        q=t["models"]
    KeyError: 'models'
     
  8. Just occurred to me...I am running from my workstation not from the URL that is registered under Shapeways for my application. Does this matter? I am not, nor want to be, an expert in Oauth I just want to write some upload logic and this is frustrating!

    Thanks,
    Will
     
  9. I never did get a command line script to work for the bulk upload but I did go back to the stock example and made it work. Here it is. Please note the comments...particularly the ones about this being a work in progress, not meant to be an example of good techniques, etc, etc, etc. Hopefully someone will find this to be a useful reference as I had a hard time finding a good example to draw on!

    Code:
    # ******************************************************************************
    # **
    # ** BulkUploader.py - Bulk Upload Script for Shapeways.Com
    # **
    # ** You will need to visit the following page to get started as you need some
    # ** Oauth stuff to get started.  There is a link on the first page that will
    # ** take you to where you need to be to register an application:
    # **
    # **     https://developers.shapeways.com/getting-started?li=devhome_main
    # **
    # ** Once that is done update the below path statement to point to the directory
    # ** where your models are stored...and where this program can find your
    # ** Index.csv file that contains an inventory of your models with some 
    # ** added details for the listings to be created.  The model title will be
    # ** the model file name.  The index file has that name as the first column, 
    # ** a numeric column that is currently not used but envisioned for markup,
    # ** a model specific description that is appended to a stock description, and
    # ** then a list of tags.
    # **
    # ** This is far from a finished piece of work...nor is it eloquent coding, 
    # ** nor in fact does anything about the user interface make one smile!  What
    # ** it does do, however, is provide a working example of an upload!
    # **
    # ** Run this script in a terminal window.  Go to your browser and enter
    # ** localhost:3000/login.   You should be asked by Shapeways whether it is
    # ** ok for your app to access your account.  Press the button and your upload
    # ** should be processed.
    # ******************************************************************************
    import json
    import base64
    import os
    import csv
    
    from shapeways.client import Client
    
    defaultPath = "/media/psf/Home/Desktop/models"
    
    client = Client(
        consumer_key="YOUR GENERATED KEY HERE",
        consumer_secret="YOUR GENERATED SECRET HERE",
        callback_url="http://localhost:3000/callback")
    
    def application(environ, start_response):
        url = environ["PATH_INFO"]
        if url.startswith("/favicon.ico"):
            start_response("204 No Content", [])
            return [""]
        elif url.startswith("/login"):
            url = client.connect()
            start_response("302 Found", [
                ("Location", str(url)),
            ])
            return [""]
        elif url.startswith("/callback"):
            client.verify_url(environ["QUERY_STRING"])
            start_response("302 Found", [
                ("Location", "http://localhost:3000/"),
            ])
            print "Going to uploadFiles"
            uF = str(uploadFiles())
            print "Back from uploadFiles"
            return (uF + " files Uploaded")
        else:
            start_response("200 Ok", [
                ("Content-Type", "application/json"),
            ])
            return ""
    
    #
    #   Drives the uploading of all files ending in .stl found on the default path
    #   and in all of its subdirectories
    #
    def uploadFiles():
        fCount= 0
        for root, dirs, files in os.walk(defaultPath):
            print str(files)
            for file in files:
                if file.endswith(".stl"):
                    print "Uploading " + file
                    uploadFile(root, file)
                    fCount += 1
        return(fCount)
    
    #
    #   Uploads an individual file found above
    #
    def uploadFile(root, file):
        #
        #   Find the model in our inventory index file
        #
        model = findModel(file)
        if model == "":
            print "NO match"
            return
        f = open(os.path.join(root, file), "r")
    
        #
        #   Create the payload expected by the API
        #
        payload = {
            "file": base64.b64encode(f.read()),
            "fileName": file,
            "hasRightsToModel": 1,
            "uploadScale": 0.001,
            "acceptTermsAndConditions": 1,
            "title": file,
            "description":  "This is a test: " + model["description"],
            "tags": model["tags"]
        }
        f.close()
        #
        #   Add the model
        #
        t=client.add_model(payload)
    
    #
    #   Load our inventory of model files from the csb index file.  Model file name
    #   is the key, then download proce (who knew this was not an option!  Followed
    #   by a field for additional description, and then a list of tags
    #
    def loadInventory():
        ifile  = open('Index.csv', "rb")
        reader = csv.reader(ifile)
        for row in reader:
            tags = []
            for i in range(3, len(row)):
                tags.append(row[i])        
            model = {"name" : row[0], "price" : row[1], "description":row[2], "tags": tags}
            temp = row[0].upper()
            models.update({temp: model})
        ifile.close()
        
    #
    #   Find the model file returning "" if not found
    #
    def findModel(model):
        try:
            return(models[model.upper()])
        except:
            return("")
    
    #
    #   Primary execution
    #
    if __name__ == "__main__":
        from wsgiref.simple_server import make_server
        models = {}
        loadInventory()
        try:
            httpd = make_server("", 3000, application)
            print "Tracking Server Listening on Port 3000"
            httpd.serve_forever()
        except KeyboardInterrupt:
            print "Exiting"
    
    Sample index file:
    Code:
    Drum.stl,1,"Something extra","Germany","Heavy"
    Drum2.stl,1,"","Germany", "Medium"
    Missing.stl,2,"","USA","Medium"
    Drum4.stl,1,"One more extra thing","France"