fparejam
November 21 |
Hey everyone! I’ve been working with the Genesys AudioHook API and getting the authentication right was a bit trickier than expected. I saw some other devs having troubles on this forum as well... so, here’s a couple of Python and JavaScript examples to save you some time.
This will show you how to build the canonical signature base, compute the HMAC-SHA256 signature, and make sure everything matches up.
This is what the Genesys docs give us as an example GET request:
GET /api/v1/voicebiometrics/ws HTTP/1.1
Host: audiohook.example.com
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: SSdtIGEgV2ViU29ja2V0IQ==
Sec-WebSocket-Version: 13
User-Agent: GenesysCloud-AudioHook-Client
Audiohook-Organization-Id: d7934305-0972-4844-938e-9060eef73d05
Audiohook-Correlation-Id: e160e428-53e2-487c-977d-96989bf5c99d
Audiohook-Session-Id: 30b0e395-84d3-4570-ac13-9a62d8f514c0
X-API-KEY: SGVsbG8sIEkgYW0gdGhlIEFQSSBrZXkh
Signature: sig1=:NZBwyBHRRyRoeLqy1IzOa9VYBuI8TgMFt2GRDkDuJh4=:
Signature-Input: sig1=(”@request-target” “@authority” “audiohook-organization-id”
“audiohook-session-id” “audiohook-correlation-id” “x-api-key”);
keyid=“SGVsbG8sIEkgYW0gdGhlIEFQSSBrZXkh”;
nonce=“VGhpc0lzQVVuaXF1ZU5vbmNl”;alg=“hmac-sha256”;created=1641013200;expires=3282026430
It assumes the following configuration:
- Request URI: wss://audiohook.example.com/api/v1/voicebiometrics/ws
- API Key: SGVsbG8sIEkgYW0gdGhlIEFQSSBrZXkh
- Client Secret: TXlTdXBlclNlY3JldEtleVRlbGxOby0xITJAMyM0JDU=.
import base64
import hashlib
import hmac
# Secret Key (Base64 encoded)
CLIENT_SECRET = "TXlTdXBlclNlY3JldEtleVRlbGxOby0xITJAMyM0JDU="
secret = base64.b64decode(CLIENT_SECRET)
# Canonical Signature Base
signature_base = (
'"@request-target": /api/v1/voicebiometrics/ws\n'
'"@authority": audiohook.example.com\n'
'"audiohook-organization-id": d7934305-0972-4844-938e-9060eef73d05\n'
'"audiohook-session-id": 30b0e395-84d3-4570-ac13-9a62d8f514c0\n'
'"audiohook-correlation-id": e160e428-53e2-487c-977d-96989bf5c99d\n'
'"x-api-key": SGVsbG8sIEkgYW0gdGhlIEFQSSBrZXkh\n'
'"@signature-params": ("@request-target" "@authority" "audiohook-organization-id" '
'"audiohook-session-id" "audiohook-correlation-id" "x-api-key");'
'keyid="SGVsbG8sIEkgYW0gdGhlIEFQSSBrZXkh";nonce="VGhpc0lzQVVuaXF1ZU5vbmNl";'
'alg="hmac-sha256";created=1641013200;expires=3282026430'
)
# Compute the HMAC-SHA256 signature
computed_hash = base64.b64encode(
hmac.new(secret, signature_base.encode("ascii"), hashlib.sha256).digest()
).decode("ascii")
# Expected hash from the HTTP header
expected_hash = "NZBwyBHRRyRoeLqy1IzOa9VYBuI8TgMFt2GRDkDuJh4="
# Output results
print("Computed Hash: ", computed_hash)
print("Expected Hash: ", expected_hash)
# Output
"Computed Hash: NZBwyBHRRyRoeLqy1IzOa9VYBuI8TgMFt2GRDkDuJh4="
"Expected Hash: NZBwyBHRRyRoeLqy1IzOa9VYBuI8TgMFt2GRDkDuJh4="
const crypto = require('crypto');
// Secret Key (Base64 encoded)
const secret = Buffer.from('TXlTdXBlclNlY3JldEtleVRlbGxOby0xITJAMyM0JDU=', 'base64');
// Canonical Signature Base
const signature_base = [
'"@request-target": /api/v1/voicebiometrics/ws',
'"@authority": audiohook.example.com',
'"audiohook-organization-id": d7934305-0972-4844-938e-9060eef73d05',
'"audiohook-session-id": 30b0e395-84d3-4570-ac13-9a62d8f514c0',
'"audiohook-correlation-id": e160e428-53e2-487c-977d-96989bf5c99d',
'"x-api-key": SGVsbG8sIEkgYW0gdGhlIEFQSSBrZXkh',
'"@signature-params": ("@request-target" "@authority" "audiohook-organization-id" ' +
'"audiohook-session-id" "audiohook-correlation-id" "x-api-key");' +
'keyid="SGVsbG8sIEkgYW0gdGhlIEFQSSBrZXkh";nonce="VGhpc0lzQVVuaXF1ZU5vbmNl";' +
'alg="hmac-sha256";created=1641013200;expires=3282026430'
].join('\n');
// Compute the HMAC-SHA256 signature
const computed_hash = crypto.createHmac('sha256', secret).update(signature_base).digest('base64');
// Expected hash from the HTTP header
const expected_hash = "NZBwyBHRRyRoeLqy1IzOa9VYBuI8TgMFt2GRDkDuJh4=";
// Output results
console.log("Computed Hash: ", computed_hash);
console.log("Expected Hash: ", expected_hash);
//Output
"Computed Hash: NZBwyBHRRyRoeLqy1IzOa9VYBuI8TgMFt2GRDkDuJh4="
"Expected Hash: NZBwyBHRRyRoeLqy1IzOa9VYBuI8TgMFt2GRDkDuJh4="
Here are some resources that might help:
I hope this makes your life easier! If you’re running into issues, double-check the signature base construction order and make sure everything is built dynamically in the same order that it comes (can change every time), and that it matches byte-for-byte.
I hope this helped guys
Happy coding!
audiohook, authentication, HMAC, HMAC-SHA256, signature verification, canonical signature base, websocket protocol change, websocket authentication, API security, Python API, JavaScript API, API integration, signature-input, X-API-Key, dynamic signature validation, real-time authentication, Genesys API example walkthrough, authentication tutorial
Visit Topic to respond.
You are receiving this because you enabled mailing list mode.
To unsubscribe from these emails, click here.