08-18-2015 07:50
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

08-18-2015 07:50
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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.
- I receive a Subscription notification signed with the Header -> X-Fitbit-Signature: sq2a+MVIgWH364adiCd8zhLLzJ4=
- When this is URL Decoded it becomes: sq2a MVIgWH364adiCd8zhLLzJ4=
- The above Signature will cause a format Exception in .NET to be thrown when calling
Convert.FromBase64String(urlDecoded)
as it does not like whitespace. - So to get around this Im using the following to strip the whitespace and pad the string to be a multiple of 4
int mm = urlDecoded.Replace(" ", "").Length % 4; if(0 < mm) { urlDecoded += new string('=', 4 - mm); } byte[] base64Decoded = Convert.FromBase64String(urlDecoded);
- 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
Answered! Go to the Best Answer.

- Labels:
-
.NET
-
Subscriptions API
Accepted Solutions
08-20-2015 08:57
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

08-20-2015 08:57
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
- Who Voted for this post?
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
08-18-2015 09:59
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

08-18-2015 09:59
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
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


08-19-2015 08:15
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

08-19-2015 08:15
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Retry mechanism to refresh access tokens if they have expired
Intra day
Zone time series

08-20-2015 08:57
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

08-20-2015 08:57
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
- Who Voted for this post?
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
08-24-2015 10:10 - edited 08-24-2015 10:11
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post



08-24-2015 10:10 - edited 08-24-2015 10:11
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
URL decoding the X-Fitbit-Signature header is unnecessary. The only valid Base64 characters are a subset of US-ASCII.

12-11-2016 20:16 - edited 12-11-2016 20:18
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

12-11-2016 20:16 - edited 12-11-2016 20:18
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
- Who Voted for this post?
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?
