{"action":"created","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":1,"created_at":"2016-08-12T12:01:22Z","updated_at":"2016-08-13T14:59:35Z","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](https://github.com/dapplo/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\t\t/// <summary>\r\n\t\t/// Logs in to the Logitech Harmony web service to get a UserAuthToken.\r\n\t\t/// </summary>\r\n\t\t/// <param name=\"username\">myharmony.com username</param>\r\n\t\t/// <param name=\"password\">myharmony.com password</param>\r\n\t\t/// <returns>MyHarmony UserAuthToken</returns>\r\n\t\tprivate static async Task<string> GetUserAuthToken(string username, string password)\r\n\t\t{\r\n\t\t\tvar myharmonyApiUri = new Uri(\"https://svcs.myharmony.com/CompositeSecurityServices/Security.svc/json\");\r\n\t\t\tvar getUserAuthTokenUri = myharmonyApiUri.AppendSegments(\"GetUserAuthToken\");\r\n\r\n\t\t\t// Post (async) the email and password as Json\r\n\t\t\t// Expect a result of GetUserAuthTokenResultRootObject, but in case of error UserAuthErrorDetails\r\n\t\t\tvar result = await getUserAuthTokenUri.PostAsync<HttpResponse<GetUserAuthTokenResultRootObject, UserAuthErrorDetails>>(new {\r\n\t\t\t\temail = username,\r\n\t\t\t\tpassword\r\n\t\t\t});\r\n\r\n\t\t\t// check if there was an error, throw an exception with the error Message from myharmony\r\n\t\t\tif (result.HasError) {\r\n\t\t\t\tthrow new Exception(result.ErrorResponse?.Message);\r\n\t\t\t}\r\n\r\n\t\t\t// Everything was fine, return the answer\r\n\t\t\treturn result.Response?.GetUserAuthTokenResult?.UserAuthToken;\r\n\t\t}\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\n- old doesn't use dependencies\r\n\r\nDisadvantage new vs old:\r\n- new  does use dependencies\r\n\r\nAdvantage new vs old:\r\n- it's less (and easier to read) code\r\n- solves proxy issues\r\n- does automatic json and other transformations\r\n- is async\r\n- makes a lot configurable (timeout etc)\r\n\r\nand 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 >"},"comment":{"url":"https://api.github.com/repos/Lakritzator/harmony/issues/comments/239624993","html_url":"https://github.com/Lakritzator/harmony/issues/3#issuecomment-239624993","issue_url":"https://api.github.com/repos/Lakritzator/harmony/issues/3","id":239624993,"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},"created_at":"2016-08-13T14:59:35Z","updated_at":"2016-08-13T14:59:35Z","body":"One way of going forward is having the \"Json\" classes available public (not internal) and also all the information like the Uri, so we make a simple implementation which handles most simple stuff and everything else can be handled in the calling application.\r\n\r\nIn that way, Dapplo or another client can be used.\r\n\r\nBUT, I at least want to change from HttpWebRequest to HttpClient which is more modern/current.\r\n"}}
{"actor":{"display_login":"Lakritzator"}}