示例#1
0
        /// <summary>
        /// Unpack the token data from the API Authentication or Refresh calls
        /// </summary>
        /// <param name="content">reponse string containing the data </param>
        /// <param name="isRefresh">Property used to know if the Unpack is from the refresh</param>
        /// <returns></returns>
        private XeroAccessToken UnpackToken(string content, bool isRefresh)
        {
            // Record the token data
            var tokens = JObject.Parse(content);

            XeroAccessToken newToken = new XeroAccessToken();

            newToken.AccessToken  = tokens["access_token"]?.ToString();
            newToken.ExpiresAtUtc = DateTime.Now.AddSeconds(int.Parse(tokens["expires_in"]?.ToString()));
            newToken.RefreshToken = tokens["refresh_token"]?.ToString();
            if (XeroConfig != null)
            {
                if (!isRefresh)
                {
                    // Only bother with this if its not a refresh
                    if (XeroConfig.StoreReceivedScope)
                    {
                        newToken.RequestedScopes = tokens["scope"]?.ToString(); // Ensure we record the scope used
                    }
                    else
                    {
                        newToken.RequestedScopes = XeroConfig.Scope;
                    }
                }
                else
                {
                    // Ensure the scopes list is left intact!
                    newToken.RequestedScopes = XeroConfig.XeroAPIToken.RequestedScopes;
                }
            }


            return(newToken);
        }
示例#2
0
        /// <summary>
        /// Perform a refresh.
        /// </summary>
        /// <param name="clientID">The client ID to use (optional) if not supplied the data in the Config will be used</param>
        /// <param name="oldToken">The client ID to use (optional) if not supplied the data the Config will be used</param>
        /// <param name="secret">The client secret to use for CODE style (optional) if not supplied the data in the Config will be used</param>
        /// <returns>New Token record</returns>
        public XeroAccessToken RefreshToken(string clientID = null, XeroAccessToken oldToken = null, string secret = null)
        {
            try
            {
                using (var client = new HttpClient())
                {
                    FormUrlEncodedContent formContent = null;

                    if ((XeroConfig != null && !string.IsNullOrEmpty(XeroConfig.ClientSecret)) || secret != null)
                    {
                        // CODE
                        string encoded = null;
                        if (!string.IsNullOrEmpty(clientID) && !string.IsNullOrEmpty(secret))
                        {
                            // Used passed ID
                            encoded = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes($"{clientID}:{secret}"));
                        }
                        else
                        {
                            // otherwise use ID from config
                            encoded = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes($"{XeroConfig.ClientID}:{XeroConfig.ClientSecret}"));
                        }

                        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encoded);

                        formContent = new FormUrlEncodedContent(new[]
                        {
                            new KeyValuePair <string, string>("grant_type", "refresh_token"),
                            new KeyValuePair <string, string>("refresh_token", oldToken != null ? oldToken.RefreshToken :  XeroConfig.XeroAPIToken.RefreshToken),
                        });
                    }
                    else
                    {
                        // PKCE
                        formContent = new FormUrlEncodedContent(new[]
                        {
                            new KeyValuePair <string, string>("grant_type", "refresh_token"),
                            new KeyValuePair <string, string>("client_id", clientID != null ? clientID :  XeroConfig.ClientID),
                            new KeyValuePair <string, string>("refresh_token", oldToken != null ? oldToken.RefreshToken :  XeroConfig.XeroAPIToken.RefreshToken),
                        });
                    }

                    var response = Task.Run(() => client.PostAsync(XeroConstants.XERO_TOKEN_URL, formContent)).ConfigureAwait(false).GetAwaiter().GetResult();

                    if (response.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        var content = Task.Run(() => response.Content.ReadAsStringAsync()).ConfigureAwait(false).GetAwaiter().GetResult();

                        // Unpack the response tokens
                        if (content.Contains("error"))
                        {
                            throw new Exception(content);
                        }

                        // Only relevent for a new Auth - Refresh can be actioned with clientid and refresh token
                        if (XeroConfig != null)
                        {
                            XeroConfig.XeroAPIToken = UnpackToken(content, true);
                        }
                        return(UnpackToken(content, true));
                    }
                    else
                    {
                        // Something didnt work - disconnected/revoked?
                        throw new Exception(response.ReasonPhrase);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new InvalidDataException($"Refresh Exchange Failed - {ex.Message}");
            }
        }