diff --git a/Fitbit.Portable.Tests/FatTests.cs b/Fitbit.Portable.Tests/FatTests.cs index ff4893c9..94a2fbb3 100644 --- a/Fitbit.Portable.Tests/FatTests.cs +++ b/Fitbit.Portable.Tests/FatTests.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using AutoFixture; using System.Threading.Tasks; +using AutoFixture.AutoMoq; using Fitbit.Api.Portable; using Fitbit.Models; @@ -20,6 +21,7 @@ public class FatTests public void Init() { fixture = new Fixture(); + fixture.Customize(new AutoMoqCustomization()); } [Test] diff --git a/Fitbit.Portable.Tests/Fitbit.Portable.Tests.csproj b/Fitbit.Portable.Tests/Fitbit.Portable.Tests.csproj index 2a2b2de2..482308a2 100644 --- a/Fitbit.Portable.Tests/Fitbit.Portable.Tests.csproj +++ b/Fitbit.Portable.Tests/Fitbit.Portable.Tests.csproj @@ -6,6 +6,7 @@ + diff --git a/Fitbit.Portable.Tests/FitbitClientConstructorTests.cs b/Fitbit.Portable.Tests/FitbitClientConstructorTests.cs index 0c20a87b..2ed6fdf7 100644 --- a/Fitbit.Portable.Tests/FitbitClientConstructorTests.cs +++ b/Fitbit.Portable.Tests/FitbitClientConstructorTests.cs @@ -1,11 +1,6 @@ using Fitbit.Api.Portable; using Fitbit.Api.Portable.OAuth2; using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Net.Http; namespace Fitbit.Portable.Tests @@ -17,10 +12,9 @@ public class FitbitClientConstructorTests [Category("constructor")] public void Most_Basic() { - var credentials = new FitbitAppCredentials() { ClientId = "SomeID", ClientSecret = "THE Secret ;)" }; var accessToken = new OAuth2AccessToken() { Token = "", TokenType = "", ExpiresIn = 3600, RefreshToken = ""}; - var sut = new FitbitClient(credentials, accessToken); + var sut = new FitbitClient(accessToken); Assert.IsNotNull(sut.HttpClient); } @@ -38,11 +32,10 @@ public void Use_Custom_HttpClient_Factory() [Category("constructor")] public void Can_Instantiate_Without_Any_Interceptors() { - var credentials = new FitbitAppCredentials() { ClientId = "SomeID", ClientSecret = "THE Secret ;)" }; var accessToken = new OAuth2AccessToken() { Token = "", TokenType = "", ExpiresIn = 3600, RefreshToken = "" }; //Ensure not even the auto-token-refresh interceptor is active - var sut = new FitbitClient(credentials, accessToken, false); + var sut = new FitbitClient(accessToken, enableOAuth2TokenRefresh: false); Assert.IsNotNull(sut.HttpClient); } @@ -51,11 +44,10 @@ public void Can_Instantiate_Without_Any_Interceptors() [Category("constructor")] public void Can_Use_Interceptors_Without_Autorefresh() { - var credentials = new FitbitAppCredentials() { ClientId = "SomeID", ClientSecret = "THE Secret ;)" }; var accessToken = new OAuth2AccessToken() { Token = "", TokenType = "", ExpiresIn = 3600, RefreshToken = "" }; - //Registere an interceptor, but disable the auto-token-refresh interceptor - var sut = new FitbitClient(credentials, accessToken, new InterceptorCounter(), false); + //Register an interceptor, but disable the auto-token-refresh interceptor + var sut = new FitbitClient(accessToken, new InterceptorCounter(), false); Assert.IsNotNull(sut.HttpClient); } diff --git a/Fitbit.Portable.Tests/FitbitHttpMessageHandlerTests.cs b/Fitbit.Portable.Tests/FitbitHttpMessageHandlerTests.cs index 31323ab2..6d5fc42c 100644 --- a/Fitbit.Portable.Tests/FitbitHttpMessageHandlerTests.cs +++ b/Fitbit.Portable.Tests/FitbitHttpMessageHandlerTests.cs @@ -1,29 +1,27 @@ -namespace Fitbit.Portable.Tests +using System.Net.Http; +using System.Threading.Tasks; +using System.Threading; +using Fitbit.Api.Portable; +using NUnit.Framework; +using Fitbit.Api.Portable.OAuth2; +using Fitbit.Portable.Tests.Helpers; +using Moq; + +namespace Fitbit.Portable.Tests { - using System; - using System.Net.Http; - using System.Threading.Tasks; - using System.Threading; - using Fitbit.Api.Portable; - using NUnit.Framework; - using Fitbit.Api.Portable.OAuth2; - using Fitbit.Portable.Tests.Helpers; - using Moq; [TestFixture] public class FitbitHttpMessageHandlerTests { - FitbitAppCredentials dummyCredentials = new FitbitAppCredentials(); OAuth2AccessToken dummyToken = new OAuth2AccessToken(); [Test] [Category("Portable")] [Category("Interceptor")] - public async Task CanSnifftHttpRequests() { //arrenge var messageHandler = new InterceptorCounter(); - var sut = new FitbitClient(dummyCredentials, dummyToken, messageHandler); + var sut = new FitbitClient(dummyToken, messageHandler); //Act var r = await sut.HttpClient.GetAsync("https://dev.fitbit.com/"); @@ -43,7 +41,7 @@ public async Task CanInterceptHttpRequestAndFakeResponse() var responseFaker = new ResponseFaker(fakeResponse); //arrenge - var sut = new FitbitClient(dummyCredentials, dummyToken, responseFaker); + var sut = new FitbitClient(dummyToken, responseFaker); //Act var actualResponse = await sut.HttpClient.GetAsync("https://dev.fitbit.com/"); @@ -52,8 +50,7 @@ public async Task CanInterceptHttpRequestAndFakeResponse() //Ensure that the response handler is still invoked, even though we short circuited the request Assert.AreEqual(EXPECT_ONE_REQUEST, responseFaker.ResponseCount); } - - + [Test] [Category("Portable")] [Category("Interceptor")] @@ -70,7 +67,7 @@ public async Task Correctly_Detects_Stale_Token_Refreshes_And_Retries_Original_R //we shortcircuit the request to fake an expired token on the first request, and assuming the token is different the second time we let the request through var fakeServer = new StaleTokenFaker(); - var sut = new FitbitClient(dummyCredentials, originalToken, fakeServer, /*Explicity activate autorefresh, default is true*/true, fakeManager.Object); + var sut = new FitbitClient(originalToken, fakeServer, /*Explicity activate autorefresh, default is true*/true, fakeManager.Object); //Act var actualResponse = await sut.HttpClient.GetAsync("https://dev.fitbit.com/"); @@ -80,12 +77,10 @@ public async Task Correctly_Detects_Stale_Token_Refreshes_And_Retries_Original_R //Ensure the client is updated with the refreshed token Assert.AreEqual(refreshedToken.Token, sut.HttpClient.DefaultRequestHeaders.Authorization.Parameter); fakeManager.Verify(m => m.RefreshTokenAsync(It.IsAny()), Times.Once); - //Expecte two interceptions. First when we get the 401 refresh, and second when we retry after refreshing the stale token + //Expected two interceptions. First when we get the 401 refresh, and second when we retry after refreshing the stale token Assert.AreEqual(2, fakeServer.requestCount, "It looks like either the client did not retry after the token was refreshed, or the stale token was not detected"); - } - [Test] [Category("Portable")] [Category("Interceptor")] @@ -102,7 +97,7 @@ public void Can_Handle_Failed_Refresh_Operation() //simulate failed refresh token. var fakeServer = new StaleTokenFaker(10); - var sut = new FitbitClient(dummyCredentials, originalToken, fakeServer, fakeManager.Object); + var sut = new FitbitClient(originalToken, fakeServer, tokenManager: fakeManager.Object); //Act var r = sut.HttpClient.GetAsync("https://dev.fitbit.com/"); @@ -124,10 +119,10 @@ public async Task Disable_Automatic_Token_Refresh() var fakeManager = new Mock(); fakeManager.Setup(m => m.RefreshTokenAsync(It.IsAny())).Returns(() => Task.Run(() => refreshedToken)); - //we shortcircuit the request to return a stale token and ensure that the client lets the stale token response through + //we short circuit the request to return a stale token and ensure that the client lets the stale token response through var fakeServer = new StaleTokenFaker(); - var sut = new FitbitClient(dummyCredentials, originalToken, fakeServer, false, fakeManager.Object); + var sut = new FitbitClient(originalToken, fakeServer, false, fakeManager.Object); //Act var actualResponse = await sut.HttpClient.GetAsync("https://dev.fitbit.com/"); diff --git a/Fitbit.Portable.Tests/GoalsTests.cs b/Fitbit.Portable.Tests/GoalsTests.cs index eb4be89e..b6b5c0d2 100644 --- a/Fitbit.Portable.Tests/GoalsTests.cs +++ b/Fitbit.Portable.Tests/GoalsTests.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using AutoFixture; using System.Threading.Tasks; +using AutoFixture.AutoMoq; namespace Fitbit.Portable.Tests { @@ -18,6 +19,7 @@ public class GoalsTests public void Init() { fixture = new Fixture(); + fixture.Customize(new AutoMoqCustomization()); } [Test] [Category("Portable")] diff --git a/Fitbit.Portable.Tests/WeightTests.cs b/Fitbit.Portable.Tests/WeightTests.cs index 90340ae6..20cc1650 100644 --- a/Fitbit.Portable.Tests/WeightTests.cs +++ b/Fitbit.Portable.Tests/WeightTests.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using AutoFixture; using System.Threading.Tasks; +using AutoFixture.AutoMoq; namespace Fitbit.Portable.Tests { @@ -20,6 +21,7 @@ public class WeightTests public void Init() { fixture = new Fixture(); + fixture.Customize(new AutoMoqCustomization()); } [Test] diff --git a/Fitbit.Portable/Constants.cs b/Fitbit.Portable/Constants.cs index 7a7bdbcf..04394ad2 100644 --- a/Fitbit.Portable/Constants.cs +++ b/Fitbit.Portable/Constants.cs @@ -2,11 +2,13 @@ { internal class Constants { - public const string BaseApiUrl = "https://api.fitbit.com/"; - public const string TemporaryCredentialsRequestTokenUri = "oauth/request_token"; - public const string TemporaryCredentialsAccessTokenUri = "oauth/access_token"; - public const string AuthorizeUri = "oauth/authorize"; - public const string LogoutAndAuthorizeUri = "oauth/logout_and_authorize"; + public static string BaseApiUrl => "https://api.fitbit.com/"; + + /// + /// The fitbit api url for oAuth2 token request + /// + public static string OAuth2TokenUrl => $"{BaseApiUrl}oauth2/token"; + public const string FloorsUnsupportedOnDeviceError = "Invalid time series resource path: /activities/floors"; public class Headers diff --git a/Fitbit.Portable/FitbitClient.cs b/Fitbit.Portable/FitbitClient.cs index 4fee7f67..b5d73d2f 100644 --- a/Fitbit.Portable/FitbitClient.cs +++ b/Fitbit.Portable/FitbitClient.cs @@ -14,8 +14,6 @@ namespace Fitbit.Api.Portable { public class FitbitClient : IFitbitClient { - public FitbitAppCredentials AppCredentials { get; private set; } - private OAuth2AccessToken _accesToken; public OAuth2AccessToken AccessToken { @@ -28,7 +26,9 @@ public OAuth2AccessToken AccessToken _accesToken = value; //If we update the AccessToken after HttpClient has been created, then reconfigure authorization header if (HttpClient != null) + { ConfigureAuthorizationHeader(); + } } } @@ -36,92 +36,66 @@ public OAuth2AccessToken AccessToken /// The httpclient which will be used for the api calls through the FitbitClient instance /// public HttpClient HttpClient { get; private set; } - public ITokenManager TokenManager { get; private set; } public bool OAuth2TokenAutoRefresh { get; set; } - public List FitbitInterceptorPipeline { get; private set; } - - + private List FitbitInterceptorPipeline { get; set; } /// - /// Simplest constructor for OAuth2- requires the minimum information required by FitBit.Net client to make succesful calls to Fitbit Api + /// Simple constructor for OAuth2- requires the minimum information required by FitBit.Net client to make succesful calls to Fitbit Api /// - /// Obtain this information from your developer dashboard. App credentials are required to perform token refresh /// Authenticate with Fitbit API using OAuth2. Authenticator2 class is a helper for this process /// An interface that enables sniffing all outgoing and incoming http requests from FitbitClient - public FitbitClient(FitbitAppCredentials credentials, OAuth2AccessToken accessToken, IFitbitInterceptor interceptor = null, bool enableOAuth2TokenRefresh = true, ITokenManager tokenManager = null) + /// + /// Implementation of ITokenManager which is required for the scope of the FitbitClient instance. + public FitbitClient(OAuth2AccessToken accessToken, IFitbitInterceptor interceptor = null, bool enableOAuth2TokenRefresh = true, ITokenManager tokenManager = null) { - this.AppCredentials = credentials; - this.AccessToken = accessToken; - - this.FitbitInterceptorPipeline = new List(); - - + AccessToken = accessToken; + TokenManager = tokenManager; + FitbitInterceptorPipeline = new List(); + if (interceptor != null) { - this.FitbitInterceptorPipeline.Add(interceptor); + FitbitInterceptorPipeline.Add(interceptor); } - ConfigureTokenManager(tokenManager); - //Auto refresh should always be the last handle to be registered. ConfigureAutoRefresh(enableOAuth2TokenRefresh); - CreateHttpClientForOAuth2(); } private void ConfigureAutoRefresh(bool enableOAuth2TokenRefresh) { - this.OAuth2TokenAutoRefresh = enableOAuth2TokenRefresh; + OAuth2TokenAutoRefresh = enableOAuth2TokenRefresh; if (OAuth2TokenAutoRefresh) - this.FitbitInterceptorPipeline.Add(new OAuth2AutoRefreshInterceptor()); - return; + { + FitbitInterceptorPipeline.Add(new OAuth2AutoRefreshInterceptor()); + } } /// - /// Simplest constructor for OAuth2- requires the minimum information required by FitBit.Net client to make succesful calls to Fitbit Api + /// Simple constructor for OAuth2- requires the minimum information required by FitBit.Net client to make successful calls to Fitbit Api /// - /// Obtain this information from your developer dashboard. App credentials are required to perform token refresh /// Authenticate with Fitbit API using OAuth2. Authenticator2 class is a helper for this process - /// An interface that enables sniffing all outgoing and incoming http requests from FitbitClient - public FitbitClient(FitbitAppCredentials credentials, OAuth2AccessToken accessToken, List interceptors, bool enableOAuth2TokenRefresh = true, ITokenManager tokenManager = null) + /// An interface that enables sniffing all outgoing and incoming http requests from FitbitClient + /// + /// Implementation of ITokenManager which is required for the scope of the FitbitClient instance. + public FitbitClient(OAuth2AccessToken accessToken, List interceptors, bool enableOAuth2TokenRefresh = true, ITokenManager tokenManager = null) { - this.AppCredentials = credentials; - this.AccessToken = accessToken; - - this.FitbitInterceptorPipeline = new List(); + AccessToken = accessToken; + TokenManager = tokenManager; - if (interceptors != null && interceptors.Count > 0) - this.FitbitInterceptorPipeline.AddRange(interceptors); + FitbitInterceptorPipeline = new List(); - ConfigureTokenManager(tokenManager); + if (interceptors?.Count > 0) + { + FitbitInterceptorPipeline.AddRange(interceptors); + } //Auto refresh should always be the last handle to be registered. ConfigureAutoRefresh(enableOAuth2TokenRefresh); CreateHttpClientForOAuth2(); } - - - public FitbitClient(FitbitAppCredentials credentials, OAuth2AccessToken accessToken, bool enableOAuth2TokenRefresh) : this(credentials, accessToken, null, enableOAuth2TokenRefresh) - { - - } - - public FitbitClient(FitbitAppCredentials credentials, OAuth2AccessToken accessToken, List interceptors, bool enableOAuth2TokenRefresh) : this(credentials, accessToken, interceptors, enableOAuth2TokenRefresh, null) - { - - } - - public FitbitClient(FitbitAppCredentials credentials, OAuth2AccessToken accessToken, List interceptors, ITokenManager tokenManager) : this(credentials, accessToken, interceptors, true, tokenManager) - { - - } - - public FitbitClient(FitbitAppCredentials credentials, OAuth2AccessToken accessToken, IFitbitInterceptor interceptor, ITokenManager tokenManager) : this(credentials, accessToken, interceptor, true, tokenManager) - { - - } - + /// /// Advanced mode for library usage. Allows custom creation of HttpClient to account for future authentication methods /// @@ -129,15 +103,8 @@ public FitbitClient(FitbitAppCredentials credentials, OAuth2AccessToken accessTo /// An interface that enables sniffing all outgoing and incoming http requests from FitbitClient public FitbitClient(Func customFactory, IFitbitInterceptor interceptor = null, ITokenManager tokenManager = null) { - this.OAuth2TokenAutoRefresh = false; - - ConfigureTokenManager(tokenManager); - this.HttpClient = customFactory(new FitbitHttpMessageHandler(this, interceptor)); - } - - private void ConfigureTokenManager(ITokenManager tokenManager) - { - TokenManager = tokenManager ?? new DefaultTokenManager(); + TokenManager = tokenManager; + HttpClient = customFactory(new FitbitHttpMessageHandler(this, interceptor)); } private void CreateHttpClientForOAuth2() diff --git a/Fitbit.Portable/OAuth2/DefaultTokenManager.cs b/Fitbit.Portable/OAuth2/DefaultTokenManager.cs index 20c23128..e3e002db 100644 --- a/Fitbit.Portable/OAuth2/DefaultTokenManager.cs +++ b/Fitbit.Portable/OAuth2/DefaultTokenManager.cs @@ -1,16 +1,21 @@ -namespace Fitbit.Api.Portable.OAuth2 -{ - using System.Collections.Generic; - using System.Net.Http; - using System.Threading.Tasks; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; - internal class DefaultTokenManager : ITokenManager +namespace Fitbit.Api.Portable.OAuth2 +{ + public class DefaultTokenManager : ITokenManager { - private static string FitbitOauthPostUrl => "https://api.fitbit.com/oauth2/token"; + private readonly FitbitAppCredentials _credentials; + + public DefaultTokenManager(FitbitAppCredentials credentials) + { + _credentials = credentials; + } public async Task RefreshTokenAsync(FitbitClient client) { - string postUrl = FitbitOauthPostUrl; + string postUrl = Constants.OAuth2TokenUrl; var content = new FormUrlEncodedContent(new[] { @@ -28,7 +33,7 @@ public async Task RefreshTokenAsync(FitbitClient client) httpClient = client.HttpClient; } - var clientIdConcatSecret = OAuth2Helper.Base64Encode(client.AppCredentials.ClientId + ":" + client.AppCredentials.ClientSecret); + var clientIdConcatSecret = OAuth2Helper.Base64Encode(_credentials.ClientId + ":" + _credentials.ClientSecret); httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", clientIdConcatSecret); HttpResponseMessage response = await httpClient.PostAsync(postUrl, content); diff --git a/Fitbit.Portable/OAuth2/OAuth2Helper.cs b/Fitbit.Portable/OAuth2/OAuth2Helper.cs index 94d5d2ae..d3b234aa 100644 --- a/Fitbit.Portable/OAuth2/OAuth2Helper.cs +++ b/Fitbit.Portable/OAuth2/OAuth2Helper.cs @@ -10,8 +10,6 @@ namespace Fitbit.Api.Portable.OAuth2 public class OAuth2Helper { private const string FitbitWebAuthBaseUrl = "https://www.fitbit.com"; - private const string FitbitApiBaseUrl = "https://api.fitbit.com"; - private const string OAuthBase = "/oauth2"; private string ClientId; @@ -25,6 +23,7 @@ public OAuth2Helper(FitbitAppCredentials credentials, string redirectUri) this.ClientSecret = credentials.ClientSecret; this.RedirectUri = redirectUri; } + public string GenerateAuthUrl(string[] scopeTypes, string state = null) { var sb = new StringBuilder(); @@ -47,7 +46,7 @@ public async Task ExchangeAuthCodeForAccessTokenAsync(string { HttpClient httpClient = new HttpClient(); - string postUrl = OAuth2Helper.FitbitOauthPostUrl; + string postUrl = Constants.OAuth2TokenUrl; var content = new FormUrlEncodedContent(new[] { @@ -71,9 +70,6 @@ public async Task ExchangeAuthCodeForAccessTokenAsync(string return accessToken; } - public static readonly string FitbitOauthPostUrl = "https://api.fitbit.com/oauth2/token"; - - public static OAuth2AccessToken ParseAccessTokenResponse(string responseString) { // assumption is the errors json will return in usual format eg. errors array diff --git a/SampleConsole/SampleConsole/App.config b/SampleConsole/SampleConsole/App.config index 9c99e876..586d44ad 100644 --- a/SampleConsole/SampleConsole/App.config +++ b/SampleConsole/SampleConsole/App.config @@ -4,7 +4,7 @@ - - + + diff --git a/SampleConsole/SampleConsole/AuthorizationHelper.cs b/SampleConsole/SampleConsole/AuthorizationHelper.cs index 0803490f..81efe972 100644 --- a/SampleConsole/SampleConsole/AuthorizationHelper.cs +++ b/SampleConsole/SampleConsole/AuthorizationHelper.cs @@ -20,7 +20,9 @@ public static FitbitClient GetAuthorizedFitBitClient(params string[] scopes) // try to retrieve the token from disk OAuth2AccessToken token = GetAccessTokenAsync(scopes).Result; - return new FitbitClient(new FitbitAppCredentials() { ClientId = Options.ClientId, ClientSecret = Options.ClientSecret }, token, true); + var tokenManager = new DefaultTokenManager(new FitbitAppCredentials { ClientId = Options.ClientId, ClientSecret = Options.ClientSecret }); + + return new FitbitClient(token, tokenManager: tokenManager); } public static async Task GetAccessTokenAsync(params string[] scopes) @@ -79,6 +81,7 @@ private static async Task AuthorizeToFitBitAsync(string[] sco { Colorizer.WriteLine("Sending authorization request..."); string scope = string.Join("%20", scopes); + string authorizeUrl = $"https://www.fitbit.com/oauth2/authorize?response_type=code&client_id={Options.ClientId}&scope={scope}&expires_in=86400"; Process.Start(authorizeUrl); diff --git a/SampleConsole/SampleConsole/Options.cs b/SampleConsole/SampleConsole/Options.cs index 2c98cb3a..4d0601b2 100644 --- a/SampleConsole/SampleConsole/Options.cs +++ b/SampleConsole/SampleConsole/Options.cs @@ -8,8 +8,8 @@ namespace SampleConsole { public class Options { - public static string ClientId = System.Configuration.ConfigurationManager.AppSettings["FitbitConsumerKey"]; - public static string ClientSecret = System.Configuration.ConfigurationManager.AppSettings["FitbitConsumerSecret"]; - public static string[] AllScopes = new string[] { "activity ", "nutrition ", "heartrate ", "location ", "nutrition ", "profile ", "settings ", "sleep ", "social ", "weight" }; + public static string ClientId = System.Configuration.ConfigurationManager.AppSettings["FitbitClientId"]; + public static string ClientSecret = System.Configuration.ConfigurationManager.AppSettings["FitbitClientSecret"]; + public static string[] AllScopes = new string[] { "activity", "nutrition", "heartrate", "location", "nutrition", "profile", "settings", "sleep", "social", "weight" }; } } diff --git a/SampleConsole/SampleConsole/SampleConsole.csproj b/SampleConsole/SampleConsole/SampleConsole.csproj index 2957de30..5266245a 100644 --- a/SampleConsole/SampleConsole/SampleConsole.csproj +++ b/SampleConsole/SampleConsole/SampleConsole.csproj @@ -57,7 +57,9 @@ - + + Always + diff --git a/SampleWebApplication/SampleWebApplication/Controllers/FitbitController.cs b/SampleWebApplication/SampleWebApplication/Controllers/FitbitController.cs index dca36903..c06cf856 100644 --- a/SampleWebApplication/SampleWebApplication/Controllers/FitbitController.cs +++ b/SampleWebApplication/SampleWebApplication/Controllers/FitbitController.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Web.Mvc; -using Fitbit.Api; using System.Configuration; using Fitbit.Models; using Fitbit.Api.Portable; @@ -12,7 +10,7 @@ namespace SampleWebMVC.Controllers { public class FitbitController : Controller { - public static string[] AllScopes = new string[] { "activity ", "nutrition ", "heartrate ", "location ", "nutrition ", "profile ", "settings ", "sleep ", "social ", "weight" }; + public static string[] AllScopes = new string[] { "activity", "nutrition", "heartrate", "location", "nutrition", "profile", "settings", "sleep", "social", "weight" }; public ActionResult Index() { @@ -219,7 +217,8 @@ private FitbitClient GetFitbitClient(OAuth2AccessToken accessToken = null) if (accessToken != null) { var appCredentials = (FitbitAppCredentials)Session["AppCredentials"]; - FitbitClient client = new FitbitClient(appCredentials, accessToken); + var tokenManager = new DefaultTokenManager(appCredentials); + FitbitClient client = new FitbitClient(accessToken, tokenManager: tokenManager); Session["FitbitClient"] = client; return client; }