protected async Task <FormAuthenticationResponse> ValidateAndGetDataAsync(string code, string redirectUri)
        {
            Dictionary <string, string> tokenRequestParameters = new Dictionary <string, string>()
            {
                { "clientId", Options.ClientId },
                { "clientSecret", Options.ClientSecret },
                { "code", code }
            };

            FormUrlEncodedContent requestContent = new FormUrlEncodedContent(tokenRequestParameters);

            HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.UserInformationEndpoint);

            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            requestMessage.Content = requestContent;
            HttpResponseMessage response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted);

            if (response.IsSuccessStatusCode)
            {
                JObject payload = JObject.Parse(await response.Content.ReadAsStringAsync());
                return(FormAuthenticationResponse.Success(payload));
            }

            string error = "OAuth token endpoint failure: " + await Display(response);

            return(FormAuthenticationResponse.Failed(new Exception(error)));
        }
        protected override Task <HandleRequestResult> HandleRemoteAuthenticateAsync()
        {
            ClaimsIdentity   identity = new ClaimsIdentity(ClaimsIssuer);
            IQueryCollection query    = Request.Query;

            StringValues             state      = query["state"];
            AuthenticationProperties properties = Options.StateDataFormat.Unprotect(state);

            if (properties == null)
            {
                return(Task.FromResult(HandleRequestResult.Fail("The  state was missing or invalid.")));
            }

            if (!ValidateCorrelationId(properties))
            {
                return(Task.FromResult(HandleRequestResult.Fail("Correlation failed.")));
            }
            StringValues codeValues             = query["code"];
            string       code                   = codeValues.FirstOrDefault();
            FormAuthenticationResponse response = ValidateAndGetDataAsync(code, Options.UserInformationEndpoint).Result;

            if (response.Error != null)
            {
                return(Task.FromResult(HandleRequestResult.Fail(response.Error.Message)));
            }


            List <Claim> claims = new List <Claim> {
                new Claim(ClaimTypes.NameIdentifier, response.NameIdentifier, ClaimValueTypes.String, ClaimsIssuer),
                new Claim(ClaimTypes.Name, response.Name, ClaimValueTypes.String, ClaimsIssuer),
                new Claim(ClaimTypes.Email, response.Email, ClaimValueTypes.String, ClaimsIssuer),
            };

            identity.AddClaims(claims);
            AuthenticationTicket ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Options.ClaimsIssuer);

            return(Task.FromResult(HandleRequestResult.Success(ticket)));
        }