Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Subscription Notification signature validation

ANSWERED

Hi all,

 

Im having a problem with Signature validation for a specific signature in my application.  My App is an ASP.NET MVC application using .NET 4.5.2.

 

  1. I receive a Subscription notification signed with the Header -> X-Fitbit-Signature: sq2a+MVIgWH364adiCd8zhLLzJ4= 
  2. When this is URL Decoded it becomes: sq2a MVIgWH364adiCd8zhLLzJ4=  
  3. The above Signature will cause a format Exception in .NET to be thrown when calling 
    Convert.FromBase64String(urlDecoded)
    as it does not like whitespace.
  4. So to get around this Im using the following to strip the whitespace and pad the string to be a multiple of 4
  5. int mm = urlDecoded.Replace(" """).Length % 4;
    if(0 < mm)
    {
        urlDecoded += new string('='4 - mm);
    }
    byte[] base64Decoded = Convert.FromBase64String(urlDecoded);
  6. Unfortuntately when I now encode the Request message body with my "clientsecret&" to validate the signatures do not match.

Can someone tell me how the X-Fitbit-Signature is generated and how it handles whitespace as in my scenario with .NET it will never be able to match the encoded message signature if there is a whitespace character in the X-Fitbit-Signature header?

 

Thanks

 

Matt

Best Answer
0 Votes
1 BEST ANSWER

Accepted Solutions

Figured this one out.  '+' and '/' are valid Base64 characters.  It turns out that HttpUtility.UrlDecode converts the '+' into whitespace.

 

I was following the recommended approach of UrlDecoding the Signature and then Base64 Decoding it but with the '+' characters being converted to whitespace the signature was wrong before it even got to Base64 Decoding.

 

New Code:

 

Snippet

private static string DecodeSignature(string authSigHeader)
{
   // Valid Characters that URL Decoding may convert when it should not.
   authSigHeader = authSigHeader.Replace("/""_HTSLASH_");
   authSigHeader = authSigHeader.Replace("+""_HTPLUS_");
 
   var urlDecoded = HttpUtility.UrlDecode(authSigHeader);
 
   urlDecoded = urlDecoded.Replace("_HTSLASH_""/");
   urlDecoded = urlDecoded.Replace("_HTPLUS_""+");
 
   // Whitespace characters causing issues
   int mm = urlDecoded.Replace(" """).Length % 4;
   if (0 < mm)
   {
        urlDecoded += new string('='4 - mm);
   }
 
   byte[] base64Decoded = Convert.FromBase64String(urlDecoded);
 
   UTF8Encoding encoding = new UTF8Encoding();
 
   return encoding.GetString(base64Decoded);
}

 

Hope this helps someone else out

View best answer in original post

Best Answer
5 REPLIES 5

Hi Matt,

 

I don't have an answer for this, but if you figure it out would you consider posting and sharing this to the Fitbit.NET library I and a few others maintain? https://github.com/aarondcoleman/Fitbit.NET

 

Thanks,

--Aaron

Using Fitbits in Research? Check out Fitabase --www.fitabase.com
Best Answer
0 Votes
Yes Aaron, ive a few things to submit when ive finished

Retry mechanism to refresh access tokens if they have expired
Intra day
Zone time series
Best Answer
0 Votes

Figured this one out.  '+' and '/' are valid Base64 characters.  It turns out that HttpUtility.UrlDecode converts the '+' into whitespace.

 

I was following the recommended approach of UrlDecoding the Signature and then Base64 Decoding it but with the '+' characters being converted to whitespace the signature was wrong before it even got to Base64 Decoding.

 

New Code:

 

Snippet

private static string DecodeSignature(string authSigHeader)
{
   // Valid Characters that URL Decoding may convert when it should not.
   authSigHeader = authSigHeader.Replace("/""_HTSLASH_");
   authSigHeader = authSigHeader.Replace("+""_HTPLUS_");
 
   var urlDecoded = HttpUtility.UrlDecode(authSigHeader);
 
   urlDecoded = urlDecoded.Replace("_HTSLASH_""/");
   urlDecoded = urlDecoded.Replace("_HTPLUS_""+");
 
   // Whitespace characters causing issues
   int mm = urlDecoded.Replace(" """).Length % 4;
   if (0 < mm)
   {
        urlDecoded += new string('='4 - mm);
   }
 
   byte[] base64Decoded = Convert.FromBase64String(urlDecoded);
 
   UTF8Encoding encoding = new UTF8Encoding();
 
   return encoding.GetString(base64Decoded);
}

 

Hope this helps someone else out

Best Answer

URL decoding the X-Fitbit-Signature header is unnecessary. The only valid Base64 characters are a subset of US-ASCII.

Best Answer
0 Votes

Do you have a sample for how you are determing if the signature is valid. There is basically really no documentation other than a brief sentence that is vague and does not really explain (lack of examples) how to determine if the key is valid. I wish they did their webhooks like braintree. For which we call a method to validate the signature. Instead if it's just this: 

=====================================

To verify the incoming signature, you compute an expected signature from the JSON contents of the "updates" request entity using your OAuth client secret and a null OAuth access token secret (in this case the key for the HMAC-SHA1 method should be the "consumer_secret&" – consumer secret concatenated with the "&" symbol). No headers or request parameters are included in the signature.

=====================================

 

What does "updates" in quotes mean? If you don't can't provide a syntax specific example, could you at least provide some sort of sudo code for God sakes? What does "No headers or request parameters are included in the signature"? What does that have to do with anything. The question boils down to you want us to check the signature, okay, how does one accomplish this?

Best Answer