string buildTokenRequestBody(string authCode, AuthState authState)
        {
            var sb = new StringBuilder();

            sb.Append("grant_type=authorization_code");
            sb.Append($"&code={authCode}");
            sb.Append($"&client_id={Config.ClientId}");
            sb.Append($"&redirect_uri={Uri.EscapeDataString(Config.RedirectUri.AbsoluteUri)}");
            if (authState.Verifier != null)
            {
                sb.Append($"&code_verifier={authState.Verifier}");
            }

            return(sb.ToString());
        }
        async Task <BoolValue <AuthResult> > getAccessCode(string authCode, AuthState authState)
        {
            var body    = buildTokenRequestBody(authCode, authState);
            var uri     = Config.TokenIssuer.AbsoluteUri;
            var request = (HttpWebRequest)WebRequest.Create(uri);

            request.Method      = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.Accept      = "Accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
            var bodyData = Encoding.ASCII.GetBytes(body);

            request.ContentLength = bodyData.Length;

            Log.DebugWebRequest(request, body);

            var stream = request.GetRequestStream();
            await stream.WriteAsync(bodyData, 0, bodyData.Length);

            stream.Close();
            Log?.DebugWebRequest(request, body);
            try
            {
                var response = await request.GetResponseAsync();

                var responseStream = response.GetResponseStream()
                                     ?? throw new Exception("Unexpected error: No response when requesting token.");

                using (var r = new StreamReader(responseStream))
                {
                    var text = await r.ReadToEndAsync();

                    Log?.DebugWebResponse(response as HttpWebResponse, text);
                    return(await buildAuthResultAsync(text));
                }
            }
            catch (WebException webException)
            {
                var response = (HttpWebResponse)webException.Response;
                return(BoolValue <AuthResult> .Fail($"Server error: {(int)response.StatusCode} {response.StatusCode.ToString().SplitCamelCase()}"));
            }
            catch (Exception ex)
            {
                return(BoolValue <AuthResult> .Fail($"Unexpected Server error: {ex}"));
            }
        }