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