Share

Securing your Action Menu Items

In Flow Production Tracking, 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 Flow Production Tracking

When your secret token is set, Flow Production Tracking 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 Flow Production Tracking and the Action server.

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

from http.server import HTTPServer, 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(
                fp=self.rfile,
                headers=self.headers,
                environ={'REQUEST_METHOD':'POST',
                         'CONTENT_TYPE':self.headers['Content-Type'],
                         })

        # Validate the signature
        if not 'signature' in form.keys():
            print("==> Request not signed.")
            return

        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))

        sorted_params.sort()
        string_to_verify = ''.join(sorted_params)

        signature = hmac.new(key.encode(), string_to_verify.encode(), hashlib.sha1).hexdigest()
        print("signature source: %s" % form['signature'].value)
        print("signature target: %s" % signature)

        if form['signature'].value == signature:
            print("==> Signatures match. This request was not tampered with!")

        if form['signature'].value != signature:
            print("==> Signatures not 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)
        return

if __name__ == '__main__':
    server = HTTPServer(('localhost', 8009), PostHandler)
    print('Starting server, use  to stop')
    server.serve_forever()

Here is an example Action server written in Python 2 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(
                fp=self.rfile,
                headers=self.headers,
                environ={'REQUEST_METHOD':'POST',
                         'CONTENT_TYPE':self.headers['Content-Type'],
                         })

        # Validate the signature
        if not 'signature' in form.keys():
            print "==> Request not signed."
            return

        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))

        sorted_params.sort()
        string_to_verify = ''.join(sorted_params)

        signature = hmac.new(key, 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
        return

if __name__ == '__main__':
    from BaseHTTPServer import HTTPServer
    server = HTTPServer(('localhost', 8009), PostHandler)
    print 'Starting server, use  to stop'
    server.serve_forever()

Was this information helpful?