protected override async Task <AuthenticationTicket> AuthenticateCoreAsync()
        {
            AuthenticationProperties properties = null;

            try
            {
                string code  = null;
                string state = null;

                var query  = Request.Query;
                var values = query.GetValues(nameof(code));

                if (values != null && values.Count == 1)
                {
                    code = values[0];
                }

                values = query.GetValues(nameof(state));
                if (values != null && values.Count == 1)
                {
                    state = values[0];
                }

                properties = Options.StateDataFormat.Unprotect(state);

                if (properties == null)
                {
                    return(null);
                }

                // OAuth2 10.12 CSRF
                if (!ValidateCorrelationId(properties, logger))
                {
                    return(new AuthenticationTicket(null, properties));
                }

                if (string.IsNullOrEmpty(code))
                {
                    return(new AuthenticationTicket(null, properties));
                }


                string requestPrefix = Request.Scheme + "://" + Request.Host;
                string redirectUri   = requestPrefix + Request.PathBase + Options.CallbackPath;

                string tokenEndpoint = Options.TokenEndpoint +
                                       "?client_id=" + Uri.EscapeDataString(Options.ClientId) +
                                       "&client_secret=" + Uri.EscapeDataString(Options.ClientSecret) +
                                       "&grant_type=code" +
                                       "&code=" + Uri.EscapeDataString(code) +
                                       "&redirect_uri=" + Uri.EscapeDataString(redirectUri);

                var tokenResponse = await httpClient.GetAsync(tokenEndpoint, Request.CallCancelled);

                tokenResponse.EnsureSuccessStatusCode();

                var token = JObject.Parse(await tokenResponse.Content.ReadAsStringAsync());

                string accessToken = token.Value <string>("access_token");
                string expiresIn   = token.Value <string>("expires_in");

                if (string.IsNullOrEmpty(accessToken))
                {
                    logger.WriteWarning("Access token was not found");
                    return(new AuthenticationTicket(null, properties));
                }

                string userInformationEndpoint = Options.UserInformationEndpoint +
                                                 "?access_token=" + Uri.EscapeDataString(accessToken);

                var response = await httpClient.GetAsync(userInformationEndpoint, Request.CallCancelled);

                response.EnsureSuccessStatusCode();

                var user = JObject.Parse(await response.Content.ReadAsStringAsync());

                var context = new WeiboAuthenticatedContext(Context, user, accessToken, expiresIn);

                context.Identity = new ClaimsIdentity(new[]
                {
                    new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString,
                              Options.AuthenticationType),
                    new Claim(ClaimTypes.Name, context.Name, XmlSchemaString,
                              Options.AuthenticationType),
                    new Claim("urn:weiboaccount:id", context.Id, XmlSchemaString,
                              Options.AuthenticationType),
                    new Claim("urn:weiboaccount:name", context.Name, XmlSchemaString,
                              Options.AuthenticationType),
                    new Claim(ClaimTypes.Gender, context.Gender, XmlSchemaString, Options.AuthenticationType)
                },
                                                      Options.AuthenticationType,
                                                      ClaimsIdentity.DefaultNameClaimType,
                                                      ClaimsIdentity.DefaultRoleClaimType);

                context.Properties = properties;

                await Options.Provider.Authenticated(context);

                return(new AuthenticationTicket(context.Identity, context.Properties));
            }
            catch (Exception ex)
            {
                logger.WriteError("Authentication failed", ex);
                return(new AuthenticationTicket(null, properties));
            }
        }
        protected override async Task <AuthenticationTicket> AuthenticateCoreAsync()
        {
            AuthenticationProperties properties = null;
            AuthenticationTicket     authenticationTicket;

            IReadableStringCollection query = this.Request.Query;

            properties = this.UnpackStateParameter(query);
            var            code   = string.Empty;
            IList <string> values = query.GetValues("code");

            if (values != null && values.Count == 1)
            {
                code = values[0];
            }
            if (string.IsNullOrEmpty(code))
            {
                authenticationTicket = new AuthenticationTicket(null, properties);
                return(authenticationTicket);
            }

            if (properties == null)
            {
                authenticationTicket = null;
            }
            else if (!this.ValidateCorrelationId(properties, this._logger))
            {
                authenticationTicket = new AuthenticationTicket(null, properties);
            }
            else
            {
                var url = string.Format(TokenUrlFormater, Uri.EscapeDataString(this.Options.AppId), Uri.EscapeDataString(this.Options.AppKey), Uri.EscapeDataString(code), Uri.EscapeDataString("http://" + this.Request.Host));
                HttpResponseMessage tokenResponse = await this._httpClient.PostAsync(url, new StringContent(""), this.Request.CallCancelled);

                tokenResponse.EnsureSuccessStatusCode();
                var accessTokenReturnValue = await tokenResponse.Content.ReadAsStringAsync();

                const string accesstokenpa = "\"access_token\":\"(.+?)\"";
                var          accesstoken   = Regex.Match(accessTokenReturnValue, accesstokenpa).Groups[1].Value;
                const string uidpa         = "\"uid\":\"(.+?)\"";
                var          openid        = Regex.Match(accessTokenReturnValue, uidpa).Groups[1].Value;
                var          nameurl       = string.Format(UserInfoFormater, Uri.EscapeDataString(accesstoken), Uri.EscapeDataString(openid));
                var          nameResponse  = await this._httpClient.GetAsync(nameurl, this.Request.CallCancelled);

                nameResponse.EnsureSuccessStatusCode();
                var nametxt = await nameResponse.Content.ReadAsStringAsync();

                const string namepa   = "\"name\":\"(.+?)\"";
                var          name     = Regex.Match(nametxt, namepa).Groups[1].Value;
                var          context  = new WeiboAuthenticatedContext(this.Context, accesstoken, openid, name);
                var          identity = new ClaimsIdentity(this.Options.AuthenticationType);
                if (!string.IsNullOrEmpty(context.OpenId))
                {
                    identity.AddClaim(new Claim(NameIdentifierClaimType, context.OpenId, XmlSchemaString, this.Options.AuthenticationType));
                }
                if (!string.IsNullOrEmpty(context.Name))
                {
                    identity.AddClaim(new Claim(NameClaimType, context.Name, XmlSchemaString, this.Options.AuthenticationType));
                }
                await this.Options.Provider.Authenticated(context);

                authenticationTicket = new AuthenticationTicket(identity, properties);
            }
            return(authenticationTicket);
        }