Signature validation in upstream web hook requests of Azure SignalR service

Jan Dvořák 20 Reputation points
2025-08-01T07:26:02.71+00:00

I'm trying (according to documentation https://v4.hkg1.meaqua.org/en-us/azure/azure-signalr/concept-upstream#signature) to validate signature in incoming upstream web hook requests of Azure SignalR service.

No matter what I tried, the signatures do not match. I must be doing something wrong, or the documentation is not describing the content from which a HMAC hash should be created correctly.

This is the code, unit test, that illustrate the problem. I have edited sensitive information, replacing it by "...".

using System.Security.Cryptography;
using System.Text;

public class SignatureTests
{
    [Fact]
    public void Validate_upstream_signature()
    {
        // Azure SignalR access keys copied from the portal UI.
        const string primaryAccessKeyBase64 = "...";
        const string secondaryAccessKeyBase64 = "...";

        /*
        sample upstream HTTP request from development environment:
        x-asrs-connection-id: 2UxdekB_sH6fnBmyv2DpjA2k43BwM02
        x-asrs-hub: acahub
        x-asrs-category: connections
        x-asrs-event: disconnected
        x-asrs-user-id: ...
        x-asrs-client-query: ?hub=acahub&id=zzlVXz6QpmnyenyyIiAyiA2k43BwM02&access_token=...
        x-asrs-signature: sha256=8abbda025556d4606bead7c432ad53881e66b11f274d6083560eb623f93c50d5, sha256=3e8fc2f9cf42b3346dfc1574c7be6647194c75d98fa1fcae76855df27c270c79
        */
        const string signatureHeaderValue = "sha256=8abbda025556d4606bead7c432ad53881e66b11f274d6083560eb623f93c50d5, sha256=3e8fc2f9cf42b3346dfc1574c7be6647194c75d98fa1fcae76855df27c270c79";
        const string connectionIdHeaderValue = "2UxdekB_sH6fnBmyv2DpjA2k43BwM02";
        
        var primaryAccessKey = Convert.FromBase64String(primaryAccessKeyBase64);
        var secondaryAccessKey = Convert.FromBase64String(secondaryAccessKeyBase64);
        
        var (primaryHex, secondaryHex) = ExtractSignatures(signatureHeaderValue);
        var primarySignature = Convert.FromHexString(primaryHex);
        var secondarySignature = Convert.FromHexString(secondaryHex);
        var content = Encoding.UTF8.GetBytes(connectionIdHeaderValue);

        var primaryOk = Verify(primaryAccessKey, content, primarySignature);
        var secondaryOk = Verify(secondaryAccessKey, content, secondarySignature);

        Assert.True(primaryOk);
        Assert.True(secondaryOk);
    }

    public static (string primary, string secondary) ExtractSignatures(string signatureHeaderValue)
    {
        var parts = signatureHeaderValue.Split(",", StringSplitOptions.RemoveEmptyEntries);
        var primary = parts[0].Trim()[7..];
        var secondary = parts[1].Trim()[7..];
        return (primary, secondary);
    }

    public static bool Verify(byte[] accessKey, byte[] content, byte[] signature)
    {
        using var hmac = new HMACSHA256(accessKey);
        var hash = hmac.ComputeHash(content);
        return CryptographicOperations.FixedTimeEquals(signature, hash);
    }
}
Azure SignalR Service
Azure SignalR Service
An Azure service that is used for adding real-time communications to web applications.
0 comments No comments
{count} votes

Answer accepted by question author
  1. Bhargavi Naragani 7,940 Reputation points Microsoft External Staff Moderator
    2025-08-01T08:37:30.2833333+00:00

    Hi Jan Dvořák,

    I'm glad that you were able to resolve your issue and thank you for posting your solution so that others experiencing the same thing can easily reference this!

    Since the Microsoft Q&A community has a policy that "The question author cannot accept their own answer. They can only accept answers by others ", I'll repost your solution in case you'd like to "Accept " the answer.

    Issue:

    Signature validation in upstream web hook requests of Azure SignalR service

    Solution:

    I found the reason. The access keys should be converted to byte arrays by Encoding.ASCII.GetBytes() and not by Convert.FromBase64String() even though they are base64 encoded strings.

    Please click Accept Answer and kindly upvote it so that other people who faces similar issue may get benefitted from it.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Jan Dvořák 20 Reputation points
    2025-08-01T07:50:11.3233333+00:00

    I found the reason. The access keys should be converted to byte arrays by Encoding.ASCII.GetBytes() and not by Convert.FromBase64String() even though they are base64 encoded strings.

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.