Get Inspire insights from former attendees in our AMA discussion thread on Inspire Buzz. ACEs and other community members are on call all week to answer!

Alteryx Server Discussions

Find answers, ask questions, and share expertise about Alteryx Server.

problem (The provided signature(oauth_signature) is invalid)

saraA
5 - Atom

Hello everyone 

 

I have been trying for two week to access Alteryx API and generate oauth_signature but I got this error each time 

>> 

the error : 

{"data":null,"exceptionName":"UnauthorizedException","innerExceptionMessage":"","message":"The provided signature(oauth_signature) is invalid."} 

 

I create python code to generate : 

this is the code 

---------------------------------------------

import time
import collections
import random
import math
import requests
import string
import json
import time
import datetime
from datetime import  timedelta
from datetime import datetime, timedelta
import AlteryxGalleryAPI


class Gallery(object😞
    def __init__(self, apiLocation, apiKey, apiSecret😞
        self.apiLocation = apiLocation
        self.apiKey = apiKey
        self.apiSecret = apiSecret
#utc
    def buildOauthParams(self😞
        return {'oauth_consumer_key': self.apiKey,
                'oauth_nonce': self.generate_nonce(5),
                'oauth_signature_method': 'HMAC-SHA1',
                'oauth_timestamp': str(int(math.floor(time.time()))),
                'oauth_version': '1.0'}

    '''Finds workflows in a subscription'''

    def subscription(self😞
        method = 'GET'
        url = self.apiLocation + '/workflows/subscription/'
        params = self.buildOauthParams()
        signature = self.generateSignature(method, url, params)
        params.update({'oauth_signature': signature})
        output = requests.get(url, params=params)
        return output.text


    '''Returns the questions for the given Alteryx Analytics App'''

    def questions(self, appId😞
        method = 'GET'
        url = self.apiLocation + '/workflows/' + appId + '/questions/'
        params = self.buildOauthParams()
        signature = self.generateSignature(method, url, params)
        params.update({'oauth_signature': signature})
        output = requests.get(url, params=params)
        return output, output.content

    '''Queue an app execution job. Returns ID of the job'''

    def executeWorkflow(self, appId, *kwpos, **kwargs😞
        if('payload' in kwargs😞
            print('Payload included: %s' % kwargs['payload'])
            data = kwargs['payload']
            method = 'POST'
            url = self.apiLocation + '/workflows/' + appId + '/jobs/'
            params = self.buildOauthParams()
            signature = self.generateSignature(method, url, params)
            params.update({'oauth_signature': signature})
            output = requests.post(url, json=data, headers={'Content-Type':'application/json'}, params=params)
        else:
            print('No Payload included')
            method = 'POST'
            url = self.apiLocation + '/workflows/' + appId + '/jobs/'
            params = self.buildOauthParams()
            signature = self.generateSignature(method, url, params)
            params.update({'oauth_signature': signature})
            output = requests.post(url, params=params)
           
        return output,output.content


    '''Returns the jobs for the given Alteryx Analytics App'''

    def getJobs(self, appId😞
        method = 'GET'
        url = self.apiLocation + '/workflows/' + appId + '/jobs/'
        params = self.buildOauthParams()
        signature = self.generateSignature(method, url, params)
        params.update({'oauth_signature': signature})
        output = requests.get(url, params=params)
        return output, output.content

    '''Retrieves the job and its current state'''

    def getJobStatus(self, jobId😞
        method = 'GET'
        url = self.apiLocation + '/jobs/' + jobId + '/'
        params = self.buildOauthParams()
        signature = self.generateSignature(method, url, params)
        params.update({'oauth_signature': signature})
        output = requests.get(url, params=params)
        return output, output.content

    '''Returns the output for a given job (FileURL)'''

    def getJobOutput(self, jobID, outputID😞
        method = 'GET'
        url = '/jobs/' + jobID + '/output/' + '/outputID/'
        params = self.buildOauthParams()
        signature = self.generateSignature(method, url, params)
        params.update({'oauth_signature': signature})
        output = requests.get(url, params=params)
        return output, output.content

    '''Returns the App that was requested'''

    def getApp(self, appId😞
        method = 'GET'
        url = self.apiLocation + '/' + appId + '/package/'
        params = self.buildOauthParams()
        signature = self.generateSignature(method, url, params)
        params.update({'oauth_signature': signature})
        output = requests.get(url, params=params)
        return output, output.content

    '''Generate pseudorandom number'''

    def generate_nonce(self, length=5😞
        return ''.join([str(random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase)) for i in
                        range(length)])

    def generateSignature(self, httpMethod, url, params😞
        import urllib
        import hmac
        import binascii
        import hashlib
        from requests.utils import quote

        """returns HMAC-SHA1 sign"""

        q = lambda x: quote(x, safe="~")
        sorted_params = collections.OrderedDict(sorted(params.items()))
        normalized_params = urllib.urlencode(sorted_params)
        base_string = "&".join((httpMethod.upper(), q(url), q(normalized_params)))
        sig = hmac.new("&".join([self.apiSecret, '']), base_string, hashlib.sha1)
        return sig.digest().encode("base64").rstrip('\n')

 


from AlteryxGalleryAPI import AlteryxGalleryAPI

client_key = 'your_client_key_here'
client_secret = 'your_client_secret_here'
gallery_url = 'your_gallery_url'  
 
con = Gallery(gallery_url, client_key, client_secret)    
print(con.subscription())

------------------------------------------------
 
Can any one Help me please 
what I am missing? 
 

 

 

3 REPLIES 3
fmvizcaino
17 - Castor
17 - Castor

Hey @saraA ,

 

I'm not a python coder, so not able to help you debug it.

But take a look at this and see if it helps.

https://github.com/Theamazingdp/AlteryxGalleryAPI

 

Best,

Fernando Vizcaino

patrick_digan
17 - Castor
17 - Castor

@saraA I would add a print statement to see what's going into your signature generation (sig = hmac.new). You'll want to print both of your arguments (your secret and your string to encode). Have a look at my post over here, but your string to encode needs to look exactly like this:

GET&https%3A%2F%2Fserver.domain.com%2Fgallery%2Fapi%2Fadmin%2Fv1%2Fworkflows%2F&oauth_consumer_key%3Dabc123%26oauth_nonce%3D000001%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1540946480%26oauth_version%3D1.0

 Perhaps there is something small that just isn't quite right.

NeilR
Alteryx Alumni (Retired)

In my experience the easiest way to get Gallery API authenticated is with the requests_oauthlib Python package. See a code snippet here.