public OnshapeOAuth(String baseUri, String clientId, String clientSecret, Action <string> logMethod = null)
        {
            IsLogging         = logMethod != null;
            logWriter         = logMethod;
            this.baseUri      = baseUri;
            this.clientId     = clientId;
            this.clientSecret = clientSecret;

            oLocker      = new object();
            AuthCode     = "";
            AccessToken  = "";
            RefreshToken = "";
            Status       = OnshapeOAuthStatus.Initialized;
        }
        private void DoAuthentication()
        {
            Status = OnshapeOAuthStatus.IsAuthenticating;
            Process pWeb = new Process();

            pWeb.StartInfo.FileName    = AuthPath;
            pWeb.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
            pWeb.Start();
            AddLogEntry("Browser opened...");
            Listen();
            pWeb.Close();
            GetTokens();
            if (Status != OnshapeOAuthStatus.Error)
            {
                Status = OnshapeOAuthStatus.Authenticated;

                AddLogEntry("Authentication completed...");
            }
        }
        //After getting callback request token
        private void GetTokens()
        {
            try
            {
                string strResponse;

                AddLogEntry("Sending request for tokens...");

                System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
                WebRequest wrRequest = WebRequest.Create(String.Format(TOKEN_URI_TEMPLATE, baseUri));
                wrRequest.Method      = "POST";
                wrRequest.ContentType = "application/x-www-form-urlencoded";

                StreamWriter swPost = new StreamWriter(wrRequest.GetRequestStream());
                swPost.Write(FormAuthReq);
                swPost.Flush();
                swPost.Close();

                AddLogEntry("Request sent...waiting for response...");

                WebResponse wrResponse = wrRequest.GetResponse();

                AddLogEntry("Processing response...");
                StreamReader srResponse = new StreamReader(wrResponse.GetResponseStream());
                strResponse = srResponse.ReadToEnd();
                srResponse.Close();

                JavaScriptSerializer jss         = new JavaScriptSerializer();
                JSONTokenResponse    jtrResponse = (JSONTokenResponse)jss.Deserialize <JSONTokenResponse>(strResponse);

                AccessToken  = jtrResponse.access_token;
                RefreshToken = jtrResponse.refresh_token;
                AddLogEntry("Access Token: " + AccessToken);
                AddLogEntry("Refresh Token: " + RefreshToken);
            }
            catch (Exception e)
            {
                Status = OnshapeOAuthStatus.Error;
                AddLogEntry("Error occured in GetTokens: " + e.ToString());
            }
        }
        //Listener for callback
        private void Listen()
        {
            try
            {
                AddLogEntry("Starting listener...");
                HttpListener hlListener = new HttpListener();
                hlListener.Prefixes.Add(SERVER_URI + "/");
                hlListener.Start();

                AddLogEntry("Listener started...");
                HttpListenerContext hlcContext = hlListener.GetContext();

                AddLogEntry("Listener received request...sending response...");
                HttpListenerRequest  hlrqRequest  = hlcContext.Request;
                HttpListenerResponse hlrpResponse = hlcContext.Response;
                string strResponse = "<HTML><HEAD><TITLE>Authentication Successful</TITLE></HEAD><BODY>Please close the window.</BODY></HTML>";//This is what people will see after authenticating
                byte[] bBuffer     = System.Text.Encoding.UTF8.GetBytes(strResponse);
                // Get a response stream and write the response to it.
                hlrpResponse.ContentLength64 = bBuffer.Length;
                System.IO.Stream smOutput = hlrpResponse.OutputStream;
                smOutput.Write(bBuffer, 0, bBuffer.Length);

                AddLogEntry("Response sent...");
                // You must close the output stream.
                smOutput.Close();
                hlListener.Stop();
                AddLogEntry("Listener closed...");

                AuthCode = hlrqRequest.QueryString["code"];

                AddLogEntry("Authentication code: " + AuthCode);
            }
            catch (Exception e)
            {
                AddLogEntry("Error occured in Listen: " + e.ToString());
                Status = OnshapeOAuthStatus.Error;
            }
        }