/// <summary> /// Get an access token. /// </summary> /// <param name="appKey">Ecobee application key.</param> /// <param name="authCode">Code previously provided by Ecobee.</param> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>A <see cref="StoredAuthToken"/>.</returns> public static async Task <StoredAuthToken> GetAccessTokenAsync(string appKey, string authCode, CancellationToken cancellationToken = default(CancellationToken)) { var requestMessage = new HttpRequestMessage(HttpMethod.Post, _baseUri + "token?grant_type=ecobeePin&code=" + authCode + "&client_id=" + appKey); requestMessage.Headers.ExpectContinue = false; var response = await SendAsyncWithTimeout(requestMessage, cancellationToken) .ConfigureAwait(false); var responseString = await response.Content.ReadAsStringAsync() .ConfigureAwait(false); if (response.StatusCode != System.Net.HttpStatusCode.OK) { throw new ApiAuthException(JsonSerializer <ApiError> .Deserialize(responseString)); } var authToken = JsonSerializer <AuthToken> .Deserialize(responseString); var storedAuthToken = new StoredAuthToken { AccessToken = authToken.AccessToken, RefreshToken = authToken.RefreshToken, TokenExpiration = DateTime.Now.AddSeconds(authToken.ExpiresIn) }; return(storedAuthToken); }
/// <summary> /// Requests a refresh token from the Ecobee API. /// </summary> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>A <see cref="Task"/>.</returns> private async Task GetRefreshTokenAsync(CancellationToken cancellationToken = default(CancellationToken)) { var requestMessage = new HttpRequestMessage(HttpMethod.Post, _baseUri + "token?grant_type=refresh_token&refresh_token=" + _storedAuthToken.RefreshToken + "&client_id=" + _appKey); requestMessage.Headers.ExpectContinue = false; var response = await SendAsyncWithTimeout(requestMessage, cancellationToken) .ConfigureAwait(false); var responseString = await response.Content.ReadAsStringAsync() .ConfigureAwait(false); if (response.StatusCode != System.Net.HttpStatusCode.OK) { throw new ApiAuthException(JsonSerializer <ApiError> .Deserialize(responseString)); } var authToken = JsonSerializer <AuthToken> .Deserialize(responseString); var storedAuthToken = new StoredAuthToken { AccessToken = authToken.AccessToken, RefreshToken = authToken.RefreshToken, TokenExpiration = DateTime.Now.AddSeconds(authToken.ExpiresIn) }; _storedAuthToken = storedAuthToken; if (_setStoredAuthTokenFunc != null) { await _setStoredAuthTokenFunc.Invoke(storedAuthToken, cancellationToken) .ConfigureAwait(false); } }
/// <summary> /// Gets current auth token and handles refresh. /// </summary> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>A <see cref="StoredAuthToken"/>.</returns> private async Task <StoredAuthToken> GetCurrentAuthTokenAsync(CancellationToken cancellationToken = default) { await _tokenReadLock.WaitAsync() .ConfigureAwait(false); try { var storedAuthToken = await _getStoredAuthTokenFunc(cancellationToken) .ConfigureAwait(false); if (storedAuthToken == null) { throw new NullReferenceException("Auth token storage delegate failed to provide token."); } if (DateTime.Compare(DateTime.Now, storedAuthToken.TokenExpiration) >= 0) { var requestMessage = new HttpRequestMessage(HttpMethod.Post, _baseUri + "token?grant_type=refresh_token&refresh_token=" + storedAuthToken.RefreshToken + "&client_id=" + _appKey); requestMessage.Headers.ExpectContinue = false; var response = await SendWithTimeoutAsync(requestMessage, cancellationToken) .ConfigureAwait(false); var responseString = await response.Content.ReadAsStringAsync() .ConfigureAwait(false); if (response.StatusCode != System.Net.HttpStatusCode.OK) { throw new ApiAuthException(JsonSerializer <ApiError> .Deserialize(responseString)); } var authToken = JsonSerializer <AuthToken> .Deserialize(responseString); storedAuthToken = new StoredAuthToken { AccessToken = authToken.AccessToken, RefreshToken = authToken.RefreshToken, TokenExpiration = DateTime.Now.AddSeconds(authToken.ExpiresIn) }; await _setStoredAuthTokenFunc(storedAuthToken, cancellationToken) .ConfigureAwait(false); } return(storedAuthToken); } finally { _tokenReadLock.Release(); } }
/// <summary> /// Peforms a POST operation against the Ecobee API. /// </summary> /// <typeparam name="TRequest">The type of request to send to the Ecobee API.</typeparam> /// <typeparam name="TResponse">The type of response from the Ecobee API.</typeparam> /// <param name="request">The request to send to the Ecobee API.</param> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>The response from the Ecobee API.</returns> public async Task <TResponse> PostAsync <TRequest, TResponse>(TRequest request, CancellationToken cancellationToken = default(CancellationToken)) where TRequest : RequestBase where TResponse : Response { if (_getStoredAuthTokenFunc != null) { _storedAuthToken = await _getStoredAuthTokenFunc.Invoke(cancellationToken) .ConfigureAwait(false); } if (DateTime.Compare(DateTime.Now, _storedAuthToken.TokenExpiration) >= 0) { await GetRefreshTokenAsync(cancellationToken) .ConfigureAwait(false); } var message = JsonSerializer <TRequest> .Serialize(request); var requestMessage = new HttpRequestMessage(HttpMethod.Post, _baseUri + _version + request.Uri + "?format=json"); requestMessage.Headers.ExpectContinue = false; requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _storedAuthToken.AccessToken); requestMessage.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); requestMessage.Content = new StringContent(message, System.Text.Encoding.UTF8, "application/json"); var response = await SendAsyncWithTimeout(requestMessage, cancellationToken) .ConfigureAwait(false); var responseString = await response.Content.ReadAsStringAsync() .ConfigureAwait(false); if (response.StatusCode != System.Net.HttpStatusCode.OK) { throw new ApiException(JsonSerializer <Response> .Deserialize(responseString)); } return(JsonSerializer <TResponse> .Deserialize(responseString)); }
/// <summary> /// Initializes a new instance of the <see cref="Client"/> class. /// </summary> /// <param name="appKey">Ecobee application key.</param> /// <param name="storedAuthToken">Ecobee authorization token data.</param> /// <param name="setStoredAuthTokenFunc">Lambda function responsible for saving current Ecobee auth token data to permanent storage.</param> /// <remarks>For single tenant Ecobee token storage. Auth tokens are stored per instance.</remarks> public Client(string appKey, StoredAuthToken storedAuthToken, Func <StoredAuthToken, CancellationToken, Task> setStoredAuthTokenFunc) { _appKey = appKey; _storedAuthToken = storedAuthToken; _setStoredAuthTokenFunc = setStoredAuthTokenFunc; }