// GET: /Account/HandleAuthenticationResponse?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj
        public async Task <ActionResult> HandleAuthenticationResponseAsync()
        {
            AuthenticationResponse authenticationResponse = AuthenticationResponse.LoadFromQueryString(Request.QueryString);

            ActionResult actionResult;

            if (authenticationResponse.State != (string)Session["OAuthAntiForgeryStateToken"])
            {
                actionResult = View(viewName: "Error", model: "Missing or invalid 'state' parameter.");
            }
            else if (string.IsNullOrEmpty(authenticationResponse.Code))
            {
                actionResult = View(viewName: "Error", model: $"Authentication failed. Error code: {authenticationResponse.Error}. Error description: {authenticationResponse.ErrorDescription}");
            }
            else
            {
                var tokenRequest = new TokenRequest(
                    clientId: Configuration.CLIENT_ID,
                    clientSecret: Configuration.CLIENT_SECRET,
                    grantType: "authorization_code",
                    code: authenticationResponse.Code,
                    redirectUri: Url.Action("HandleAuthenticationResponse", "Account", null, Request.Url.Scheme));

                using (var tokenWebResponse = await tokenRequest.SendAsync(Configuration.TOKEN_ENDPOINT_URL))
                {
                    if (tokenWebResponse == null)
                    {
                        actionResult = View(viewName: "Error", model: "Token request failed. Could not connect to the identity provider.");
                    }
                    else if (!tokenWebResponse.ContentType.StartsWith("application/json"))
                    {
                        actionResult = View(viewName: "Error", model: "Token request failed. Unexpected identity provider response.");
                    }
                    else
                    {
                        using (Stream tokenResponseStream = tokenWebResponse.GetResponseStream())
                        {
                            using (var tokenResponseReader = new StreamReader(tokenResponseStream))
                            {
                                string tokenResponseJson = await tokenResponseReader.ReadToEndAsync();

                                if (tokenWebResponse.StatusCode != HttpStatusCode.OK)  // Token error response
                                {
                                    TokenErrorResponse tokenErrorResponse = TokenErrorResponse.Deserialize(tokenResponseJson);
                                    actionResult = View(viewName: "Error", model: $"Token request failed. Error code: {tokenErrorResponse.Error}. Error description: {tokenErrorResponse.ErrorDescription}");
                                }
                                else  // Successful token response
                                {
                                    SuccessfulTokenResponse successfulTokenResponse = SuccessfulTokenResponse.Deserialize(tokenResponseJson);
                                    if (successfulTokenResponse.TokenType != "Bearer")
                                    {
                                        actionResult = View(viewName: "Error", model: $"Unexpected token type \"{successfulTokenResponse.TokenType}\". The only supported token type is \"Bearer\".");
                                    }
                                    else if (string.IsNullOrEmpty(successfulTokenResponse.IdToken))
                                    {
                                        actionResult = View(viewName: "Error", model: "The token response does not contain the required ID token.");
                                    }
                                    else
                                    {
                                        IdToken.ValidateAndLoadResult validateAndLoadIdTokenResult = IdToken.ValidateAndLoad(successfulTokenResponse.IdToken, Configuration.ISSUER_IDENTIFIER, Configuration.CLIENT_ID, Configuration.CLIENT_SECRET);
                                        if (!validateAndLoadIdTokenResult.IsValid)
                                        {
                                            actionResult = View(viewName: "Error", model: "ID token validation failed. Error: " + validateAndLoadIdTokenResult.ErrorMessage);
                                        }
                                        else if (validateAndLoadIdTokenResult.IdToken.Exp < DateTime.UtcNow)
                                        {
                                            actionResult = View(viewName: "Error", model: "ID token is expired.");
                                        }
                                        else if (validateAndLoadIdTokenResult.IdToken.Nonce != (string)Session["OAuthAntiReplayNonceToken"])
                                        {
                                            actionResult = View(viewName: "Error", model: "Invalid \"nonce\" token. Possible replay attack.");
                                        }
                                        else
                                        {
                                            // All checks passed. Login the user and redirect to the Home page.
                                            string userId         = $"{validateAndLoadIdTokenResult.IdToken.Iss}|{validateAndLoadIdTokenResult.IdToken.Sub}";
                                            var    claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, userId) }, DefaultAuthenticationTypes.ApplicationCookie);
                                            HttpContext.GetOwinContext().Authentication.SignIn(new AuthenticationProperties {
                                                IsPersistent = false
                                            }, claimsIdentity);
                                            actionResult = RedirectToAction("Index", "Home");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(actionResult);
        }