· 7 years ago · Jan 20, 2018, 03:18 PM
1public class Authenticator
2{
3 private const string ApiBaseUrl = "http://api.fitbit.com";
4 private const string Callback = "http://myCallbackUrlHere";
5 private const string SignatureMethod = "HMAC-SHA1";
6 private const string OauthVersion = "1.0";
7 private const string ConsumerKey = "myConsumerKey";
8 private const string ConsumerSecret = "myConsumerSecret";
9 private const string RequestTokenUrl = "http://api.fitbit.com/oauth/request_token";
10 private const string AccessTokenUrl = "http://api.fitbit.com/oauth/access_token";
11 private const string AuthorizeUrl = "http://www.fitbit.com/oauth/authorize";
12 private string requestToken;
13 private string requestTokenSecret;
14
15 public string GetAuthUrlToken()
16 {
17 return GenerateAuthUrlToken().Result;
18 }
19
20 private async Task<string> GenerateAuthUrlToken()
21 {
22 var httpClient = new HttpClient { BaseAddress = new Uri(ApiBaseUrl) };
23 var timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);
24 var oauthTimestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString(CultureInfo.InvariantCulture);
25 var oauthNonce = DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture);
26
27 var authHeaderValue = string.Format(
28 "oauth_callback="{0}",oauth_consumer_key="{1}",oauth_nonce="{2}"," +
29 "oauth_signature="{3}",oauth_signature_method="{4}"," +
30 "oauth_timestamp="{5}",oauth_version="{6}"",
31 Uri.EscapeDataString(Callback),
32 Uri.EscapeDataString(ConsumerKey),
33 Uri.EscapeDataString(oauthNonce),
34 Uri.EscapeDataString(this.CreateSignature(RequestTokenUrl, oauthNonce, oauthTimestamp, Callback)),
35 Uri.EscapeDataString(SignatureMethod),
36 Uri.EscapeDataString(oauthTimestamp),
37 Uri.EscapeDataString(OauthVersion));
38
39 httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
40 "OAuth",
41 authHeaderValue);
42
43 var content = new StringContent(string.Empty);
44 var response = await httpClient.PostAsync(RequestTokenUrl, content);
45
46 if (response.StatusCode != HttpStatusCode.OK)
47 {
48 throw new Exception("Request Token Step Failed");
49 }
50
51 var responseContent = await response.Content.ReadAsStringAsync();
52 var responseItems = responseContent.Split(new[] { '&' });
53
54 this.requestToken = responseItems[0];
55 this.requestTokenSecret = responseItems[1];
56
57 var url = string.Format("{0}?{1}&display=touch", AuthorizeUrl, this.requestToken);
58
59 return url;
60 }
61
62 public string CreateSignature(string url, string nonce, string timestamp, string callback)
63 {
64 // code removed
65 return signatureString;
66 }
67
68 private static byte[] StringToAscii(string s)
69 {
70 // code removed
71 return retval;
72 }
73}
74
75public class Program
76{
77 public static void Main(string[] args)
78 {
79 var o = new Program();
80 o.LinkToFitbit();
81 }
82
83 public void LinkToFitbit()
84 {
85 var authenticator = new Authenticator();
86
87 // this works and returns the url immediately
88 var url = authenticator.GetAuthUrlToken();
89
90 // code removed
91 }
92}
93
94var response = await httpClient.PostAsync(RequestTokenUrl, content);
95
96public partial class FitbitConnector : PhoneApplicationPage
97{
98 public FitbitConnector()
99 {
100 InitializeComponent();
101 this.AuthenticateUser();
102 }
103
104 private void AuthenticateUser()
105 {
106 var authenticator = new Authenticator();
107 var url = authenticator.GetAuthUrlToken();
108
109 // code removed
110 }
111}
112
113public string GetAuthUrlToken()
114{
115 return GenerateAuthUrlToken().Result;
116}
117
118private void AuthenticateUser()
119{
120 var authenticator = new Authenticator();
121 var url = authenticator.GetAuthUrlToken();
122
123 // code removed
124}
125
126private async void AuthenticateUser()
127{
128 var authenticator = new Authenticator();
129 var url = await authenticator.GenerateAuthUrlToken();
130
131 // code removed
132}
133
134public static class OauthHelper
135{
136 public const string ConsumerKey = "MyKey";
137 public const string ConsumerSecret = "MySecret";
138 public const string UriScheme = "https";
139 public const string HostName = "api.somePlace.com";
140 public const string RequestPath = "/services/api/json/1.3.0";
141 public const string OauthSignatureMethod = "HMAC-SHA1";
142 public const string OauthVersion = "1.0";
143
144 public static string BuildRequestUri(Dictionary<string, string> requestParameters)
145 {
146 var url = GetNormalizedUrl(UriScheme, HostName, RequestPath);
147 var allParameters = new List<QueryParameter>(requestParameters.Select(entry => new QueryParameter(entry.Key, entry.Value)));
148 var normalizedParameters = NormalizeParameters(allParameters);
149 var requestUri = string.Format("{0}?{1}", url, normalizedParameters);
150
151 return requestUri;
152 }
153
154 public static AuthenticationHeaderValue CreateAuthorizationHeader(
155 string oauthToken,
156 string oauthNonce,
157 string oauthTimestamp,
158 string oauthSignature)
159 {
160 var normalizedUrl = GetNormalizedUrl(UriScheme, HostName, RequestPath);
161 return CreateAuthorizationHeader(oauthToken, oauthNonce, oauthTimestamp, oauthSignature, normalizedUrl);
162 }
163
164 public static AuthenticationHeaderValue CreateAuthorizationHeader(
165 string oauthToken,
166 string oauthNonce,
167 string oauthTimestamp,
168 string oauthSignature,
169 string realm)
170 {
171 if (string.IsNullOrWhiteSpace(oauthToken))
172 {
173 oauthToken = string.Empty;
174 }
175
176 if (string.IsNullOrWhiteSpace(oauthTimestamp))
177 {
178 throw new ArgumentNullException("oauthTimestamp");
179 }
180
181 if (string.IsNullOrWhiteSpace(oauthNonce))
182 {
183 throw new ArgumentNullException("oauthNonce");
184 }
185
186 if (string.IsNullOrWhiteSpace(oauthSignature))
187 {
188 throw new ArgumentNullException("oauthSignature");
189 }
190
191 var authHeaderValue = string.Format(
192 "realm="{0}"," +
193 "oauth_consumer_key="{1}"," +
194 "oauth_token="{2}"," +
195 "oauth_nonce="{3}"," +
196 "oauth_timestamp="{4}"," +
197 "oauth_signature_method="{5}"," +
198 "oauth_version="{6}"," +
199 "oauth_signature="{7}"",
200 realm,
201 Uri.EscapeDataString(ConsumerKey),
202 Uri.EscapeDataString(oauthToken),
203 Uri.EscapeDataString(oauthNonce),
204 Uri.EscapeDataString(oauthTimestamp),
205 Uri.EscapeDataString(OauthSignatureMethod),
206 Uri.EscapeDataString(OauthVersion),
207 Uri.EscapeDataString(oauthSignature));
208
209 var authHeader = new AuthenticationHeaderValue("OAuth", authHeaderValue);
210
211 return authHeader;
212 }
213
214 public static string CreateSignature(
215 string httpMethod,
216 string oauthToken,
217 string oauthTokenSecret,
218 string oauthTimestamp,
219 string oauthNonce,
220 Dictionary<string, string> requestParameters)
221 {
222 // get normalized url
223 var normalizedUrl = GetNormalizedUrl(UriScheme, HostName, RequestPath);
224
225 return CreateSignature(
226 httpMethod,
227 oauthToken,
228 oauthTokenSecret,
229 oauthTimestamp,
230 oauthNonce,
231 requestParameters,
232 normalizedUrl);
233 }
234
235 public static string CreateSignature(
236 string httpMethod,
237 string oauthToken,
238 string oauthTokenSecret,
239 string oauthTimestamp,
240 string oauthNonce,
241 Dictionary<string, string> requestParameters,
242 string realm)
243 {
244 if (string.IsNullOrWhiteSpace(httpMethod))
245 {
246 throw new ArgumentNullException("httpMethod");
247 }
248
249 if (string.IsNullOrWhiteSpace(oauthToken))
250 {
251 oauthToken = string.Empty;
252 }
253
254 if (string.IsNullOrWhiteSpace(oauthTokenSecret))
255 {
256 oauthTokenSecret = string.Empty;
257 }
258
259 if (string.IsNullOrWhiteSpace(oauthTimestamp))
260 {
261 throw new ArgumentNullException("oauthTimestamp");
262 }
263
264 if (string.IsNullOrWhiteSpace(oauthNonce))
265 {
266 throw new ArgumentNullException("oauthNonce");
267 }
268
269 var allParameters = new List<QueryParameter>
270 {
271 new QueryParameter("oauth_consumer_key", ConsumerKey),
272 new QueryParameter("oauth_token", oauthToken),
273 new QueryParameter("oauth_nonce", oauthNonce),
274 new QueryParameter("oauth_timestamp", oauthTimestamp),
275 new QueryParameter("oauth_signature_method", OauthSignatureMethod),
276 new QueryParameter("oauth_version", OauthVersion)
277 };
278 allParameters.AddRange(requestParameters.Select(entry => new QueryParameter(entry.Key, entry.Value)));
279
280 // sort params
281 allParameters.Sort(new QueryParameterComparer());
282
283 // concat all params
284 var normalizedRequestParameters = NormalizeParameters(allParameters);
285
286 // create base string
287 var signatureBase = string.Format(
288 "{0}&{1}&{2}",
289 UrlEncode(httpMethod.ToUpperInvariant()),
290 UrlEncode(realm),
291 UrlEncode(normalizedRequestParameters));
292
293 var signatureKey = string.Format(
294 "{0}&{1}",
295 UrlEncode(ConsumerSecret),
296 UrlEncode(oauthTokenSecret));
297
298 // hash the base string
299 var hmacsha1 = new HMACSHA1(StringToAscii(signatureKey));
300 var signatureString = Convert.ToBase64String(hmacsha1.ComputeHash(StringToAscii(signatureBase)));
301
302 return signatureString;
303 }
304
305 public static string GenerateNonce()
306 {
307 var ts = new TimeSpan(DateTime.Now.Ticks);
308 var ms = ts.TotalMilliseconds.ToString().Replace(".", string.Empty);
309 var nonce = ms;
310 return nonce;
311 }
312
313 public static string GenerateTimeStamp()
314 {
315 var timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);
316 var timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString(CultureInfo.InvariantCulture);
317 return timestamp;
318 }
319
320 private static string GetNormalizedUrl(string uriScheme, string hostName, string requestPath)
321 {
322 var normalizedUrl = string.Format(
323 "{0}://{1}{2}",
324 uriScheme.ToLowerInvariant(),
325 hostName.ToLowerInvariant(),
326 requestPath);
327
328 return normalizedUrl;
329 }
330
331 private static string NormalizeParameters(IList<QueryParameter> parameters)
332 {
333 var result = new StringBuilder();
334
335 for (var i = 0; i < parameters.Count; i++)
336 {
337 var p = parameters[i];
338
339 result.AppendFormat("{0}={1}", p.Name, p.Value);
340
341 if (i < parameters.Count - 1)
342 {
343 result.Append("&");
344 }
345 }
346
347 return result.ToString();
348 }
349
350 private static byte[] StringToAscii(string s)
351 {
352 var retval = new byte[s.Length];
353 for (var ix = 0; ix < s.Length; ++ix)
354 {
355 var ch = s[ix];
356 if (ch <= 0x7f)
357 {
358 retval[ix] = (byte)ch;
359 }
360 else
361 {
362 retval[ix] = (byte)'?';
363 }
364 }
365
366 return retval;
367 }
368
369 private static string UrlEncode(string value)
370 {
371 const string Unreserved = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
372
373 var result = new StringBuilder();
374
375 foreach (char symbol in value)
376 {
377 if (Unreserved.IndexOf(symbol) != -1)
378 {
379 result.Append(symbol);
380 }
381 else
382 {
383 result.Append('%' + string.Format("{0:X2}", (int)symbol));
384 }
385 }
386
387 return result.ToString();
388 }
389}
390
391public class QueryParameter
392{
393 public QueryParameter(string name, string value)
394 {
395 this.Name = name;
396 this.Value = value;
397 }
398
399 public string Name { get; private set; }
400
401 public string Value { get; private set; }
402}
403
404public class QueryParameterComparer : IComparer<QueryParameter>
405{
406 public int Compare(QueryParameter x, QueryParameter y)
407 {
408 return x.Name == y.Name
409 ? string.Compare(x.Value, y.Value)
410 : string.Compare(x.Name, y.Name);
411 }
412}
413
414var response = await httpClient.PostAsync(RequestTokenUrl, content).ConfigureAwait(false);