Securing your Action Menu Items

In Shotgun, you can create Action Menu Items (AMIs) to allow for customized actions in your site. AMIs can be sitewide or used per entity.

To secure your AMIs, use the Secret Token field.

Setting your secret token

Secret tokens add a layer of security to your AMIs. You can set a secret token to each AMI.

Note: Secret tokens can only be set once, and after they are set, they cannot be viewed via the web or API.

Validating payloads from Shotgun

When your secret token is set, Shotgun uses it to create a hash signature with each request sent to the Action server.

This hash signature is added to the payload of the request before it is sent.

Note: If your AMI is secure, then the hash signature will match in Shotgun and the Action server.

Here is an example Action server written in Python that validates received requests:

from BaseHTTPServer import BaseHTTPRequestHandler
import cgi
import hashlib
import hmac
import datetime
key = 'test_key'
class PostHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        # Parse the form data posted
        form = cgi.FieldStorage(
        # Validate the signature
        if not 'signature' in form.keys():
            print "==> Request not signed."
        sorted_params = []
        # Echo back information about what was posted in the form
        for field in form.keys():
            if field != "signature":
                sorted_params.append("%s=%s\r\n" % (field, form[field].value))
        string_to_verify = ''.join(sorted_params)
        signature =, string_to_verify, hashlib.sha1).hexdigest()
        print "signature: %s" % form['signature'].value
        print "signature: %s" % signature
        if form['signature'].value == signature:
            print "==> Signatures match. This request was not tampered with!"
        now = datetime.datetime.utcnow();
        request_time = datetime.datetime.strptime(form['timestamp'].value, "%Y-%m-%dT%H:%M:%SZ")
        delta = (now -  request_time).total_seconds()
        if delta > 10:
            print "==> This request is getting old (%d seconds). Is it a replay attack?" % delta
if __name__ == '__main__':
    from BaseHTTPServer import HTTPServer
    server = HTTPServer(('localhost', 8009), PostHandler)
    print 'Starting server, use  to stop'