예제 #1
0
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
        {
            var tokenRequestParameters = new List <KeyValuePair <string, string> >
            {
                new KeyValuePair <string, string>("appid", Options.ClientId),
                new KeyValuePair <string, string>("secret", Options.ClientSecret),
                new KeyValuePair <string, string>("code", context.Code),
                new KeyValuePair <string, string>("grant_type", "authorization_code"),
            };

            var urlEncodedContent = new FormUrlEncodedContent(tokenRequestParameters);

            var response =
                await Backchannel.PostAsync(Options.TokenEndpoint, urlEncodedContent, Context.RequestAborted);

            //var response = await Backchannel.SendAsync(new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint)
            //{
            //    Headers = {
            //        Accept = {
            //            new MediaTypeWithQualityHeaderValue("application/json")
            //        }
            //    },
            //    Content = urlEncodedContent
            //}, Context.RequestAborted);

            return(response.IsSuccessStatusCode ? OAuthTokenResponse.Success(JsonDocument.Parse(await response.Content.ReadAsStringAsync())) : OAuthTokenResponse.Failed(new Exception("OAuth token failure")));
        }
예제 #2
0
        /// <summary>
        ///  与本站通信,可获取用户基本信息
        /// </summary>
        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>[ -~]+)\\);");
            // just throw it when error appears.
            var json       = JObject.Parse(regex.Match(tmp).Groups["json"].Value);
            var identifier = TencentHelper.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 notification = new OAuthCreatingTicketContext(Context, Options, Backchannel, tokens, info)
            {
                Properties = properties,
                Principal  = new ClaimsPrincipal(identity)
            };

            var name = TencentHelper.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 = TencentHelper.GetFigure(info);

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

            await Options.Events.CreatingTicket(notification);

            return(new AuthenticationTicket(notification.Principal, notification.Properties, notification.Options.AuthenticationScheme));
        }
        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));
        }
예제 #4
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            ClaimsIdentity identity,
            AuthenticationProperties properties,
            OAuthTokenResponse tokens)
        {
            // Get the DingTalk user
            var timestamp  = GetTimeStamp();
            var requestUri = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase)
            {
                { "accessKey", Options.ClientId },
                { "timestamp", timestamp },
                { "signature", Signature(timestamp, Options.ClientSecret) }
            });

            var requestContent = new StringContent(JsonSerializer.Serialize(new Dictionary <string, string>
            {
                { "tmp_auth_code", tokens.AccessToken }
            }), Encoding.UTF8, MediaTypeNames.Application.Json);

            var response = await Backchannel.PostAsync(requestUri, requestContent, Context.RequestAborted);

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

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

            using var payload = JsonDocument.Parse(responseContent);

            int status = payload.RootElement.GetProperty("errcode").GetInt32();

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

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

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

            context.RunClaimActions();

            await Options.Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
예제 #5
0
        private async Task <string> GetJson(string scope, string access_token)
        {
            var endpoint = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "access_token", access_token);
            var data     = "clientId=" + Options.ClientId;

            data += "&accessToken=" + access_token;
            data += "&resourceId=1&kapsam=" + scope;
            var contentPost         = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");
            var userRequestResponse = await Backchannel.PostAsync(new Uri(Options.UserInformationEndpoint), contentPost).ContinueWith(
                (postTask) => postTask.Result.EnsureSuccessStatusCode());

            return(await userRequestResponse.Content.ReadAsStringAsync());
        }
예제 #6
0
        /// <summary>
        /// 3.通过令牌获取用户并创建Ticket
        /// </summary>
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            ClaimsIdentity identity,
            AuthenticationProperties properties,
            OAuthTokenResponse tokens)
        {
            var code = properties.GetTokenValue("code");

            var timestamp = ((DateTime.Now.Ticks - new DateTime(1970, 1, 1).ToLocalTime().Ticks) / 10000).ToString();

            var signature = HMacSha256.Compute(timestamp, Options.ClientSecret);

            var parameters = new Dictionary <string, string>
            {
                { "accessKey", Options.ClientId },
                { "timestamp", timestamp },
                { "signature", signature }
            };

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

            var response = await Backchannel.PostAsync(userInfoEndpoint, new StringContent($"{{ \"tmp_auth_code\":\"{code}\"}}"), Context.RequestAborted);

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

            using (var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()))
            {
                payload.RootElement.TryGetProperty("errcode", out var resCode);

                if (resCode.GetInt32() != 0)
                {
                    throw new HttpRequestException($"An error occurred when retrieving Ding user information ({response.StatusCode}). Please check if the authentication information is correct.");
                }

                payload.RootElement.TryGetProperty("user_info", out var userData);

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

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

                context.Properties.ExpiresUtc = DateTimeOffset.Now.AddMinutes(15);
                return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
            }
        }
예제 #7
0
        private async Task <OAuthTokenResponse> GetTokenByAuthCodeAsync(string authCode)
        {
            if (string.IsNullOrEmpty(authCode))
            {
                throw new ArgumentNullException(nameof(authCode));
            }

            var timestamp    = GetTimeStamp();
            var scopes       = FormatScope(Options.Scope);
            var state        = GetState();
            var signMessage  = $"{scopes}{timestamp}{Options.ClientId}{state}";
            var clientSecret = SignString(signMessage).Result;

            var requestParameters = new List <KeyValuePair <string, string> >
            {
                new KeyValuePair <string, string>("client_id", Options.ClientId),
                new KeyValuePair <string, string>("code", authCode),
                new KeyValuePair <string, string>("grant_type", "authorization_code"),
                new KeyValuePair <string, string>("state", state),
                new KeyValuePair <string, string>("scope", scopes),
                new KeyValuePair <string, string>("timestamp", timestamp),
                new KeyValuePair <string, string>("token_type", "Bearer"),
                new KeyValuePair <string, string>("client_secret", clientSecret),
                new KeyValuePair <string, string>("redirect_uri", Options.CallbackPath)
            };

            var requestContent = new FormUrlEncodedContent(requestParameters);

            try
            {
                using (var response = await Backchannel.PostAsync(Options.TokenEndpoint, requestContent, Context.RequestAborted))
                {
                    if (!response.IsSuccessStatusCode)
                    {
                        throw new Exception($"ЕСИА вернул неуспешный код code: '{response.StatusCode}'.");
                    }

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

                    return(OAuthTokenResponse.Success(JObject.Parse(content)));
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message, e);
            }
        }
예제 #8
0
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
        {
            var tokenRequestParameters = new List <KeyValuePair <string, string> >
            {
                new KeyValuePair <string, string>("appid", Options.ClientId),
                new KeyValuePair <string, string>("secret", Options.ClientSecret),
                new KeyValuePair <string, string>("code", context.Code),
                new KeyValuePair <string, string>("grant_type", "authorization_code"),
            };

            var urlEncodedContent = new FormUrlEncodedContent(tokenRequestParameters);

            var response =
                await Backchannel.PostAsync(Options.TokenEndpoint, urlEncodedContent, Context.RequestAborted);

            return(response.IsSuccessStatusCode ? OAuthTokenResponse.Success(JsonDocument.Parse(await response.Content.ReadAsStringAsync())) : OAuthTokenResponse.Failed(new Exception("OAuth token failure")));
        }
예제 #9
0
        /// <summary>
        ///  回调后验证通信
        /// </summary>
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var query = new FormUrlEncodedContent(new Dictionary <string, string>
            {
                { "client_id", Options.ClientId },
                { "access_token", tokens.AccessToken }
            });
            var response = await Backchannel.PostAsync(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 identifier = YoukuHelper.GetId(payload);

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

            var name = YoukuHelper.GetName(payload);

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

            var avatar = YoukuHelper.GetAvatar(payload);

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

            await Options.Events.CreatingTicket(notification);

            return(new AuthenticationTicket(notification.Principal, notification.Properties, notification.Options.AuthenticationScheme));
        }
예제 #10
0
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(
            OAuthCodeExchangeContext context)
        {
            Dictionary <string, string> param = new Dictionary <string, string>
            {
                { "corpid", Options.ClientId },
                { "corpsecret", Options.ClientSecret }
            };

            var stringContent = new StringContent(JsonConvert.SerializeObject(param), Encoding.UTF8, "application/json");

            var response = await Backchannel.PostAsync(Options.TokenEndpoint, stringContent);

            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.")));
            }

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

            if (payload.Value <int>("errcode") != 0)
            {
                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 jsonDocument = JsonDocument.Parse(payload.ToString());

            return(OAuthTokenResponse.Success(jsonDocument));
        }
예제 #11
0
        /// <summary>
        /// 第二步:获取供应商provider_access_token。获取使用使用服务供应商coprid和ProviderSecret,获取供应商的provider_access_token
        /// </summary>
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] OAuthCodeExchangeContext context)
        {
            //1,设置post参数。获取供应商provider_access_token需要的post参数
            Dictionary <string, string> param = new Dictionary <string, string>();

            param.Add("corpid", Options.ClientId);
            param.Add("provider_secret", Options.ClientSecret);

            var stringContent = new StringContent(JsonSerializer.Serialize(param), Encoding.UTF8, "application/json");
            //2,发送请求并取得数据
            var response = await Backchannel.PostAsync(Options.TokenEndpoint, stringContent);

            //3,判断provider_access_token是否获取成功
            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 = JsonDocument.Parse(await response.Content.ReadAsStringAsync());

            if (!string.IsNullOrEmpty(payload.RootElement.GetString("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));
        }
        /// <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 query = Request.Query;
            // 用户临时授权码。跟在redirectUri后。
            var code = query["code"];

            #region 第三步:获取持久授权码
            #region 1, 请求参数配置
            var address = QueryHelpers.AddQueryString(DingTalkAuthenticationDefaults.PersistentTokenEndpoint, new Dictionary <string, string>
            {
                ["access_token"] = tokens.AccessToken,
            });

            // 获取用户基本信息的post参数:用户授权码
            Dictionary <string, string> param = new Dictionary <string, string>();
            param.Add("tmp_auth_code", code);
            var stringContent = new StringContent(JsonConvert.SerializeObject(param), Encoding.UTF8, "application/json");
            #endregion

            #region 2,发送请求并取得数据
            var response = await Backchannel.PostAsync(address, stringContent);

            #endregion
            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("An error occurred while retrieving the persistent code: 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 persistent code.");
            }
            var payload = JObject.Parse(await response.Content.ReadAsStringAsync());

            if (!(payload.Value <int>("errcode") == 0))
            {
                Logger.LogError("An error occurred while retrieving the persistent code: 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 persistent code.");
            }

            PersistentCodeDTO persistentDodeDTO = DingTalkAuthenticationHelper.GetPersistentCodeInfo(payload);
            #endregion

            #region 第四步:获取SNS_TOKEN
            address = QueryHelpers.AddQueryString(DingTalkAuthenticationDefaults.SNSTokenEndpoint, new Dictionary <string, string>
            {
                ["access_token"] = tokens.AccessToken,
            });

            // 获取用户基本信息的post参数:用户授权码
            param = new Dictionary <string, string>();
            param.Add("openid", persistentDodeDTO.OpenId);
            param.Add("persistent_code", persistentDodeDTO.Persistent_Code);
            stringContent = new StringContent(JsonConvert.SerializeObject(param), Encoding.UTF8, "application/json");

            #region 2,发送请求并取得数据
            response = await Backchannel.PostAsync(address, stringContent);

            #endregion
            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("An error occurred while retrieving the SNS_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());

                throw new HttpRequestException("An error occurred while retrieving SNS_TOKEN.");
            }
            payload = JObject.Parse(await response.Content.ReadAsStringAsync());

            if (!(payload.Value <int>("errcode") == 0))
            {
                Logger.LogError("An error occurred while retrieving the SNS_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());

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

            SNSTokenDTO snsTokenDTO = DingTalkAuthenticationHelper.GetSNSTokenInfo(payload);
            #endregion

            #region 第五步:使用SNS_TOKEN获取用户个人信息
            address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string>
            {
                ["sns_token"] = snsTokenDTO.SNS_Token,
            });

            #region 2,发送请求并取得数据
            response = await Backchannel.GetAsync(address);

            #endregion

            #region 判断请求是否成功
            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.");
            }

            payload = JObject.Parse(await response.Content.ReadAsStringAsync());
            if (!(payload.Value <int>("errcode") == 0))
            {
                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.");
            }
            #endregion
            #endregion
            //3,提取响应内容中的user_info
            #region 响应内容格式

            /*
             * {
             *     "errcode": 0,
             *     "errmsg": "ok",
             *     "user_info": {
             *         "maskedMobile": "130****1234",
             *         "nick": "张三",
             *         "openid": "liSii8KCxxxxx",
             *         "unionid": "7Huu46kk"
             *     }
             * }
             */
            #endregion
            LoginUserInfoDTO loginUserInfoDTO = DingTalkAuthenticationHelper.GetLoginUserInfo(payload);

            //4,从获取到的用户基本信息中,配置用户身份声明信息
            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, loginUserInfoDTO.OpenId, Options.ClaimsIssuer));//此行为必须项,没有NameIdentitier,会被认为用户未登录。
            identity.AddClaim(new Claim(ClaimTypes.Name, loginUserInfoDTO.Nick, Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:dingtalk:unionid", loginUserInfoDTO.UnionId, Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:dingtalk:userinfo", DingTalkAuthenticationHelper.GetUserInfo(payload), Options.ClaimsIssuer));
            //5,初始化一个OAuth正在创建ticket的上下文
            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload);
            context.RunClaimActions();
            //6,Events:OAuthEvents。Handler调用事件上的方法,这些方法(在发生处理的某些点上(提供对应用程序)的控制)
            //   CreatingTicket:在提供程序成功验证用户后调用。
            //   context:包含有关登录会话以及用户System.Security.Claims.ClaimsIdentity(身份声明)的信息。
            await Events.CreatingTicket(context);

            //7,返回认证票据
            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
예제 #13
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)
        {
            #region 1, 请求参数配置
            var query = Request.Query;
            // 用户授权码。跟在redirectUri后。
            var code = query["auth_code"];
            // 获取用户基本信息的url参数:provider_access_token
            var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string>
            {
                ["access_token"] = tokens.AccessToken,
            });
            // 获取用户基本信息的post参数:用户授权码
            Dictionary <string, string> param = new Dictionary <string, string>();
            param.Add("auth_code", code);
            var stringContent = new StringContent(JsonSerializer.Serialize(param), Encoding.UTF8, "application/json");
            #endregion

            #region 2,发送请求并取得数据
            var response = await Backchannel.PostAsync(address, stringContent);

            #endregion

            #region 判断请求是否成功
            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.RootElement.GetString("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.");
            }
            #endregion

            //3,提取响应内容中的user_info
            #region 响应内容格式

            /*
             *  {
             *     {
             *         "usertype": 5,
             *         "user_info": {
             *             "userid": "wangmaohai",
             *             "name": "王毛孩",
             *             "email": "*****@*****.**",
             *             "avatar": "http://p.qpic.cn/wwhead/nMl9ssowtibVGyrmvBiaibzDo5QicKNxARD52zpQ1kyQnOgvzzjYfaBhej0dnLqYtoyX5PbPgez1HmQ/0"
             *         },
             *         "corp_info": {
             *             "corpid": "ww4670356807022617"
             *         },
             *         "agent": []
             *     }
             *  }
             */
            #endregion
            LoginUserInfoDTO loginUserInfoDTO = WXWorkAuthenticationHelper.GetLoginUserInfo(payload);
            //4,从获取到的用户基本信息中,配置用户身份声明信息
            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, loginUserInfoDTO.UserId, Options.ClaimsIssuer));//此行为必须项,没有NameIdentitier,会被认为用户未登录。
            identity.AddClaim(new Claim(ClaimTypes.Name, loginUserInfoDTO.Name, Options.ClaimsIssuer));
            identity.AddClaim(new Claim(ClaimTypes.Email, loginUserInfoDTO.Email, Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:wxwork:userid", loginUserInfoDTO.UserId, Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:wxwork:usertype", WXWorkAuthenticationHelper.GetUserType(payload), Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:wxwork:userinfo", WXWorkAuthenticationHelper.GetUserInfo(payload), Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:wxwork:avatar", loginUserInfoDTO.Avatar, Options.ClaimsIssuer));
            identity.AddClaim(new Claim("urn:wxwork:agent", WXWorkAuthenticationHelper.GetAgent(payload), Options.ClaimsIssuer));
            //5,初始化一个OAuth正在创建ticket的上下文
            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
            context.RunClaimActions();
            //6,Events:OAuthEvents。Handler调用事件上的方法,这些方法(在发生处理的某些点上(提供对应用程序)的控制)
            //   CreatingTicket:在提供程序成功验证用户后调用。
            //   context:包含有关登录会话以及用户System.Security.Claims.ClaimsIdentity(身份声明)的信息。
            await Events.CreatingTicket(context);

            //7,返回认证票据
            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
예제 #14
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var query = Request.Query;
            var code  = query["code"];

            var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string>
            {
                ["access_token"] = tokens.AccessToken,
                ["code"]         = code
            });

            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 (payload.Value <int>("errcode") != 0)
            {
                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 userId = payload.Value <string>("UserId");

            if (StringValues.IsNullOrEmpty(userId))
            {
                throw new HttpRequestException("Non-corporate members cannot obtain corporate member information.");
            }
            var getMemberInfoAddress = QueryHelpers.AddQueryString(Options.MemberInformationEndpoint, new Dictionary <string, string>
            {
                ["access_token"] = tokens.AccessToken,
                ["userid"]       = userId
            });

            var memberInfoResponse = await Backchannel.GetAsync(getMemberInfoAddress);

            if (!memberInfoResponse.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: */ memberInfoResponse.StatusCode,
                                /* Headers: */ memberInfoResponse.Headers.ToString(),
                                /* Body: */ await memberInfoResponse.Content.ReadAsStringAsync());

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

            var memberInfoPayload = JObject.Parse(await memberInfoResponse.Content.ReadAsStringAsync());

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

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

            var userIdConvertToOpenIdAddress = QueryHelpers.AddQueryString(
                WxWorkAuthenticationDefaults.UserIdConvertToOpenIdEndpoint, new Dictionary <string, string>()
            {
                ["access_token"] = tokens.AccessToken
            });

            Dictionary <string, string> param = new Dictionary <string, string>
            {
                { "userid", userId }
            };

            var stringContent = new StringContent(JsonConvert.SerializeObject(param), Encoding.UTF8, "application/json");

            var convertResponse = await Backchannel.PostAsync(userIdConvertToOpenIdAddress, stringContent);

            if (!convertResponse.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: */ convertResponse.StatusCode,
                                /* Headers: */ convertResponse.Headers.ToString(),
                                /* Body: */ await convertResponse.Content.ReadAsStringAsync());

                throw new HttpRequestException("An error occurred while userid convert to openid.");
            }

            var convertResponsePayload = JObject.Parse(await convertResponse.Content.ReadAsStringAsync());

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

                throw new HttpRequestException("An error occurred while userid convert to openid.");
            }

            var jObject = new JObject();

            jObject.TryAppend(memberInfoPayload).TryAppend(convertResponsePayload);

            var resultPayload = JsonDocument.Parse(jObject.ToString());
            var context       = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, resultPayload.RootElement);

            context.RunClaimActions(resultPayload.RootElement);

            await Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }