protected virtual async Task <string> GetEmailAsync([NotNull] OAuthTokenResponse tokens)
        {
            // See http://open.weibo.com/wiki/2/account/profile/email for more information about the /account/profile/email.json endpoint.
            string address = QueryHelpers.AddQueryString(Options.UserEmailsEndpoint, "access_token", tokens.AccessToken);

            using var request = new HttpRequestMessage(HttpMethod.Get, address);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            using var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogWarning("An error occurred while retrieving the email address associated with the logged in user: "******"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 email address associated to the user profile.");
            }

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

            return((from email in payload.RootElement.EnumerateArray()
                    select email.GetString("email")).FirstOrDefault());
        }
    protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] OAuthCodeExchangeContext context)
    {
        var tokenRequestParameters = new Dictionary <string, string?>()
        {
            ["app_id"] = Options.ClientId,
            ["secret"] = Options.ClientSecret,
            ["code"]   = context.Code,
            ["output"] = "json",
        };

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

        string endpoint = QueryHelpers.AddQueryString(Options.TokenEndpoint, tokenRequestParameters);

        using var requestMessage = new HttpRequestMessage(HttpMethod.Get, endpoint);
        requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
        using var response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted);

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

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

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

        return(OAuthTokenResponse.Success(payload));
    }
Exemple #3
0
        /// <inheritdoc />
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri)
        {
            var content = ToJsonContent(new
            {
                token = new
                {
                    grant_type = "authorization_code",
                    code,
                    client_id     = Options.ClientId,
                    client_secret = Options.ClientSecret,
                    redirect_uri  = redirectUri,
                    scope         = string.Join(" ", Options.Scopes)
                }
            });

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

            return(response.IsSuccessStatusCode
                ? OAuthTokenResponse.Success(JObject.Parse(await response.Content.ReadAsStringAsync()))
                : OAuthTokenResponse.Failed(new Exception("OAuth token endpoint failure: " + await Display(response))));
        }
Exemple #4
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);

            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);

            var response = await Backchannel.SendAsync(request, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                throw new HttpRequestException($"Failed to retrived Microsoft user information ({response.StatusCode}) Please check if the authentication information is correct and the corresponding Microsoft Account API is enabled.");
            }

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

            var ticket     = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Options.AuthenticationScheme);
            var context    = new OAuthCreatingTicketContext(ticket, Context, Options, Backchannel, tokens, payload);
            var identifier = MicrosoftAccountHelper.GetId(payload);

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

            var name = MicrosoftAccountHelper.GetDisplayName(payload);

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

            var givenName = MicrosoftAccountHelper.GetGivenName(payload);

            if (!string.IsNullOrEmpty(givenName))
            {
                identity.AddClaim(new Claim(ClaimTypes.GivenName, givenName, ClaimValueTypes.String, Options.ClaimsIssuer));
                identity.AddClaim(new Claim("urn:microsoftaccount:givenname", givenName, ClaimValueTypes.String, Options.ClaimsIssuer));
            }

            var surname = MicrosoftAccountHelper.GetSurname(payload);

            if (!string.IsNullOrEmpty(surname))
            {
                identity.AddClaim(new Claim(ClaimTypes.Surname, surname, ClaimValueTypes.String, Options.ClaimsIssuer));
                identity.AddClaim(new Claim("urn:microsoftaccount:surname", surname, ClaimValueTypes.String, Options.ClaimsIssuer));
            }

            var email = MicrosoftAccountHelper.GetEmail(payload);

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

            await Options.Events.CreatingTicket(context);

            return(context.Ticket);
        }
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var endpoint = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "access_token", tokens.AccessToken);

            if (Options.SendAppSecretProof)
            {
                endpoint = QueryHelpers.AddQueryString(endpoint, "appsecret_proof", GenerateAppSecretProof(tokens.AccessToken));
            }
            if (Options.Fields.Count > 0)
            {
                endpoint = QueryHelpers.AddQueryString(endpoint, "fields", string.Join(",", Options.Fields));
            }

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

            if (!response.IsSuccessStatusCode)
            {
                throw new HttpRequestException($"Failed to retrieve Facebook user information ({response.StatusCode}) Please check if the authentication information is correct and the corresponding Facebook Graph API is enabled.");
            }

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

            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));
        }
Exemple #6
0
        /// <inheritdoc />
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            ClaimsIdentity identity,
            AuthenticationProperties properties,
            OAuthTokenResponse tokens)
        {
            // Get the Google user
            var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);

            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);

            var response = await Backchannel.SendAsync(request, Context.RequestAborted);

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

            using (var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync(Context.RequestAborted)))
            {
                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 !, context.Properties, Scheme.Name));
            }
        }
Exemple #7
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync([NotNull] ClaimsIdentity identity,
                                                                               [NotNull] AuthenticationProperties properties, [NotNull] OAuthTokenResponse tokens)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);

            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);

            var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);

            response.EnsureSuccessStatusCode();

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

            identity.AddOptionalClaim(ClaimTypes.NameIdentifier, FitbitAuthenticationHelper.GetIdentifier(payload), Options.ClaimsIssuer)
            .AddOptionalClaim(ClaimTypes.Name, FitbitAuthenticationHelper.GetLogin(payload), Options.ClaimsIssuer)
            .AddOptionalClaim("urn:fitbit:avatar", FitbitAuthenticationHelper.GetAvatar(payload), Options.ClaimsIssuer)
            .AddOptionalClaim("urn:fitbit:avatar150", FitbitAuthenticationHelper.GetAvatar150(payload), Options.ClaimsIssuer);

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

            await Options.Events.CreatingTicket(context);

            if (context.Principal?.Identity == null)
            {
                return(null);
            }

            return(new AuthenticationTicket(context.Principal, context.Properties, Options.AuthenticationScheme));
        }
Exemple #8
0
    /// <summary>
    /// Exchanges the authorization code for a authorization token from the remote provider.
    /// </summary>
    /// <param name="context">The <see cref="OAuthCodeExchangeContext"/>.</param>
    /// <returns>The response <see cref="OAuthTokenResponse"/>.</returns>
    protected virtual async Task <OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
    {
        var tokenRequestParameters = new Dictionary <string, string>()
        {
            { "client_id", Options.ClientId },
            { "redirect_uri", context.RedirectUri },
            { "client_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 requestContent = new FormUrlEncodedContent(tokenRequestParameters !);

        var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint);

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

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

        return(response.IsSuccessStatusCode switch
        {
            true => OAuthTokenResponse.Success(JsonDocument.Parse(body)),
            false => PrepareFailedOAuthTokenReponse(response, body)
        });
Exemple #9
0
        /// <summary>
        /// 通过Code获取Access Token(这是第二步)
        /// </summary>
        protected async Task <OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri, string appId)
        {
            var parameters = new Dictionary <string, string>
            {
                { "appid", appId },
                { "secret", Options.Apps.First(p => p.AppId == appId).AppSecret },
                { "code", code },
                { "grant_type", "authorization_code" }
            };

            _logger.LogDebug("code换取access_token");
            var endpoint = QueryHelpers.AddQueryString(Options.TokenEndpoint, parameters);

            _logger.LogDebug(endpoint);
            var response = await Backchannel.GetAsync(endpoint, Context.RequestAborted);

            if (response.IsSuccessStatusCode)
            {
                var result = await response.Content.ReadAsStringAsync();

                _logger.LogDebug(result);
                var payload = JObject.Parse(result);
                if (payload.Properties().Any(p => p.Name == "errcode"))
                {
                    return(OAuthTokenResponse.Failed(new Exception($"获取微信AccessToken出错。{result}")));
                }
                return(OAuthTokenResponse.Success(payload));
            }
            else
            {
                return(OAuthTokenResponse.Failed(new Exception("获取微信AccessToken出错。")));
            }
        }
    protected override async Task <AuthenticationTicket> CreateTicketAsync(
        [NotNull] ClaimsIdentity identity,
        [NotNull] AuthenticationProperties properties,
        [NotNull] OAuthTokenResponse tokens)
    {
        string address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "access_token", tokens.AccessToken !);

        using var request = new HttpRequestMessage(HttpMethod.Get, address);
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));

        using var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);

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

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

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

        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));
    }
Exemple #11
0
    protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] OAuthCodeExchangeContext context)
    {
        var tokenRequestParameters = new Dictionary <string, string>
        {
            ["grant_type"]   = "authorization_code",
            ["redirect_uri"] = context.RedirectUri,
            ["code"]         = context.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);
        }

        using var request = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint);
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        request.Headers.Authorization = CreateAuthorizationHeader();

        request.Content = new FormUrlEncodedContent(tokenRequestParameters);

        using var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);

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

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

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

        return(OAuthTokenResponse.Success(payload));
    }
Exemple #12
0
    private async Task <(int ErrorCode, string?UserId)> GetUserIdentifierAsync(OAuthTokenResponse tokens)
    {
        // See https://open.work.weixin.qq.com/api/doc/90000/90135/91023 for details.
        var parameters = new Dictionary <string, string?>
        {
            ["access_token"] = tokens.AccessToken,
            ["code"]         = Request.Query["code"],
        };

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

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

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

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

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

        var errorCode =
            payload.RootElement.TryGetProperty("errcode", out var errCodeElement) && errCodeElement.ValueKind == JsonValueKind.Number ?
            errCodeElement.GetInt32() :
            0;

        return(errorCode, payload.RootElement.GetString("UserId"));
    }
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            [NotNull] ClaimsIdentity identity,
            [NotNull] AuthenticationProperties properties,
            [NotNull] OAuthTokenResponse tokens)
        {
            using var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);

            using var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, 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 payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync(Context.RequestAborted));

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

            context.RunClaimActions(payload.RootElement.GetProperty("user"));

            await Options.Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal !, context.Properties, Scheme.Name));
        }
Exemple #14
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync([NotNull] ClaimsIdentity identity,
                                                                               [NotNull] AuthenticationProperties properties, [NotNull] OAuthTokenResponse tokens)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);

            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);

            var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, 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());

            identity.AddOptionalClaim(ClaimTypes.NameIdentifier, DropboxAuthenticationHelper.GetIdentifier(payload), Options.ClaimsIssuer)
            .AddOptionalClaim(ClaimTypes.Name, DropboxAuthenticationHelper.GetDisplayName(payload), Options.ClaimsIssuer)
            .AddOptionalClaim(ClaimTypes.Email, DropboxAuthenticationHelper.GetEmail(payload), Options.ClaimsIssuer);

            var principal = new ClaimsPrincipal(identity);
            var ticket    = new AuthenticationTicket(principal, properties, Options.AuthenticationScheme);

            var context = new OAuthCreatingTicketContext(ticket, Context, Options, Backchannel, tokens, payload);
            await Options.Events.CreatingTicket(context);

            return(context.Ticket);
        }
Exemple #15
0
    protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] OAuthCodeExchangeContext context)
    {
        // See https://open.work.weixin.qq.com/api/doc/90000/90135/91039 for details.
        var tokenRequestParameters = new Dictionary <string, string?>()
        {
            ["corpid"]     = Options.ClientId,
            ["corpsecret"] = Options.ClientSecret,
        };

        // 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, Context.RequestAborted);

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

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

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

        return(OAuthTokenResponse.Success(payload));
    }
Exemple #16
0
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] string code, [NotNull] string redirectUri)
        {
            var request = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint);

            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));

            request.Content = new FormUrlEncodedContent(new Dictionary <string, string>
            {
                ["redirect_uri"]          = redirectUri,
                ["client_assertion"]      = Options.ClientSecret,
                ["assertion"]             = code,
                ["grant_type"]            = "urn:ietf:params:oauth:grant-type:jwt-bearer",
                ["client_assertion_type"] = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
            });

            var response = await Backchannel.SendAsync(request, 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());

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

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

            return(OAuthTokenResponse.Success(payload));
        }
Exemple #17
0
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] OAuthCodeExchangeContext context)
        {
            using var request = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            request.Headers.Authorization = CreateAuthorizationHeader();

            var parameters = new Dictionary <string, string>
            {
                ["grant_type"]   = "authorization_code",
                ["redirect_uri"] = context.RedirectUri,
                ["code"]         = context.Code
            };

            request.Content = new FormUrlEncodedContent(parameters !);

            using var response = await Backchannel.SendAsync(request, 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.")));
            }

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

            return(OAuthTokenResponse.Success(payload));
        }
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            log.LogDebug("CreateTicketAsync called");

            var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);

            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);

            var response = await Backchannel.SendAsync(request, Context.RequestAborted);

            response.EnsureSuccessStatusCode();

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

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

            var identifier = MicrosoftAccountHelper.GetId(payload);

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

            var name = MicrosoftAccountHelper.GetName(payload);

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

            var email = MicrosoftAccountHelper.GetEmail(payload);

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

            await Options.Events.CreatingTicket(context);

            ISiteSettings site = siteResolver.Resolve();

            if (site != null)
            {
                Claim siteGuidClaim = new Claim("SiteGuid", site.SiteGuid.ToString());
                if (!identity.HasClaim(siteGuidClaim.Type, siteGuidClaim.Value))
                {
                    identity.AddClaim(siteGuidClaim);
                }
            }

            //return new AuthenticationTicket(notification.Principal, notification.Properties, notification.Options.AuthenticationScheme);
            return(new AuthenticationTicket(context.Principal, context.Properties, AuthenticationScheme.External));
        }
Exemple #19
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,
                ["uid"]          = tokens.Response.Value <string>("uid")
            });

            HttpRequestMessage  request  = null;
            HttpResponseMessage response = null;

            try
            {
                request = new HttpRequestMessage(HttpMethod.Get, address);
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, 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());

                // When the email address is not public, retrieve it from
                // the emails endpoint if the user:email scope is specified.
                if (!string.IsNullOrEmpty(Options.UserEmailsEndpoint) &&
                    !identity.HasClaim(claim => claim.Type == ClaimTypes.Email) && Options.Scope.Contains("user:email"))
                {
                    var email = await GetEmailAsync(tokens);

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

                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
            {
                request?.Dispose();
                response?.Dispose();
            }
        }
Exemple #20
0
    /// <inheritdoc />
    protected override async Task <AuthenticationTicket> CreateTicketAsync(
        [NotNull] ClaimsIdentity identity,
        [NotNull] AuthenticationProperties properties,
        [NotNull] OAuthTokenResponse tokens)
    {
        var uri = string.Format(
            CultureInfo.InvariantCulture,
            ShopifyAuthenticationDefaults.UserInformationEndpointFormat,
            properties.Items[ShopifyAuthenticationDefaults.ShopNameAuthenticationProperty]);

        using var request = new HttpRequestMessage(HttpMethod.Get, uri);
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        request.Headers.Add("X-Shopify-Access-Token", tokens.AccessToken);

        using var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);

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

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

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

        // In Shopify, the customer can modify the scope given to the app. Apps should verify
        // that the customer is allowing the required scope.
        var actualScope  = tokens.Response !.RootElement.GetString("scope") ?? string.Empty;
        var isPersistent = true;

        // If the request was for a "per-user" (i.e. no offline access)
        if (tokens.Response.RootElement.TryGetProperty("expires_in", out var expiresInProperty))
        {
            isPersistent = false;

            if (expiresInProperty.TryGetInt32(out var expiresIn))
            {
                var expires = Clock.UtcNow.AddSeconds(expiresIn);
                identity.AddClaim(new Claim(ClaimTypes.Expiration, expires.ToString("O", CultureInfo.InvariantCulture), ClaimValueTypes.DateTime));
            }

            actualScope = tokens.Response.RootElement.GetString("associated_user_scope") ?? string.Empty;

            var userData = tokens.Response.RootElement.GetString("associated_user") ?? string.Empty;
            identity.AddClaim(new Claim(ClaimTypes.UserData, userData));
        }

        identity.AddClaim(new Claim(ClaimTypes.IsPersistent, isPersistent.ToString(CultureInfo.InvariantCulture), ClaimValueTypes.Boolean));
        identity.AddClaim(new Claim(ShopifyAuthenticationDefaults.ShopifyScopeClaimType, actualScope));

        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));
    }
        /// <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));
        }
Exemple #22
0
        protected override async Task <OpenIdConnectMessage> RedeemAuthorizationCodeAsync(OpenIdConnectMessage tokenEndpointRequest)
        {
            //Logger.RedeemingCodeForTokens();

            OpenIdConnectHandler       idConnectHandler   = this;
            OpenIdConnectConfiguration configurationAsync = await idConnectHandler.Options.ConfigurationManager.GetConfigurationAsync(CancellationToken.None);

            var requestMessage = new HttpRequestMessage(HttpMethod.Post, configurationAsync.TokenEndpoint);

            //add header ipv body
            var basicAuthHeader = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{Options.ClientId}:{Options.ClientSecret}"));

            requestMessage.Headers.Add("Authorization", basicAuthHeader);

            var parameters = tokenEndpointRequest.Parameters;

            parameters.Remove("client_id");
            parameters.Remove("client_secret");

            requestMessage.Content = new FormUrlEncodedContent(parameters);

            var responseMessage = await Backchannel.SendAsync(requestMessage);

            var contentMediaType = responseMessage.Content.Headers.ContentType?.MediaType;

            if (string.IsNullOrEmpty(contentMediaType))
            {
                Logger.LogDebug($"Unexpected token response format. Status Code: {(int)responseMessage.StatusCode}. Content-Type header is missing.");
            }
            else if (!string.Equals(contentMediaType, "application/json", StringComparison.OrdinalIgnoreCase))
            {
                Logger.LogDebug($"Unexpected token response format. Status Code: {(int)responseMessage.StatusCode}. Content-Type {responseMessage.Content.Headers.ContentType}.");
            }

            // Error handling:
            // 1. If the response body can't be parsed as json, throws.
            // 2. If the response's status code is not in 2XX range, throw OpenIdConnectProtocolException. If the body is correct parsed,
            //    pass the error information from body to the exception.
            OpenIdConnectMessage message;

            try
            {
                var responseContent = await responseMessage.Content.ReadAsStringAsync();

                message = new OpenIdConnectMessage(responseContent);
            }
            catch (Exception ex)
            {
                throw new OpenIdConnectProtocolException($"Failed to parse token response body as JSON. Status Code: {(int)responseMessage.StatusCode}. Content-Type: {responseMessage.Content.Headers.ContentType}", ex);
            }

            if (!responseMessage.IsSuccessStatusCode)
            {
                //throw CreateOpenIdConnectProtocolException(message, responseMessage);
            }

            return(message);
        }
Exemple #23
0
    protected override async Task <AuthenticationTicket> CreateTicketAsync(
        [NotNull] ClaimsIdentity identity,
        [NotNull] AuthenticationProperties properties,
        [NotNull] OAuthTokenResponse tokens)
    {
        // See https://opendocs.alipay.com/apis/api_2/alipay.user.info.share for details.
        var parameters = new SortedDictionary <string, string?>()
        {
            ["app_id"]     = Options.ClientId,
            ["auth_token"] = tokens.AccessToken,
            ["charset"]    = "utf-8",
            ["format"]     = "JSON",
            ["method"]     = "alipay.user.info.share",
            ["sign_type"]  = "RSA2",
            ["timestamp"]  = Clock.UtcNow.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
            ["version"]    = "1.0",
        };

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

        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 stream = await response.Content.ReadAsStreamAsync(Context.RequestAborted);

        using var document = JsonDocument.Parse(stream);
        var rootElement = document.RootElement;

        if (!rootElement.TryGetProperty("alipay_user_info_share_response", out JsonElement mainElement))
        {
            var errorCode = rootElement.GetProperty("error_response").GetProperty("code").GetString() !;
            throw new Exception($"An error (Code:{errorCode}) occurred while retrieving user information.");
        }

        if (!ValidateReturnCode(mainElement, out var code))
        {
            throw new Exception($"An error (Code:{code}) occurred while retrieving user information.");
        }

        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, mainElement.GetString("user_id") !, ClaimValueTypes.String, Options.ClaimsIssuer));

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

        context.RunClaimActions();

        await Events.CreatingTicket(context);

        return(new AuthenticationTicket(context.Principal !, context.Properties, Scheme.Name));
    }
        private async Task<bool> TryRefreshTokenAsync(AuthenticationTicket ticket)
        {
            // Refresh
            var rfrshToken = ticket.Properties.GetTokenValue("refresh_token");

            var tokenRequestParameters = new Dictionary<string, string>()
            {
                { "client_id", Options.ClientId },
                { "client_secret", Options.ClientSecret },
                { "grant_type", "refresh_token" },
                { "refresh_token", rfrshToken },
                { "scope", "identify guilds" }
            };

            var requestContent = new FormUrlEncodedContent(tokenRequestParameters);

            using var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint);
            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            requestMessage.Content = requestContent;

            var response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted);
            if (response.IsSuccessStatusCode)
            {
                await using var stream = await response.Content.ReadAsStreamAsync();
                var payload = await JsonDocument.ParseAsync(stream);
                var tokens = OAuthTokenResponse.Success(payload);

                ticket.Properties.UpdateTokenValue("access_token", tokens.AccessToken);
                ticket.Properties.UpdateTokenValue("refresh_token", tokens.RefreshToken);

                if (int.TryParse(tokens.ExpiresIn, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value))
                {
                    var expiresAt = Clock.UtcNow + TimeSpan.FromSeconds(value);
                    ticket.Properties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));
                }

                if (ticket.Principal.Identity is ClaimsIdentity identity)
                {
                    var existingClaim = identity.FindFirst("discord");
                    if (existingClaim != null && identity.TryRemoveClaim(existingClaim))
                    {
                        identity.AddClaim(new Claim("discord", tokens.AccessToken));
                    }
                }

                if (ticket.Properties.ExpiresUtc.HasValue && ticket.Properties.IssuedUtc.HasValue)
                {
                    var delta = ticket.Properties.ExpiresUtc - ticket.Properties.IssuedUtc;
                    ticket.Properties.IssuedUtc = Clock.UtcNow;
                    ticket.Properties.ExpiresUtc = Clock.UtcNow + delta;
                }

                return true;
            }

            return false;
        }
Exemple #25
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            [NotNull] ClaimsIdentity identity,
            [NotNull] AuthenticationProperties properties,
            [NotNull] OAuthTokenResponse tokens)
        {
            var identifier = await GetUserIdentifierAsync(tokens);

            if (string.IsNullOrEmpty(identifier))
            {
                throw new HttpRequestException("An error occurred while retrieving the user identifier.");
            }

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

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

            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());

            var status = payload.Value <int>("ret");

            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.Value <string>("msg"));

                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));
        }
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            if (identity == null)
            {
                throw new ArgumentNullException(nameof(identity));
            }
            if (tokens == null)
            {
                throw new ArgumentNullException(nameof(tokens));
            }

            OAuthCreatingTicketContext context = null;

            if (Options.Scope.First() == WeChatScopes.snsapi_userinfo)
            {
                var url = Options.UserInformationEndpoint +
                          $"?access_token={UrlEncoder.Default.Encode(tokens.AccessToken)}" +
                          $"&openid={UrlEncoder.Default.Encode(tokens.Response.RootElement.GetString("openid"))}" +
                          $"&lang=" + Options.Language;

                var request = new HttpRequestMessage(HttpMethod.Get, url);

                var response = await Backchannel.SendAsync(request, Context.RequestAborted);

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

                if (response.IsSuccessStatusCode)
                {
                    var payload = JsonDocument.Parse(content);

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

                    context.RunClaimActions(payload.RootElement);
                }
                else
                {
                    var weChatException = new WeChatException("获取微信用户信息失败:HttpClient返回错误代码," +
                                                              $"Status:{response.StatusCode},Headers:{response.Headers.ToString()},Body:{content}");

                    Logger.LogDebug(weChatException, "WeChatHandler CreateTicketAsync");


                    throw weChatException;
                }
            }

            if (context == null)
            {
                context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, tokens.Response.RootElement);

                context.RunClaimActions(tokens.Response.RootElement);
            }

            await Events.CreatingTicket(context);

            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
Exemple #27
0
        protected override async Task <AuthenticationTicket> CreateTicketAsync(
            ClaimsIdentity identity,
            AuthenticationProperties properties,
            OAuthTokenResponse tokens)
        {
            using var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);

            using var response = await Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, 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}.",
                                response.StatusCode,
                                response.Headers.ToString(),
                                await response.Content.ReadAsStringAsync());

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

            using var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
            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);

            // store token and user in database
            string id           = "";
            string emailAddress = "";
            string name         = "";

            foreach (Claim claim in identity.Claims)
            {
                switch (claim.Type)
                {
                case "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier":
                    id = claim.Value;
                    break;

                case "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress":
                    emailAddress = claim.Value;
                    break;

                case "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name":
                    name = claim.Value;
                    break;
                }
            }
            CommentLinkUser commentLinkUser = new CommentLinkUser(id, emailAddress, name, tokens);

            _ = CosmosDb.UpsertItem(commentLinkUser);
            return(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
        }
        /// <summary>
        ///  获取用户参数,与本机通信
        /// </summary>
        protected override async Task <AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
        {
            var openId = XiaoMiHelper.GetOpenId(tokens.Response);

            if (!string.IsNullOrEmpty(openId))
            {
                identity.AddClaim(new Claim("urn:mi:openid", openId, ClaimValueTypes.String, Options.ClaimsIssuer));
            }
            var type    = tokens.TokenType.ToEnum <TokenType>();
            var content = await new FormUrlEncodedContent(new Dictionary <string, string>
            {
                { "clientId", Options.ClientId },
                { "token", tokens.AccessToken }
            }).ReadAsStringAsync();
            var message = new HttpRequestMessage(HttpMethod.Get, $"{Options.UserInformationEndpoint}?{content}");

            if (type == TokenType.MAC)
            {
                var key       = tokens.Response.Value <string>("mac_key");
                var algorithm = tokens.Response.Value <string>("mac_algorithm");
                message.Headers.Authorization = new AuthenticationHeaderValue("MAC",
                                                                              ComputeMAC(tokens.AccessToken, key, message, algorithm));
            }
            var response = await Backchannel.SendAsync(message, Context.RequestAborted);

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

            var ticket  = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Options.AuthenticationScheme);
            var context = new OAuthCreatingTicketContext(ticket, Context, Options, Backchannel, tokens, payload);

            var identifier = XiaoMiHelper.GetId(payload);

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

            var name = XiaoMiHelper.GetName(payload);

            if (!string.IsNullOrEmpty(name))
            {
                identity.AddClaim(new Claim(ClaimTypes.Name, name, ClaimValueTypes.String, Options.ClaimsIssuer));
                identity.AddClaim(new Claim("urn:mi:name", name, ClaimValueTypes.String, Options.ClaimsIssuer));
            }
            var icon = XiaoMiHelper.GetIcon(payload);

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

            await Options.Events.CreatingTicket(context);

            return(context.Ticket);
        }
Exemple #29
0
    protected override async Task <AuthenticationTicket> CreateTicketAsync(
        [NotNull] ClaimsIdentity identity,
        [NotNull] AuthenticationProperties properties,
        [NotNull] OAuthTokenResponse tokens)
    {
        (var errorCode, var openId, var unionId) = await GetUserIdentifierAsync(tokens);

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

        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, openId, ClaimValueTypes.String, Options.ClaimsIssuer));
        if (!string.IsNullOrEmpty(unionId))
        {
            identity.AddClaim(new Claim(QQAuthenticationConstants.Claims.UnionId, unionId, ClaimValueTypes.String, Options.ClaimsIssuer));
        }

        var parameters = new Dictionary <string, string?>(3)
        {
            ["oauth_consumer_key"] = Options.ClientId,
            ["access_token"]       = tokens.AccessToken,
            ["openid"]             = 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.");
        }

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

        using var payload = JsonDocument.Parse(stream);

        var status = payload.RootElement.GetProperty("ret").GetInt32();

        if (status != 0)
        {
            Log.UserProfileErrorCode(Logger, status, payload.RootElement.GetString("msg"));
            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.RootElement);

        context.RunClaimActions();

        await Events.CreatingTicket(context);

        return(new AuthenticationTicket(context.Principal !, context.Properties, Scheme.Name));
    }
Exemple #30
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(OAuthCodeExchangeContext context)
        {
            var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, new Dictionary <string, string>()
            {
                ["client_id"]     = Options.ClientId,
                ["client_secret"] = Options.ClientSecret,
                ["code"]          = context.Code,
                ["grant_type"]    = "authorization_code",
                ["redirect_uri"]  = context.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.")));
            }

            JsonDocument payload = JsonDocument.Parse("{}");

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

            var buffer = new ArrayBufferWriter <byte>();
            var write  = new Utf8JsonWriter(buffer);

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

                write.WritePropertyName(kv[0]);
                write.WriteStringValue(kv[1]);
            }

            return(OAuthTokenResponse.Success(payload));
        }