0

I'm following this tutorial on making a REST call to Azure App Config to add a key-value entry using HMAC authentication. Both the JS and c# versions don't work - i end up with a 401 Unauthorized error saying

HMAC-SHA256 error="invalid_token", error_description="Invalid Signature"

My calling code for the C# implementation is:

var credential = "<my app config id>";
var secret = Encoding.ASCII.GetBytes(Base64Encode("<my app config secret>"));

UserQuery.MsgRouterConfigValue body = new MsgRouterConfigValue();
var key = "asd1";
body.clientId = Guid.NewGuid();
body.serviceUrl = new Uri("https://someuri");

using (var client = new HttpClient())
{
    var request = new HttpRequestMessage()
    {
        RequestUri = new Uri($"<my app config url>/kv/{key}?label=dev&api-version=1.0"),
        Method = HttpMethod.Put,
        Content = new StringContent(JsonSerializer.Serialize(body)) 
    };
    
    Sign(request,credential, secret);

    var resp = await client.SendAsync(request);
    
}

public static string Base64Encode(string plainText)
{
    var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
    return System.Convert.ToBase64String(plainTextBytes);
}

With regards to the values i'm using for credential and secret, they are from the portal for app config:

enter image description here

Can anyone advise why i'm getting a 401 error ?

EDIT: So this error is down to:

Reason: The Signature provided doesn't match what the server expects.

Solution: Make sure the String-To-Sign is correct. Make sure the Secret is correct and properly used (base64 decoded prior to using).

So in terms of the 'Make sure the String-To-Sign is correct' i'm using the same code as provided in the example, which leaves the secret being wrong but this is the same value as defined in the portal for the app config.

auburg
  • 1,373
  • 2
  • 12
  • 22

3 Answers3

0

@auburg the secret must be base64 decoded before using. The code you shared doesn't do it. You may want to call Convert.FromBase64String.

Zhenlan Wang
  • 1,213
  • 8
  • 10
  • Fantastic - that works for the C# implementation BUT this seemingly contradicts the JS implementation comment `secret) // access key value (base64 encoded)` ? This is what confused me - is the secret base 64 encoded or not ? Can you include what the equivalent JS call look like ? – auburg Sep 07 '21 at 17:56
  • @auburg, the secret you got from the Azure Portal is base64 **en**coded. The document suggests the secret should be base64 **de**coded before using. The C# sample code can be updated to include the call to Convert.FromBase64String so it's more consistent with other samples (including JS) that do base64 decode already. – Zhenlan Wang Sep 09 '21 at 15:28
0

I got the same message from Azure, even though my credentials were valid. Turns out, my local Date/Time settings were incorrect (made some clock changes that messed up current time). Once fixed the date/time to the actual current time, it went back to normal.

This happens because Azure issues a short lived token and compares your UTC time to theirs to make sure the token is valid. Maybe not the case for all "Invalid Token" issues but definitely worth the check.

hiram
  • 140
  • 1
  • 7
-1

Could be a TLS requirement

try:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

before you create the client.