public void CreateErrorResponseTest()
        {
            var webResponse = Substitute.For <IHttpWebResponse>();

            TokenResponse response = TokenResponse.CreateFromErrorResponse(null);

            Assert.IsNotNull(response);
            Assert.AreEqual(MsalError.ServiceReturnedError, response.Error);
            Assert.AreEqual(MsalErrorMessage.ServiceReturnedError, response.ErrorDescription);

            using (
                var stream =
                    MockHelpers.GenerateStreamFromString(
                        "{ \"expires_in\":\"3599\",\"token_type\":\"Bearer\",\"scope\":\"https://outlook.office.com/Mail.Read\",\"access_token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSIsImtpZCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSJ9.eyJhdWQiOiJodHRwczovL291dGxvb2sub2ZmaWNlLmNvbSIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzY5MmFkZWNmLWVjZmItNDRmZS05YTIyLTdjN2YyNDMwNjAwMi8iLCJpYXQiOjE0MzQxMzEyNTksIm5iZiI6MTQzNDEzMTI1OSwiZXhwIjoxNDM0MTM1MTU5LCJ2ZXIiOiIxLjAiLCJ0aWQiOiI2OTJhZGVjZi1lY2ZiLTQ0ZmUtOWEyMi03YzdmMjQzMDYwMDIiLCJvaWQiOiI0Njc0YWRiMS1mNTU4LTQ4MmUtOGM4MC04NmQzMjBmZWUwNDgiLCJ1cG4iOiJhZG1pbkBjb252ZXJnZVRlc3Qub25taWNyb3NvZnQuY29tIiwicHVpZCI6IjEwMDMzRkZGOTBFREU5NzEiLCJzdWIiOiJnbGp6V3BEZHJfT3ZPV2M1dXdQckt3MkZmdXBadU1PVjcyZFlDQU5SVGRBIiwiZ2l2ZW5fbmFtZSI6ImFkbWluIiwiZmFtaWx5X25hbWUiOiJhZG1pbiIsIm5hbWUiOiJhZG1pbiBhZG1pbiIsImFtciI6WyJwd2QiXSwidW5pcXVlX25hbWUiOiJhZG1pbkBjb252ZXJnZVRlc3Qub25taWNyb3NvZnQuY29tIiwiYXBwaWQiOiJlMWViOGE4ZC03YjBjLTRhMTQtOTMxMy0zZjJjMjVjODI5MjkiLCJhcHBpZGFjciI6IjEiLCJzY3AiOiJNYWlsLlJlYWQiLCJhY3IiOiIxIn0.o0vNXLXrHQs4Mu2tjkjtngoTccHjDAS3mFZe3YloNpbr_pQKPk784vBB-CBerwm3Asc5P4hnJ_lsGhE67s70h0bQQc08Fa9hDjTutl8mtC8SnzR3lhr_4rE1zl8_wIQGmdX6jir9vdrOziOLBXSUms_PwgkgTekRcRD6sXnO4ES40InoQBN94ANm-xc4jMTn2hD_4hIywu8Pil7eFtZ26HHRJdIR8DF0HliEXZ3AgNUpLmPGvZKFmJ6c6JmL-XTtxF-Nnp_VSa6tod0P6DuXTMWnnqlFIaRsAiBCo2IBfLfkW9LbcNIeEQb42Km7x-PymBrZRtrVTjH4CqJ3qNPGcw\",\"refresh_token\":\"OAAABAAAAiL9Kn2Z27UubvWFPbm0gLam8oo7uhd6_0TnCKEplswX89HQhihggWEstgFcorro3BpegqIolvZQ4TpxuIX_6ZKJmCtdWO90Kvn87iF13wrQnYpHEr3mNBi9CdV8jej_i88x2KXz8gGV2FdyWA5QBhc-rJhe8CCmh1GRF26JUgZXraEOsLtXLJKxPzrjWM0lNUKbXnqLZWumKAlc3euZrCGXDwrLV73rn7r_LKef2_V-toWAzceNHhqzyOfxmjeffsZ5pmh8ZR9JdOZ3C-tbMSBETJuqHlNz3tVgPu-gC4wTgNA3Cm7OFvM3ni2jzxzcBJ6h7H6nsU0KgP7EMHPW1I1wqTpqSIz439hx3IzQ3jx9vcMJk3YqxSkbiqlfju6l0qwB-mzvo4h_6UOGVS9a81ZJ_BqQ-JUrkCzdXr8wpqkOitNjNc2MvMuFIubeGs4zVaO9WbYEIFDnVb70XgdHZTU0faVu80XsUAJnjYis6e3fe2F2pIKAPQZj1aq9yJWt27pgRNE8WoRA7gGdhuDFLZk4K_o4h7hmAYvICVsQPLJ-KI3uTFCuugc9ZiG0H_TLlAVaikJowb1Stj4_FVG6npqZLACHXpFqf5SPqoY8nB38uwC0TO1Vun2fv6QHp23kB4G0q4G8oJrMZmA_IcRx0RSCFRj2g-9B7IDV78eHBcMPYN1XeG41KiYjjLBViwN0iVCmoKNL0Wxt39KrS2cI1ZzHsnxPdAOpKpwVLgoLUAiM1aywhellEXAvY1x7tr4Ks_QTXghPR4TLRBRU6Z9a9xhL6WFmyIYwwflklCyesYXPoHTU_tPJcRPuhnV7MoNLnkOTJ7WiMfXnyJpcS7oWZVJQkjTl24REB49oQPgezZ7cNWB7lSffO5Rd2p0BzqoIA5SWgLf2ENJ--cV6zf16L0iAA\",\"id_token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSIsImtpZCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSJ9.eyJhdWQiOiJlMWViOGE4ZC03YjBjLTRhMTQtOTMxMy0zZjJjMjVjODI5MjkiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vNjkyYWRlY2YtZWNmYi00NGZlLTlhMjItN2M3ZjI0MzA2MDAyL3YyLjAvIiwiaWF0IjoxNDM0MTMxMjU5LCJuYmYiOjE0MzQxMzEyNTksImV4cCI6MTQzNDEzNTE1OSwidmVyIjoiMi4wIiwidGlkIjoiNjkyYWRlY2YtZWNmYi00NGZlLTlhMjItN2M3ZjI0MzA2MDAyIiwib2lkIjoiNDY3NGFkYjEtZjU1OC00ODJlLThjODAtODZkMzIwZmVlMDQ4IiwiZW1haWwiOiJhZG1pbkBjb252ZXJnZVRlc3Qub25taWNyb3NvZnQuY29tIiwic3ViIjoiaU5CaDVnSE1XRXdKdGZKTVBsbHpwMU1JbXNHMWRFa3pYZWliZ1BVdC16OCIsIm5hbWUiOiJhZG1pbiBhZG1pbiIsImF1dGhfdGltZSI6MTQzNDEzMDg5M30.OxBoUrMQIBn9dZ3F8PfXoSMpr718KOeD2vHvA9MnP8NWgrugK3n_gYXVRR7IiuTjiYf08NVdG-cvTXOr1fvg78zAhEiBRmnGZWGfW8VSzKd5D1ZqHyMRL8jQPHbN8Tok8parbfjEYHrPrqxMyiGJ5oGcDsB1fyjsLghGOagvbK1B8SCo_yICvw0hicjSsiLitYFnul27RVvXxp7B-ZhRZGfTyH8orDpcHXoxcVb_QoVozd06XsQEXzXXS_WyhZAHSr4eSKj0IA52ghF9f46ZHqHBUeGtLzjNrjgzuUUehD6fHkTJUb-XuUGyGYX-7_c-CeyEjHa_rz0LeLUkjbhhDA\"}")
                )
            {
                webResponse.ResponseStream.Returns(stream);
                response = TokenResponse.CreateFromErrorResponse(webResponse);
                Assert.IsNotNull(response);
            }

            using (
                var stream =
                    MockHelpers.GenerateStreamFromString(
                        "random-string")
                )
            {
                webResponse.ResponseStream.Returns(stream);
                response = TokenResponse.CreateFromErrorResponse(webResponse);
                Assert.IsNotNull(response);
                Assert.AreEqual(response.Error, MsalError.Unknown);
                Assert.AreEqual(response.ErrorDescription, "random-string");
            }

            using (
                var stream =
                    MockHelpers.GenerateStreamFromString(
                        "random-string")
                )
            {
                webResponse.ResponseStream.Returns(stream);
                webResponse.StatusCode.Returns(HttpStatusCode.ServiceUnavailable);
                response = TokenResponse.CreateFromErrorResponse(webResponse);
                Assert.IsNotNull(response);
                Assert.AreEqual(response.Error, MsalError.ServiceUnavailable);
                Assert.AreEqual(response.ErrorDescription, "random-string");
            }
        }
        private async Task <T> GetResponseAsync <T>(bool respondToDeviceAuthChallenge)
        {
            T typedResponse = default(T);
            IHttpWebResponse response;

            try
            {
                IDictionary <string, string> adalIdHeaders = AdalIdHelper.GetAdalIdParameters();
                foreach (KeyValuePair <string, string> kvp in adalIdHeaders)
                {
                    this.Client.Headers[kvp.Key] = kvp.Value;
                }
                //add pkeyauth header
                this.Client.Headers[DeviceAuthHeaderName] = DeviceAuthHeaderValue;
                using (response = await this.Client.GetResponseAsync().ConfigureAwait(false))
                {
                    typedResponse = EncodingHelper.DeserializeResponse <T>(response.ResponseString);
                }
            }
            catch (HttpRequestWrapperException ex)
            {
                if (ex.InnerException is TaskCanceledException)
                {
                    Resiliency = true;

                    _callState.Logger.Information(this.CallState, "Network timeout, Exception type: " + ex.InnerException.GetType());
                    _callState.Logger.InformationPii(this.CallState, "Network timeout, Exception message: " + ex.InnerException.Message);
                }

                if (!Resiliency && ex.WebResponse == null)
                {
                    _callState.Logger.Error(CallState, ex);
                    _callState.Logger.ErrorPii(CallState, ex);
                    throw new AdalServiceException(AdalError.Unknown, ex);
                }

                //check for resiliency
                if (!Resiliency && (int)ex.WebResponse.StatusCode >= 500 && (int)ex.WebResponse.StatusCode < 600)
                {
                    _callState.Logger.Information(this.CallState,
                                                  "HttpStatus code: " + ex.WebResponse.StatusCode + ", Exception type: " + ex.InnerException?.GetType());

                    _callState.Logger.InformationPii(this.CallState,
                                                     "HttpStatus code: " + ex.WebResponse.StatusCode + ", Exception message: " + ex.InnerException?.Message);

                    Resiliency = true;
                }

                if (Resiliency)
                {
                    if (RetryOnce)
                    {
                        await Task.Delay(DelayTimePeriodMilliSeconds).ConfigureAwait(false);

                        RetryOnce = false;

                        var msg = "Retrying one more time..";
                        _callState.Logger.Information(this.CallState, msg);
                        _callState.Logger.InformationPii(this.CallState, msg);

                        return(await this.GetResponseAsync <T>(respondToDeviceAuthChallenge).ConfigureAwait(false));
                    }

                    _callState.Logger.Information(CallState,
                                                  "Retry Failed, Exception type: " + ex.InnerException?.GetType());
                    _callState.Logger.InformationPii(CallState,
                                                     "Retry Failed, Exception message: " + ex.InnerException?.Message);
                }

                if (!this.IsDeviceAuthChallenge(ex.WebResponse, respondToDeviceAuthChallenge))
                {
                    TokenResponse        tokenResponse = TokenResponse.CreateFromErrorResponse(ex.WebResponse);
                    string[]             errorCodes    = tokenResponse.ErrorCodes ?? new[] { ex.WebResponse.StatusCode.ToString() };
                    AdalServiceException serviceEx     = new AdalServiceException(tokenResponse.Error,
                                                                                  tokenResponse.ErrorDescription,
                                                                                  errorCodes, ex);

                    if (ex.WebResponse.StatusCode == HttpStatusCode.BadRequest &&
                        tokenResponse.Error == AdalError.InteractionRequired)
                    {
                        throw new AdalClaimChallengeException(tokenResponse.Error, tokenResponse.ErrorDescription, ex, tokenResponse.Claims);
                    }

                    throw serviceEx;
                }

                //attempt device auth
                return(await HandleDeviceAuthChallenge <T>(ex.WebResponse).ConfigureAwait(false));
            }

            return(typedResponse);
        }