{"action":"opened","issue":{"url":"https://api.github.com/repos/Lakritzator/harmony/issues/3","repository_url":"https://api.github.com/repos/Lakritzator/harmony","labels_url":"https://api.github.com/repos/Lakritzator/harmony/issues/3/labels{/name}","comments_url":"https://api.github.com/repos/Lakritzator/harmony/issues/3/comments","events_url":"https://api.github.com/repos/Lakritzator/harmony/issues/3/events","html_url":"https://github.com/Lakritzator/harmony/issues/3","id":170856540,"number":3,"title":"Change GetUserAuthToken","user":{"login":"Lakritzator","id":708125,"avatar_url":"https://avatars.githubusercontent.com/u/708125?v=3","gravatar_id":"","url":"https://api.github.com/users/Lakritzator","html_url":"https://github.com/Lakritzator","followers_url":"https://api.github.com/users/Lakritzator/followers","following_url":"https://api.github.com/users/Lakritzator/following{/other_user}","gists_url":"https://api.github.com/users/Lakritzator/gists{/gist_id}","starred_url":"https://api.github.com/users/Lakritzator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Lakritzator/subscriptions","organizations_url":"https://api.github.com/users/Lakritzator/orgs","repos_url":"https://api.github.com/users/Lakritzator/repos","events_url":"https://api.github.com/users/Lakritzator/events{/privacy}","received_events_url":"https://api.github.com/users/Lakritzator/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-08-12T12:01:22Z","updated_at":"2016-08-12T12:01:22Z","closed_at":null,"body":"I had a quick look at the \"GetUserAuthToken\" method implementation, which gets a token via a login at Logitech. This is written with HttpWebRequest, the implementation will cause issues when someone is behind a proxy. (This is why I wrote Dapplo.HttpExtensions, as most people implement HTTP calls wrong)\r\n\r\nJust for fun, here is an implementation of the GetUserAuthToken with Dapplo.HttpExtensions:\r\n\r\n< promotion mode on >\r\n\r\n        /// <summary>\r\n        /// Logs in to the Logitech Harmony web service to get a UserAuthToken.\r\n        /// </summary>\r\n        /// <param name=\"username\">myharmony.com username</param>\r\n        /// <param name=\"password\">myharmony.com password</param>\r\n        /// <returns>Logitech UserAuthToken</returns>\r\n        private static async Task<string> DapploGetUserAuthToken(string username, string password)\r\n        {\r\n            var logitechAuthUrl = new Uri(\"https://svcs.myharmony.com/CompositeSecurityServices/Security.svc/json/GetUserAuthToken\");\r\n\r\n            // Post the email and password as Json, async\r\n            // Expect a result of GetUserAuthTokenResultRootObject, but in case of error UserAuthErrorDetails\r\n            var result = await logitechAuthUrl.PostAsync<HttpResponse<GetUserAuthTokenResultRootObject, UserAuthErrorDetails>>(new\r\n            {\r\n                email = username,\r\n                password\r\n            });\r\n\r\n            // check if there was an error\r\n            if (result.HasError) {\r\n                throw new Exception(result.ErrorResponse?.Message);\r\n            }\r\n\r\n            // Everything fine, return the answer\r\n            return result.Response?.GetUserAuthTokenResult?.UserAuthToken;\r\n        }\r\nHere the original:\r\n\r\n        /// <summary>\r\n        /// Logs in to the Logitech Harmony web service to get a UserAuthToken.\r\n        /// </summary>\r\n        /// <param name=\"username\">myharmony.com username</param>\r\n        /// <param name=\"password\">myharmony.com password</param>\r\n        /// <returns>Logitech UserAuthToken</returns>\r\n        private static string GetUserAuthToken(string username, string password)\r\n        {\r\n            const string logitechAuthUrl = \"https://svcs.myharmony.com/CompositeSecurityServices/Security.svc/json/GetUserAuthToken\";\r\n\r\n            var httpWebRequest = (HttpWebRequest)WebRequest.Create(logitechAuthUrl);\r\n            httpWebRequest.ContentType = \"text/json\";\r\n            httpWebRequest.Method = \"POST\";\r\n\r\n            using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))\r\n            {\r\n                var json = new JavaScriptSerializer().Serialize(new\r\n                {\r\n                    email = username,\r\n                    password\r\n                });\r\n\r\n                streamWriter.Write(json);\r\n                streamWriter.Flush();\r\n            }\r\n\r\n            var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();\r\n\r\n            var responseStream = httpResponse.GetResponseStream();\r\n            if (responseStream == null)\r\n            {\r\n                return null;\r\n            }\r\n\r\n            string result;\r\n            using (var streamReader = new StreamReader(responseStream))\r\n            {\r\n                result = streamReader.ReadToEnd();\r\n            }\r\n            var harmonyData = new JavaScriptSerializer().Deserialize<GetUserAuthTokenResultRootObject>(result);\r\n            return harmonyData.GetUserAuthTokenResult.UserAuthToken;\r\n        }\r\nAdvantage old vs new:\r\nold doesn't use dependencies\r\n\r\nAdvantage new vs old:\r\nnew does use dependencies, but it's less (and easier) code, solves proxy issues, does automatic json and other transformations, is async, makes a lot configurable (timeout etc), and most importantly it has error checking: it processes the Json response depending on an HTTP error differently! It either gives a normal response (as before, when no error) or an UserAuthErrorDetails when there was an error... packed in a wrapper, but you can write your own, where you can just check \"if (result.HasError)\" and e.g. create an exception which in case of a bad password passes the error message from logitech and looks like this:\r\n\r\nAuthentication failure BadCredentials : Unable to authenticate user's mail with the corresponding password via LIP:: 1234@domain.com\r\n</ promotion mode off >"}}
{"actor":{"display_login":"Lakritzator"}}