コード例 #1
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            // 首先获取OpenId
            var openIdEndpoint = QueryHelpers.AddQueryString(Options.OpenIdEndpoint,
                                                             "access_token", tokens.AccessToken);
            var openIdResponse = await Backchannel.GetAsync(openIdEndpoint, Context.RequestAborted);

            var openIdContent = await openIdResponse.Content.ReadAsStringAsync();

            openIdContent = openIdContent.TrimStart("callback( ").TrimEnd(" );\n");
            var openIdPayload = JObject.Parse(openIdContent);

            // 存储openid,绑定到系统的用户,作为系统在第三方的唯一标识
            var openId = openIdPayload["openid"].Value <string>();

            var tokenRequestParameters = new Dictionary <string, string>()
            {
                { "access_token", tokens.AccessToken },
                { "oauth_consumer_key", Options.ClientId },
                { "openid", openId },
            };

            var endpoint = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, tokenRequestParameters);

            var requestMessage = new HttpRequestMessage(HttpMethod.Get, endpoint);

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

            //var endpoint = QueryHelpers.AddQueryString(Options.UserInformationEndpoint,
            //    "access_token", tokens.AccessToken);
            //var response = await Backchannel.GetAsync(endpoint, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                throw new HttpRequestException($"An error occurred when retrieving Facebook user information ({response.StatusCode}). Please check if the authentication information is correct and the corresponding Facebook Graph API is enabled.");
            }

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

            // 填充openid
            jObj["openid"] = openId;

            using (var payload = JsonDocument.Parse(jObj.ToString()))//
            {
                var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme,
                                                             Options, Backchannel, tokens, payload.RootElement);

                context.RunClaimActions();
                await Events.CreatingTicket(context);

                return(new AuthenticationTicket(context.Principal, properties, Scheme.Name));
            }
        }
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            [NotNull] ClaimsIdentity identity,
            [NotNull] AuthenticationProperties properties,
            [NotNull] OAuthTokenResponse tokens)
        {
            (int errorCode, string?userId) = await GetUserIdentifierAsync(tokens);

            if (errorCode != 0 || string.IsNullOrEmpty(userId))
            {
                throw new Exception($"An error (Code:{errorCode}) occurred while retrieving the user identifier.");
            }

            // See https://open.work.weixin.qq.com/api/doc/90000/90135/90196 for details.
            string address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string?>
            {
                ["access_token"] = tokens.AccessToken,
                ["userid"]       = userId,
            });

            using var response = await Backchannel.GetAsync(address, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync(Context.RequestAborted));

                throw new HttpRequestException("An error occurred while retrieving user information.");
            }

            using var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync(Context.RequestAborted));

            errorCode = payload.RootElement.GetProperty("errcode").GetInt32();
            if (errorCode != 0)
            {
                Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                "returned a {ErrorCode} response with the following message: {Message} .",
                                /* ErrorCode: */ errorCode,
                                /* Message: */ payload.RootElement.GetString("errmsg"));

                throw new Exception("An error occurred while retrieving user information.");
            }

            var principal = new ClaimsPrincipal(identity);
            var context   = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);

            context.RunClaimActions();

            await Options.Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal !, context.Properties, Scheme.Name));
        }
コード例 #3
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var openIdEndpoint = Options.OpenIdEndpoint + "?access_token=" + tokens.AccessToken;
            var response       = await Backchannel.GetAsync(openIdEndpoint, Context.RequestAborted);

            response.EnsureSuccessStatusCode();

            var tmp = await response.Content.ReadAsStringAsync();

            var regex      = new System.Text.RegularExpressions.Regex("callback\\((?<json>[ -~]+)\\);");
            var json       = JObject.Parse(regex.Match(tmp).Groups["json"].Value);
            var identifier = QQHelper.GetId(json);

            if (!string.IsNullOrEmpty(identifier))
            {
                identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, identifier, ClaimValueTypes.String, Options.ClaimsIssuer));
                identity.AddClaim(new Claim("urn:qq:id", identifier, ClaimValueTypes.String, Options.ClaimsIssuer));
            }

            var content = new FormUrlEncodedContent(new Dictionary <string, string>
            {
                { "oauth_consumer_key", Options.ClientId },
                { "access_token", tokens.AccessToken },
                { "openid", identifier }
            });

            response = await Backchannel.PostAsync(Options.UserInformationEndpoint, content);

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

            info.Add("id", identifier);
            var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Options.AuthenticationScheme);

            var notification = new OAuthCreatingTicketContext(ticket, Context, Options, Backchannel, tokens, info);

            var name = QQHelper.GetName(info);

            if (!string.IsNullOrEmpty(name))
            {
                identity.AddClaim(new Claim(ClaimTypes.Name, name, ClaimValueTypes.String, Options.ClaimsIssuer));
                identity.AddClaim(new Claim("urn:qq:name", name, ClaimValueTypes.String, Options.ClaimsIssuer));
            }
            var figure = QQHelper.GetFigure(info);

            if (!string.IsNullOrEmpty(name))
            {
                identity.AddClaim(new Claim("urn:qq:figure", figure, ClaimValueTypes.String, Options.ClaimsIssuer));
            }

            await Options.Events.CreatingTicket(notification);

            return(notification.Ticket);
        }
コード例 #4
0
        /// <summary>
        ///  Last step:
        ///  create ticket from remote server
        /// </summary>
        /// <param name="identity"></param>
        /// <param name="properties"></param>
        /// <param name="tokens"></param>
        /// <returns></returns>
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string>
            {
                ["access_token"] = tokens.AccessToken,
                ["openid"]       = tokens.Response.Value <string>("openid")
            });

            var response = await Backchannel.GetAsync(address);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync());

                throw new HttpRequestException("An error occurred while retrieving user information.");
            }

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

            if (!string.IsNullOrEmpty(payload.Value <string>("errcode")))
            {
                Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync());

                throw new HttpRequestException("An error occurred while retrieving user information.");
            }

            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, WeixinAuthenticationHelper.GetUnionid(payload), Options.ClaimsIssuer));
            identity.AddClaim(new Claim(ClaimTypes.Name, WeixinAuthenticationHelper.GetNickname(payload), Options.ClaimsIssuer));
            identity.AddClaim(new Claim(ClaimTypes.Gender, WeixinAuthenticationHelper.GetSex(payload), Options.ClaimsIssuer));
            identity.AddClaim(new Claim(ClaimTypes.Country, WeixinAuthenticationHelper.GetCountry(payload), Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:weixin:openid", WeixinAuthenticationHelper.GetOpenId(payload), Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:weixin:province", WeixinAuthenticationHelper.GetProvince(payload), Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:weixin:city", WeixinAuthenticationHelper.GetCity(payload), Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:weixin:headimgurl", WeixinAuthenticationHelper.GetHeadimgUrl(payload), Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:weixin:privilege", WeixinAuthenticationHelper.GetPrivilege(payload), Options.ClaimsIssuer));

            identity.AddClaim(new Claim("urn:weixin:user_info", payload.ToString(), Options.ClaimsIssuer));

            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload);

            context.RunClaimActions();

            await Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
コード例 #5
0
        protected override async Task <AuthenticationTicket> GetUserInformationAsync(AuthenticationProperties properties, TokenResponse tokens)
        {
            string graphAddress = Options.UserInformationEndpoint + "?access_token=" + Uri.EscapeDataString(tokens.AccessToken);

            if (Options.SendAppSecretProof)
            {
                graphAddress += "&appsecret_proof=" + GenerateAppSecretProof(tokens.AccessToken);
            }

            var graphResponse = await Backchannel.GetAsync(graphAddress, Context.RequestAborted);

            graphResponse.EnsureSuccessStatusCode();
            string text = await graphResponse.Content.ReadAsStringAsync();

            JObject user = JObject.Parse(text);

            var context = new FacebookAuthenticatedContext(Context, Options, user, tokens);

            context.Identity = new ClaimsIdentity(
                Options.AuthenticationType,
                ClaimsIdentity.DefaultNameClaimType,
                ClaimsIdentity.DefaultRoleClaimType);
            if (!string.IsNullOrEmpty(context.Id))
            {
                context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, ClaimValueTypes.String, Options.AuthenticationType));
            }
            if (!string.IsNullOrEmpty(context.UserName))
            {
                context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, ClaimValueTypes.String, Options.AuthenticationType));
            }
            if (!string.IsNullOrEmpty(context.Email))
            {
                context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, ClaimValueTypes.String, Options.AuthenticationType));
            }
            if (!string.IsNullOrEmpty(context.Name))
            {
                context.Identity.AddClaim(new Claim("urn:facebook:name", context.Name, ClaimValueTypes.String, Options.AuthenticationType));

                // Many Facebook accounts do not set the UserName field.  Fall back to the Name field instead.
                if (string.IsNullOrEmpty(context.UserName))
                {
                    context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.Name, ClaimValueTypes.String, Options.AuthenticationType));
                }
            }
            if (!string.IsNullOrEmpty(context.Link))
            {
                context.Identity.AddClaim(new Claim("urn:facebook:link", context.Link, ClaimValueTypes.String, Options.AuthenticationType));
            }
            context.Properties = properties;

            await Options.Notifications.Authenticated(context);

            return(new AuthenticationTicket(context.Identity, context.Properties));
        }
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            ClaimsIdentity identity,
            Microsoft.AspNetCore.Authentication.AuthenticationProperties properties,
            OAuthTokenResponse tokens)
        {
            var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "access_token", tokens.AccessToken);

            Dictionary <string, string> queryString = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase)
            {
                ["application_key"] = Options.PublicKey,
                ["format"]          = "json",
                ["__online"]        = "false"
            };

            if (Options.Fields.Count != 0)
            {
                queryString.Add("fields", string.Join(",", Options.Fields));
            }

            queryString.Add("sig", GetSignature(tokens.AccessToken, queryString));

            address = QueryHelpers.AddQueryString(address, queryString);

            var response = await Backchannel.GetAsync(address, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("Произошла ошибка при получении профиля пользователя: удаленный сервер " +
                                "вернул {Status} ответ со следующей информацией: {Headers} {Body}.",
                                response.StatusCode,
                                response.Headers.ToString(),
                                await response.Content.ReadAsStringAsync());

                throw new HttpRequestException("Произошла ошибка при получении профиля пользователя.");
            }

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

            //identity.AddOptionalClaim(ClaimTypes.NameIdentifier, user.Value<string>("uid"), Options.ClaimsIssuer)
            //        .AddOptionalClaim(ClaimTypes.Name, user.Value<string>("name"), Options.ClaimsIssuer)
            //        .AddOptionalClaim(ClaimTypes.GivenName, user.Value<string>("first_name"), Options.ClaimsIssuer)
            //        .AddOptionalClaim(ClaimTypes.Surname, user.Value<string>("last_name"), Options.ClaimsIssuer)
            //        .AddOptionalClaim(ClaimTypes.Email, user.Value<string>("email"), Options.ClaimsIssuer);


            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, user);

            context.RunClaimActions();

            await Options.Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
コード例 #7
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var facebookHandler = this;
            var openIdEndpoint  = $"{Options.OpenIdEndpoint}?access_token={tokens.AccessToken}";
            var response        = await Backchannel.GetAsync(openIdEndpoint, Context.RequestAborted);

            response.EnsureSuccessStatusCode();

            var tmp = await response.Content.ReadAsStringAsync();

            var regex      = new System.Text.RegularExpressions.Regex("callback\\((?<json>[ -~]+)\\);");
            var json       = JObject.Parse(regex.Match(tmp).Groups["json"].Value);
            var identifier = json.Value <string>("openid");

            if (!string.IsNullOrEmpty(identifier))
            {
                identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, identifier, ClaimValueTypes.String, Options.ClaimsIssuer));
                identity.AddClaim(new Claim("urn:qq:id", identifier, ClaimValueTypes.String, Options.ClaimsIssuer));
            }

            var content = new FormUrlEncodedContent(new Dictionary <string, string>
            {
                { "oauth_consumer_key", Options.ClientId },
                { "access_token", tokens.AccessToken },
                { "openid", identifier }
            });

            response = await Backchannel.PostAsync(Options.UserInformationEndpoint, content);

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

            info.Add("id", identifier);
            var name = info.Value <string>("nickname");

            if (!string.IsNullOrEmpty(name))
            {
                identity.AddClaim(new Claim(ClaimTypes.Name, name, ClaimValueTypes.String, Options.ClaimsIssuer));
                identity.AddClaim(new Claim("urn:qq:name", name, ClaimValueTypes.String, Options.ClaimsIssuer));
            }
            var figure = info.Value <string>("figureurl_qq_1");

            if (!string.IsNullOrEmpty(name))
            {
                identity.AddClaim(new Claim("urn:qq:figure", figure, ClaimValueTypes.String, Options.ClaimsIssuer));
            }
            //JObject user = JObject.Parse(await async.Content.ReadAsStringAsync());
            OAuthCreatingTicketContext context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, facebookHandler.Context, facebookHandler.Scheme, facebookHandler.Options, facebookHandler.Backchannel, tokens);

            context.RunClaimActions();
            await facebookHandler.Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, facebookHandler.Scheme.Name));
        }
コード例 #8
0
ファイル: QQHandler.cs プロジェクト: wind2006/osharp-1
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            ClaimsIdentity identity,
            AuthenticationProperties properties,
            OAuthTokenResponse tokens)
        {
            //获取OpenId
            string openIdEndpoint = QueryHelpers.AddQueryString(Options.OpenIdEndpoint, "access_token", tokens.AccessToken);
            HttpResponseMessage openIdResponse = await Backchannel.GetAsync(openIdEndpoint, Context.RequestAborted);

            if (!openIdResponse.IsSuccessStatusCode)
            {
                throw new HttpRequestException($"未能检索QQ Connect的OpenId(返回状态码:{openIdResponse.StatusCode}),请检查access_token是正确。");
            }
            JObject json   = JObject.Parse(企鹅的返回不拘一格传入这里统一转换为JSON(await openIdResponse.Content.ReadAsStringAsync()));
            string  openId = GetOpenId(json);

            //获取用户信息
            Dictionary <string, string> parameters = new Dictionary <string, string>
            {
                { "openid", openId },
                { "access_token", tokens.AccessToken },
                { "oauth_consumer_key", Options.ClientId }
            };
            string userInformationEndpoint = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, parameters);
            HttpResponseMessage userInformationResponse = await Backchannel.GetAsync(userInformationEndpoint, Context.RequestAborted);

            if (!userInformationResponse.IsSuccessStatusCode)
            {
                throw new HttpRequestException($"未能检索QQ Connect的用户信息(返回状态码:{userInformationResponse.StatusCode}),请检查参数是否正确。");
            }

#if NETSTANDARD
            JObject payload = JObject.Parse(await userInformationResponse.Content.ReadAsStringAsync());
            //identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, openId, ClaimValueTypes.String, Options.ClaimsIssuer));
            payload.Add("openid", openId);
            OAuthCreatingTicketContext context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload);
            context.RunClaimActions();
            await Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
#else
            string json2 = await userInformationResponse.Content.ReadAsStringAsync();

            JObject      payload  = JObject.Parse(json2);
            JsonDocument document = JsonDocument.Parse(json2);
            //identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, openId, ClaimValueTypes.String, Options.ClaimsIssuer));
            payload.Add("openid", openId);
            OAuthCreatingTicketContext context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, document.RootElement);
            context.RunClaimActions();
            await Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
#endif
        }
コード例 #9
0
        /// <summary>
        ///  Step2:通过Authorization Code获取Access Token
        ///  http://wiki.connect.qq.com/%E4%BD%BF%E7%94%A8authorization_code%E8%8E%B7%E5%8F%96access_token
        /// </summary>
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri)
        {
            var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, new Dictionary <string, string>()
            {
                ["client_id"]     = Options.ClientId,
                ["client_secret"] = Options.ClientSecret,
                ["code"]          = code,
                ["grant_type"]    = "authorization_code",
                ["redirect_uri"]  = redirectUri,
            });

            var response = await Backchannel.GetAsync(address);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("An error occurred while retrieving an access token: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync());

                return(OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")));
            }

            // 成功:  access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14
            // 失败:  callback( {"error":123456 ,"error_description":"**************"} );

            var responseString = await response.Content.ReadAsStringAsync();

            if (responseString.StartsWith("callback"))
            {
                Logger.LogError("An error occurred while retrieving an access token: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync());

                return(OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")));
            }

            JObject payload = new JObject();

            var responseParams = responseString.Split('&');

            foreach (var parm in responseParams)
            {
                var kv = parm.Split('=');

                payload[kv[0]] = kv[1];
            }

            return(OAuthTokenResponse.Success(payload));
        }
コード例 #10
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync([NotNull] ClaimsIdentity identity,
                                                                               [NotNull] AuthenticationProperties properties, [NotNull] OAuthTokenResponse tokens)
        {
            var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string>
            {
                ["access_token"] = tokens.AccessToken,
                ["v"]            = !string.IsNullOrEmpty(Options.ApiVersion) ? Options.ApiVersion : VkontakteAuthenticationDefaults.ApiVersion
            });

            if (Options.Fields.Count != 0)
            {
                address = QueryHelpers.AddQueryString(address, "fields", string.Join(",", Options.Fields));
            }

            HttpResponseMessage response = null;

            try
            {
                response = await Backchannel.GetAsync(address, Context.RequestAborted);

                if (!response.IsSuccessStatusCode)
                {
                    Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                    "returned a {Status} response with the following payload: {Headers} {Body}.",
                                    /* Status: */ response.StatusCode,
                                    /* Headers: */ response.Headers.ToString(),
                                    /* Body: */ await response.Content.ReadAsStringAsync());

                    throw new HttpRequestException("An error occurred while retrieving the user profile.");
                }

                var container = JObject.Parse(await response.Content.ReadAsStringAsync());
                var payload   = container["response"].First as JObject;

                if (tokens.Response["email"] != null)
                {
                    payload.Add("email", tokens.Response["email"]);
                }

                var principal = new ClaimsPrincipal(identity);
                var context   = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload);
                context.RunClaimActions(payload);

                await Options.Events.CreatingTicket(context);

                return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
            }
            finally
            {
                response?.Dispose();
            }
        }
コード例 #11
0
        protected override async Task <HandleRequestResult> HandleRemoteAuthenticateAsync()
        {
            IQueryCollection query = Request.Query;

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

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

            string ticket    = query["ticket"].FirstOrDefault();
            string returnUrl = query["returnUrl"].FirstOrDefault();

            if (ticket == null)
            {
                return(HandleRequestResult.Fail("Ticket should never be null."));
            }

            string serviceUri         = CurrentUri;
            string userInformationUrl = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string>
            {
                ["ticket"]  = ticket,
                ["service"] = GetService(CurrentUri)
            });
            HttpResponseMessage response = await Backchannel.GetAsync(userInformationUrl);

            var xdoc = XDocument.Load(await response.Content.ReadAsStreamAsync());

            string xmlErrorMessage = GetXmlErrorMessage(xdoc);

            if (xmlErrorMessage != null)
            {
                return(HandleRequestResult.Fail(xmlErrorMessage));
            }

            IEnumerable <Claim> claims = GetXmlClaims(xdoc);
            var identity = new ClaimsIdentity(claims, ClaimsIssuer);

            var token = OAuthTokenResponse.Failed(new Exception("Token not available."));
            AuthenticationTicket authenticationTicket = await CreateTicketAsync(identity, properties, token);

            if (authenticationTicket != null)
            {
                return(HandleRequestResult.Success(authenticationTicket));
            }
            else
            {
                return(HandleRequestResult.Fail("Failed to retrieve user information from remote user.", properties));
            }
        }
コード例 #12
0
        /// <summary>	Creates ticket asynchronous. </summary>
        /// <exception cref="HttpRequestException"> Thrown when a HTTP Request error condition occurs. </exception>
        /// <param name="identity">     The identity. </param>
        /// <param name="properties">	The properties. </param>
        /// <param name="tokens">	    The tokens. </param>
        /// <returns>	The new ticket asynchronous. </returns>
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity,
                                                                               AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            // construct endpoint-address
            var endpoint =
                QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "access_token", tokens.AccessToken);

            // query endpoint
            var response = await Backchannel.GetAsync(endpoint, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                throw new HttpRequestException(
                          $"An error occurred when retrieving Facebook user information ({response.StatusCode}). Please check if the authentication information is correct and the corresponding Facebook Graph API is enabled.");
            }

            // parse endpoint-response
            var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
            var user    = JsonConvert.DeserializeObject <AmazonUser>(await response.Content.ReadAsStringAsync());

            // parse Amazon-content manually
            var identifier = user.UserId;

            if (!string.IsNullOrEmpty(identifier))
            {
                identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, identifier, ClaimValueTypes.String,
                                            Options.ClaimsIssuer));
            }

            var name = user.Name;

            if (!string.IsNullOrEmpty(name))
            {
                identity.AddClaim(new Claim(ClaimTypes.Name, name, ClaimValueTypes.String, Options.ClaimsIssuer));
            }

            var email = user.EMail;

            if (!string.IsNullOrEmpty(email))
            {
                identity.AddClaim(new Claim(ClaimTypes.Email, email, ClaimValueTypes.String, Options.ClaimsIssuer));
            }

            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme,
                                                         Options, Backchannel, tokens, payload);

            context.RunClaimActions();

            await Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
コード例 #13
0
    protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] OAuthCodeExchangeContext context)
    {
        // See https://opendocs.alipay.com/apis/api_9/alipay.system.oauth.token for details.
        var tokenRequestParameters = new SortedDictionary <string, string?>()
        {
            ["app_id"]     = Options.ClientId,
            ["charset"]    = "utf-8",
            ["code"]       = context.Code,
            ["format"]     = "JSON",
            ["grant_type"] = "authorization_code",
            ["method"]     = "alipay.system.oauth.token",
            ["sign_type"]  = "RSA2",
            ["timestamp"]  = Clock.UtcNow.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
            ["version"]    = "1.0",
        };

        tokenRequestParameters.Add("sign", GetRSA2Signature(tokenRequestParameters));

        // PKCE https://tools.ietf.org/html/rfc7636#section-4.5, see BuildChallengeUrl
        if (context.Properties.Items.TryGetValue(OAuthConstants.CodeVerifierKey, out var codeVerifier))
        {
            tokenRequestParameters.Add(OAuthConstants.CodeVerifierKey, codeVerifier);
            context.Properties.Items.Remove(OAuthConstants.CodeVerifierKey);
        }

        var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, tokenRequestParameters);

        using var response = await Backchannel.GetAsync(address, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);

        if (!response.IsSuccessStatusCode)
        {
            await Log.AccessTokenError(Logger, response, Context.RequestAborted);

            return(OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")));
        }

        using var stream = await response.Content.ReadAsStreamAsync(Context.RequestAborted);

        using var document = JsonDocument.Parse(stream);

        var mainElement = document.RootElement.GetProperty("alipay_system_oauth_token_response");

        if (!ValidateReturnCode(mainElement, out var code))
        {
            return(OAuthTokenResponse.Failed(new Exception($"An error (Code:{code}) occurred while retrieving an access token.")));
        }

        var payload = JsonDocument.Parse(mainElement.GetRawText());

        return(OAuthTokenResponse.Success(payload));
    }
コード例 #14
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            ClaimsIdentity identity,
            Microsoft.AspNetCore.Authentication.AuthenticationProperties properties,
            OAuthTokenResponse tokens)
        {
            var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "access_token", tokens.AccessToken);

            if (Options.Fields.Count != 0)
            {
                address = QueryHelpers.AddQueryString(address, "fields", string.Join(",", Options.Fields));
            }

            var response = await Backchannel.GetAsync(address, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("Произошла ошибка при получении профиля пользователя: удаленный сервер " +
                                "вернул {Status} ответ со следующей информацией: {Headers} {Body}.",
                                response.StatusCode,
                                response.Headers.ToString(),
                                await response.Content.ReadAsStringAsync());

                throw new HttpRequestException("Произошла ошибка при получении профиля пользователя.");
            }

            var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
            var user    = (JObject)payload["response"][0];

            foreach (var scope in Options.Scope)
            {
                var scope_value = tokens.Response.Value <string>(scope);
                if (!string.IsNullOrEmpty(scope_value))
                {
                    user.Add(scope, scope_value);
                }
            }

            identity.AddOptionalClaim(ClaimTypes.NameIdentifier, user.Value <string>("uid"), Options.ClaimsIssuer)
            .AddOptionalClaim(ClaimTypes.GivenName, user.Value <string>("first_name"), Options.ClaimsIssuer)
            .AddOptionalClaim(ClaimTypes.Surname, user.Value <string>("last_name"), Options.ClaimsIssuer)
            .AddOptionalClaim(ClaimTypes.Email, user.Value <string>("email"), Options.ClaimsIssuer);


            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, user);

            context.RunClaimActions();

            await Options.Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
コード例 #15
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync([NotNull] ClaimsIdentity identity, [NotNull] AuthenticationProperties properties, [NotNull] OAuthTokenResponse tokens)
        {
            var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string>
            {
                ["access_token"] = tokens.AccessToken,
                ["openid"]       = tokens.Response.Value <string>("openid")
            });

            HttpResponseMessage response = null;

            try
            {
                response = await Backchannel.GetAsync(address);

                if (!response.IsSuccessStatusCode)
                {
                    Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                    "returned a {Status} response with the following payload: {Headers} {Body}.",
                                    /* Status: */ response.StatusCode,
                                    /* Headers: */ response.Headers.ToString(),
                                    /* Body: */ await response.Content.ReadAsStringAsync());

                    throw new HttpRequestException("An error occurred while retrieving user information.");
                }

                var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
                if (!string.IsNullOrEmpty(payload.Value <string>("errcode")))
                {
                    Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                    "returned a {Status} response with the following payload: {Headers} {Body}.",
                                    /* Status: */ response.StatusCode,
                                    /* Headers: */ response.Headers.ToString(),
                                    /* Body: */ await response.Content.ReadAsStringAsync());

                    throw new HttpRequestException("An error occurred while retrieving user information.");
                }

                var principal = new ClaimsPrincipal(identity);
                var context   = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload);
                context.RunClaimActions(payload);

                await Options.Events.CreatingTicket(context);

                return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
            }
            finally
            {
                response?.Dispose();
            }
        }
コード例 #16
0
        /// <summary>
        /// 微信登录
        /// </summary>
        /// <returns></returns>
        private string GetAccessToken()
        {
            var parameters = new Dictionary <string, string>
            {
                { "corpid", Options.AppId },
                { "corpsecret", Options.AppKey }
            };

            var loginurl = QueryHelpers.AddQueryString("https://qyapi.weixin.qq.com/cgi-bin/gettoken", parameters);
            var result   = Backchannel.GetAsync(loginurl).Result.Content.ReadAsStringAsync().Result;
            var res      = Newtonsoft.Json.JsonConvert.DeserializeObject <WeChatCompanyAccessTokenResult>(result);

            return(res.access_token);
        }
コード例 #17
0
ファイル: DingTalkHandler.cs プロジェクト: zoulei0718/fulusso
        /// <summary>
        ///2.1子步骤>>向认证服务器申请令牌
        /// </summary>
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
        {
            var tokenRequestParameters = new Dictionary <string, string>
            {
                { "appid", Options.ClientId },
                { "appsecret", Options.ClientSecret }
            };

            var userInfoEndpoint = QueryHelpers.AddQueryString(Options.TokenEndpoint, tokenRequestParameters);

            var response = await Backchannel.GetAsync(userInfoEndpoint, Context.RequestAborted);

            return(response.IsSuccessStatusCode ? OAuthTokenResponse.Success(JsonDocument.Parse(await response.Content.ReadAsStringAsync())) : OAuthTokenResponse.Failed(new Exception("OAuth token failure")));
        }
コード例 #18
0
        /// <summary>
        ///  获取 相关令牌
        /// </summary>
        /// <param name="code">授权码</param>
        /// <param name="redirectUri">回调地址</param>
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri)
        {
            var query = new QueryBuilder
            {
                { "appid", Options.AppId },
                { "secret", Options.AppSecret },
                { "code", code },
                { "grant_type", "authorization_code" },
                { "redirect_uri", redirectUri }
            };
            var response = await Backchannel.GetAsync(Options.TokenEndpoint + query, Context.RequestAborted);

            response.EnsureSuccessStatusCode();
            return(new OAuthTokenResponse(JObject.Parse(await response.Content.ReadAsStringAsync())));
        }
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string>
            {
                ["access_token"] = tokens.AccessToken,
                ["openid"]       = tokens.Response.GetRootString("openid")
            });

            var response = await Backchannel.GetAsync(address);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync());

                throw new HttpRequestException("An error occurred while retrieving user information.");
            }

            var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());

            if (!string.IsNullOrEmpty(payload.GetRootString("errcode")))
            {
                Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync());

                throw new HttpRequestException("An error occurred while retrieving user information.");
            }

            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);

            context.RunClaimActions();

            await Events.CreatingTicket(context);

            // TODO: 此处通过唯一的 CorrelationId, 将 properties生成的State缓存删除
            var state = Request.Query["state"];

            var stateCacheKey = WeChatOfficialStateCacheItem.CalculateCacheKey(state.ToString().ToMd5(), null);
            await Cache.RemoveAsync(stateCacheKey, token : Context.RequestAborted);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] OAuthCodeExchangeContext context)
        {
            // See https://opendocs.alipay.com/apis/api_9/alipay.system.oauth.token for details.
            var sortedParams = new SortedDictionary <string, string>()
            {
                ["app_id"]     = Options.ClientId,
                ["charset"]    = "utf-8",
                ["code"]       = context.Code,
                ["format"]     = "JSON",
                ["grant_type"] = "authorization_code",
                ["method"]     = "alipay.system.oauth.token",
                ["sign_type"]  = "RSA2",
                ["timestamp"]  = Clock.UtcNow.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
                ["version"]    = "1.0",
            };

            sortedParams.Add("sign", GetRSA2Signature(sortedParams));

            string address = QueryHelpers.AddQueryString(Options.TokenEndpoint, sortedParams !);

            using var response = await Backchannel.GetAsync(address, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("An error occurred while retrieving an access token: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync(Context.RequestAborted));

                return(OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")));
            }

            using var stream = await response.Content.ReadAsStreamAsync(Context.RequestAborted);

            using var document = JsonDocument.Parse(stream);

            var mainElement = document.RootElement.GetProperty("alipay_system_oauth_token_response");

            if (!ValidateReturnCode(mainElement, out string code))
            {
                return(OAuthTokenResponse.Failed(new Exception($"An error (Code:{code}) occurred while retrieving an access token.")));
            }

            var payload = JsonDocument.Parse(mainElement.GetRawText());

            return(OAuthTokenResponse.Success(payload));
        }
コード例 #21
0
    protected override async Task <AuthenticationTicket> CreateTicketAsync(
        [NotNull] ClaimsIdentity identity,
        [NotNull] AuthenticationProperties properties,
        [NotNull] OAuthTokenResponse tokens)
    {
        var parameters = new Dictionary <string, string?>
        {
            ["access_token"] = tokens.AccessToken,
            ["openid"]       = tokens.Response?.RootElement.GetString("openid"),
        };

        var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, parameters);

        using var response = await Backchannel.GetAsync(address);

        if (!response.IsSuccessStatusCode)
        {
            await Log.UserProfileErrorAsync(Logger, response, Context.RequestAborted);

            throw new HttpRequestException("An error occurred while retrieving user information.");
        }

        var json = await response.Content.ReadAsStringAsync(Context.RequestAborted);

        using var payload = JsonDocument.Parse(json);

        var errorCode = payload.RootElement.GetString("errcode");

        if (!string.IsNullOrEmpty(errorCode))
        {
            Log.UserProfileErrorCode(Logger, errorCode, response.Headers.ToString(), json);
            throw new HttpRequestException("An error occurred while retrieving user information.");
        }

        (var openId, var unionId) = GetUserIdentifier(payload.RootElement);
        var nameIdentifier = !string.IsNullOrWhiteSpace(unionId) ? unionId : openId;

        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, nameIdentifier !, ClaimValueTypes.String, Options.ClaimsIssuer));

        var principal = new ClaimsPrincipal(identity);
        var context   = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);

        context.RunClaimActions();

        await Events.CreatingTicket(context);

        return(new AuthenticationTicket(context.Principal !, context.Properties, Scheme.Name));
    }
コード例 #22
0
    protected override async Task <AuthenticationTicket> CreateTicketAsync(
        [NotNull] ClaimsIdentity identity,
        [NotNull] AuthenticationProperties properties,
        [NotNull] OAuthTokenResponse tokens)
    {
        (var errorCode, var userId) = await GetUserIdentifierAsync(tokens);

        if (errorCode != 0 || string.IsNullOrEmpty(userId))
        {
            throw new Exception($"An error (Code:{errorCode}) occurred while retrieving the user identifier.");
        }

        // See https://open.work.weixin.qq.com/api/doc/90000/90135/90196 for details.
        var parameters = new Dictionary <string, string?>
        {
            ["access_token"] = tokens.AccessToken,
            ["userid"]       = userId,
        };

        var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, parameters);

        using var response = await Backchannel.GetAsync(address, Context.RequestAborted);

        if (!response.IsSuccessStatusCode)
        {
            await Log.UserProfileErrorAsync(Logger, response, Context.RequestAborted);

            throw new HttpRequestException("An error occurred while retrieving user information.");
        }

        using var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync(Context.RequestAborted));

        errorCode = payload.RootElement.GetProperty("errcode").GetInt32();
        if (errorCode != 0)
        {
            Log.UserProfileErrorCode(Logger, errorCode, payload.RootElement.GetString("errmsg"));
            throw new Exception("An error occurred while retrieving user information.");
        }

        var principal = new ClaimsPrincipal(identity);
        var context   = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);

        context.RunClaimActions();

        await Events.CreatingTicket(context);

        return(new AuthenticationTicket(context.Principal !, context.Properties, Scheme.Name));
    }
コード例 #23
0
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri)
        {
            log.LogDebug("ExchangeCodeAsync called with code " + code + " redirectUri " + redirectUri);
            //var queryBuilder = new QueryBuilder()
            //{
            //    { "grant_type", "authorization_code" },
            //    { "code", code },
            //    { "redirect_uri", redirectUri },
            //    { "client_id", Options.AppId },
            //    { "client_secret", Options.AppSecret },
            //};

            var currentSite = await GetSite();

            var tenantFbOptions
                = new MultiTenantFacebookOptionsResolver(
                      Options,
                      currentSite,
                      multiTenantOptions);


            var queryBuilder = new QueryBuilder()
            {
                { "grant_type", "authorization_code" },
                { "code", code },
                { "redirect_uri", tenantFbOptions.ResolveRedirectUrl(redirectUri) },
                { "client_id", tenantFbOptions.AppId },
                { "client_secret", tenantFbOptions.AppSecret },
            };

            var response = await Backchannel.GetAsync(Options.TokenEndpoint + queryBuilder.ToString(), Context.RequestAborted);

            response.EnsureSuccessStatusCode();

            var form    = new FormCollection(FormReader.ReadForm(await response.Content.ReadAsStringAsync()));
            var payload = new JObject();

            foreach (string key in form.Keys)
            {
                //payload.Add(string.Equals(key, "expires", StringComparison.OrdinalIgnoreCase) ? "expires_in" : key, form[key]);
                payload.Add(string.Equals(key, "expires", StringComparison.OrdinalIgnoreCase) ? "expires_in" : key, (string)form[key]);
            }

            // The refresh token is not available.
            return(new OAuthTokenResponse(payload));
        }
コード例 #24
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            [NotNull] ClaimsIdentity identity,
            [NotNull] AuthenticationProperties properties,
            [NotNull] OAuthTokenResponse tokens)
        {
            string address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string?>
            {
                ["access_token"] = tokens.AccessToken,
                ["v"]            = !string.IsNullOrEmpty(Options.ApiVersion) ? Options.ApiVersion : VkontakteAuthenticationDefaults.ApiVersion
            });

            if (Options.Fields.Count != 0)
            {
                address = QueryHelpers.AddQueryString(address, "fields", string.Join(",", Options.Fields));
            }

            using var response = await Backchannel.GetAsync(address, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync(Context.RequestAborted));

                throw new HttpRequestException("An error occurred while retrieving the user profile.");
            }

            using var container  = JsonDocument.Parse(await response.Content.ReadAsStringAsync(Context.RequestAborted));
            using var enumerator = container.RootElement.GetProperty("response").EnumerateArray();
            var payload = enumerator.First();

            var principal = new ClaimsPrincipal(identity);
            var context   = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload);

            context.RunClaimActions();

            // Re-run to get the email claim from the tokens response
            context.RunClaimActions(tokens.Response.RootElement);

            await Options.Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal !, context.Properties, Scheme.Name));
        }
コード例 #25
0
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri)
        {
            var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, new Dictionary <string, string>()
            {
                ["appid"]      = Options.ClientId,
                ["secret"]     = Options.ClientSecret,
                ["code"]       = code,
                ["grant_type"] = "authorization_code"
            });

            HttpResponseMessage response = null;

            try
            {
                response = await Backchannel.GetAsync(address);

                if (!response.IsSuccessStatusCode)
                {
                    Logger.LogError("An error occurred while retrieving an access token: the remote server " +
                                    "returned a {Status} response with the following payload: {Headers} {Body}.",
                                    /* Status: */ response.StatusCode,
                                    /* Headers: */ response.Headers.ToString(),
                                    /* Body: */ await response.Content.ReadAsStringAsync());

                    return(OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")));
                }

                var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
                if (!string.IsNullOrEmpty(payload.Value <string>("errcode")))
                {
                    Logger.LogError("An error occurred while retrieving an access token: the remote server " +
                                    "returned a {Status} response with the following payload: {Headers} {Body}.",
                                    /* Status: */ response.StatusCode,
                                    /* Headers: */ response.Headers.ToString(),
                                    /* Body: */ await response.Content.ReadAsStringAsync());

                    return(OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")));
                }
                return(OAuthTokenResponse.Success(payload));
            }
            finally
            {
                response?.Dispose();
            }
        }
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "access_token", tokens.AccessToken);

            address = QueryHelpers.AddQueryString(address, "v", Options.ApiVersion);

            if (Options.Fields.Count != 0)
            {
                address = QueryHelpers.AddQueryString(address, "fields", string.Join(",", Options.Fields));
            }

            var response = await Backchannel.GetAsync(address, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync());

                throw new HttpRequestException("An error occurred while retrieving the user profile.");
            }

            var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
            var user    = (JObject)payload["response"][0];

            foreach (var scope in Options.Scope)
            {
                var scope_value = tokens.Response.Value <string>(scope);
                if (!string.IsNullOrEmpty(scope_value))
                {
                    user.Add(scope, scope_value);
                }
            }

            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, user);

            context.RunClaimActions();


            await Options.Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
コード例 #27
0
        /// <summary>
        /// 创建身份票据(这是第三步)
        /// </summary>
        /// <param name="identity"></param>
        /// <param name="properties"></param>
        /// <param name="tokens"></param>
        /// <returns></returns>
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            ClaimsIdentity identity,
            AuthenticationProperties properties,
            OAuthTokenResponse tokens)
        {
            var openId  = GetOpenId(tokens.Response);
            var unionId = GetUnionId(tokens.Response);
            // 构造用户信息JsonElement
            var payloadDic = new Dictionary <string, object>()
            {
                ["openid"] = openId
            };
            var userInfo = JsonDocument.Parse(JsonSerializer.Serialize(payloadDic));

            //微信获取用户信息是需要开通权限的,没有开通权限的只能用openId来标示用户
            if (!string.IsNullOrEmpty(unionId))
            {
                //获取用户信息
                var parameters = new Dictionary <string, string>
                {
                    { "openid", openId },
                    { "access_token", tokens.AccessToken },
                    { "lang", "zh-CN" } //如果是多语言,这个参数该怎么获取?
                };
                var userInfoEndpoint = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, parameters);
                var userInfoResponse = await Backchannel.GetAsync(userInfoEndpoint, Context.RequestAborted);

                if (!userInfoResponse.IsSuccessStatusCode)
                {
                    throw new HttpRequestException(
                              $"未能获取到微信用户个人信息(返回状态码:{userInfoResponse.StatusCode}),请检查access_token是正确。");
                }

                userInfo = JsonDocument.Parse(await userInfoResponse.Content.ReadAsStringAsync());
            }

            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme,
                                                         Options, Backchannel, tokens, userInfo.RootElement);

            context.RunClaimActions();
            await Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
コード例 #28
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "access_token", tokens.AccessToken);

            address = QueryHelpers.AddQueryString(address, "v", Options.ApiVersion);

            if (Options.Fields.Count != 0)
            {
                address = QueryHelpers.AddQueryString(address, "fields", string.Join(",", Options.Fields));
            }

            var response = await Backchannel.GetAsync(address, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
                                "returned a {Status} response with the following payload: {Headers} {Body}.",
                                /* Status: */ response.StatusCode,
                                /* Headers: */ response.Headers.ToString(),
                                /* Body: */ await response.Content.ReadAsStringAsync());

                throw new HttpRequestException("An error occurred while retrieving the user profile.");
            }

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

            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload);
            var user    = (JObject)payload["response"][0];

            identity.AddOptionalClaim(ClaimTypes.NameIdentifier, VkontakteHelper.GetId(user), Options.ClaimsIssuer)
            .AddOptionalClaim(ClaimTypes.Name, VkontakteHelper.GetName(user), Options.ClaimsIssuer)
            .AddOptionalClaim(ClaimTypes.GivenName, VkontakteHelper.GetFirstName(user), Options.ClaimsIssuer)
            .AddOptionalClaim(ClaimTypes.Surname, VkontakteHelper.GetLastName(user), Options.ClaimsIssuer)
            .AddOptionalClaim(ClaimTypes.Hash, VkontakteHelper.GetHash(user), Options.ClaimsIssuer)
            .AddOptionalClaim("urn:vkontakte:photo:link", VkontakteHelper.GetPhoto(user), Options.ClaimsIssuer)
            .AddOptionalClaim("urn:vkontakte:photo_thumb:link", VkontakteHelper.GetPhotoThumbnail(user), Options.ClaimsIssuer);

            context.RunClaimActions();

            await Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
コード例 #29
0
        /// <summary>
        ///  验证用户,并与本机通信
        /// </summary>
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var identifier = WeChatHelper.GetId(tokens.Response);

            if (!string.IsNullOrEmpty(identifier))
            {
                identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, identifier, ClaimValueTypes.String, Options.ClaimsIssuer));
                identity.AddClaim(new Claim("urn:wechat:id", identifier, ClaimValueTypes.String, Options.ClaimsIssuer));
            }
            var query = new QueryBuilder
            {
                { "access_token", tokens.AccessToken },
                { "openid", identifier }
            };
            var response = await Backchannel.GetAsync(Options.UserInformationEndpoint + query, Context.RequestAborted);

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

            var notification = new OAuthCreatingTicketContext(Context, Options, Backchannel, tokens, payload)
            {
                Properties = properties,
                Principal  = new ClaimsPrincipal(identity)
            };

            var name = WeChatHelper.GetName(payload);

            if (!string.IsNullOrEmpty(name))
            {
                identity.AddClaim(new Claim(ClaimTypes.Name, name, ClaimValueTypes.String, Options.ClaimsIssuer));
                identity.AddClaim(new Claim("urn:wechat:name", name, ClaimValueTypes.String, Options.ClaimsIssuer));
            }
            var img = WeChatHelper.GetHeadImage(payload);

            if (!string.IsNullOrEmpty(img))
            {
                identity.AddClaim(new Claim("urn:wechat:headimgurl", img, ClaimValueTypes.String, Options.ClaimsIssuer));
            }

            await Options.Events.CreatingTicket(notification);

            return(new AuthenticationTicket(notification.Principal, notification.Properties, notification.Options.AuthenticationScheme));
        }
    protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] OAuthCodeExchangeContext context)
    {
        var tokenRequestParameters = new Dictionary <string, string?>()
        {
            ["appid"]      = Options.ClientId,
            ["secret"]     = Options.ClientSecret,
            ["code"]       = context.Code,
            ["grant_type"] = "authorization_code",
        };

        // PKCE https://tools.ietf.org/html/rfc7636#section-4.5, see BuildChallengeUrl
        if (context.Properties.Items.TryGetValue(OAuthConstants.CodeVerifierKey, out var codeVerifier))
        {
            tokenRequestParameters.Add(OAuthConstants.CodeVerifierKey, codeVerifier !);
            context.Properties.Items.Remove(OAuthConstants.CodeVerifierKey);
        }

        var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, tokenRequestParameters);

        using var response = await Backchannel.GetAsync(address);

        if (!response.IsSuccessStatusCode)
        {
            await Log.ExchangeCodeErrorAsync(Logger, response, Context.RequestAborted);

            return(OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")));
        }

        var json = await response.Content.ReadAsStringAsync(Context.RequestAborted);

        var payload = JsonDocument.Parse(json);

        var errorCode = payload.RootElement.GetString("errcode");

        if (!string.IsNullOrEmpty(errorCode))
        {
            Log.ExchangeCodeErrorCode(Logger, errorCode, response.Headers.ToString(), json);
            return(OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")));
        }

        return(OAuthTokenResponse.Success(payload));
    }