Search code examples
azureazureservicebusazure-eventhubsas-token

Event Hub API POST: 40103: Invalid authorization token signature


Before this gets marked as a duplicate: I have read every question/answer on SO with the above error message, and none of them solved my problem. I must be missing something simple, as what should be simple is not working.

I have created an Event Hub Namespace, with a "Send" Shared Access Policy and an Event Hub in the namespace.

Using the code from the Python Event Hub SDK (which was suggested in another answer), I have the following script to create my Authorization header:

import time
from base64 import b64encode, b64decode
from hashlib import sha256
from hmac import HMAC
from urllib.parse import quote_plus, urlencode

def generate_sas_token(uri, policy, policy_key, expiry_days=14):
    expiry = time.time() + expiry_days * 60 * 60 * 24
    encoded_uri = quote_plus(uri)
    ttl = int(expiry)
    sign_key = '{}\n{}'.format(encoded_uri, ttl)
    signature = b64encode(HMAC(b64decode(policy_key), sign_key.encode('utf-8'), sha256).digest())
    result = {
        'sr': uri,
        'sig': signature,
        'se': str(ttl),
        'skn': policy
    }
    return 'SharedAccessSignature ' + urlencode(result)

if __name__ == '__main__':
    NAMESPACE = input('Namespace: ').strip().lower()
    URI = '{}.servicebus.windows.net'.format(NAMESPACE)
    POLICY = input('Policy: ').strip()
    POLICY_KEY = input('Policy key: ').strip()
    EXPIRY_DAYS = int(input('Expiry (days): ').strip())
    print(generate_sas_token(URI, POLICY, POLICY_KEY, EXPIRY_DAYS))

Now, if I run this script using the following (dummy) values:

NAMESPACE=<my Event Hub Namespace> # let's call it "ehns"
POLICY=<"Send" Shared Access Policy Name> # let's call it "event-publisher"
POLICY_KEY=<Primary Key for the above policy, ends with = sign>
EXPIRY_DAYS=14

then I get the following (dummy) Authorization header:

SharedAccessSignature sr=ehns.servicebus.windows.net&sig=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%3D&se=1574773874&skn=event-publisher

Now when I POST a dummy message to the API endpoint, following this page:

curl -i -X POST --data-ascii "test message" -H "Content-Type: text/plain" -H "Authorization: SharedAccessSignature sr=ehns.servicebus.windows.net&sig=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%3D&se=1574773874&skn=event-publisher" https://ehns.servicebus.windows.net/ehresource/messages

I get the following response:

HTTP/1.1 401 SubCode=40103: Invalid authorization token signature
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
Strict-Transport-Security: max-age=31536000
Date: Tue, 12 Nov 2019 13:11:34 GMT

Notes:

  • I have also tried generating the Shared Access Signature with the shell commands on this page, linked to by one of the questions/answers, to no avail.
  • I have also tried the Event Hubs Signature Generator, with no more success.

Solution

  • Please use the code below:

    import time
    import hmac
    import hashlib
    import base64
    from urllib.parse import quote_plus, urlencode
    
    def _sign_string(uri, key, key_name):
    
        '''
        100000 = milsecond expiry
        '''
        expiry = int(time.time() + 10000)
    
        string_to_sign = quote_plus(uri) + '\n' + str(expiry)
    
        key = key.encode('utf-8')
        string_to_sign = string_to_sign.encode('utf-8')
        signed_hmac_sha256 = hmac.HMAC(key, string_to_sign, hashlib.sha256)
        signature = signed_hmac_sha256.digest()
        signature = base64.b64encode(signature)
    
        return 'SharedAccessSignature sr=' + quote_plus(uri)  + '&sig=' + quote_plus(signature) + '&se=' + str(expiry) + '&skn=' + key_name
    
    
    if __name__ == '__main__':    
        URI = "your_eventhub_namespace.servicebus.windows.net/your_eventhub_name"
        POLICY = "your_policy_name"
        POLICY_KEY = "the policy key"
    
        print(_sign_string(URI,POLICY_KEY,POLICY))
    

    The test result:

    enter image description here