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