This repository has been archived by the owner. It is now read-only.

Get the user's e-mail address from Twitter #765

Closed
Tratcher opened this Issue Apr 4, 2016 · 8 comments

Comments

Projects
None yet
4 participants
@Tratcher
Member

Tratcher commented Apr 4, 2016

Getting the user's e-mail address from Twitter is a pain. You have to contact Twitter support to request the permission for your app. Then you have to send a request to an additional endpoint. The auth middleware should support optionally sending this request.

http://stackoverflow.com/questions/22627083/can-we-get-email-id-from-twitter-oauth-api/32852370#32852370
http://stackoverflow.com/questions/36330675/get-users-email-from-twitter-api-for-external-login-authentication-asp-net-mvc?lq=1

@Tratcher Tratcher added the enhancement label Apr 4, 2016

@Tratcher

This comment has been minimized.

Member

Tratcher commented Apr 6, 2016


            app.UseTwitterAuthentication(options =>
            {
                options.ConsumerKey = Configuration["Authentication:Twitter:ConsumerKey"];
                options.ConsumerSecret = Configuration["Authentication:Twitter:ConsumerSecret"];
                options.Events = new TwitterEvents()
                {
                    OnCreatingTicket = async context =>
                    {                        
                        var nonce = Guid.NewGuid().ToString("N");

                        var authorizationParts = new SortedDictionary<string, string>
                        {
                            { "oauth_consumer_key", context.Options.ConsumerKey },
                            { "oauth_nonce", nonce },
                            { "oauth_signature_method", "HMAC-SHA1" },
                            { "oauth_timestamp", GenerateTimeStamp() },
                            { "oauth_token", context.AccessToken },
                            { "oauth_version", "1.0" }
                        };

                        var parameterBuilder = new StringBuilder();
                        foreach (var authorizationKey in authorizationParts)
                        {
                            parameterBuilder.AppendFormat("{0}={1}&", UrlEncoder.Default.UrlEncode(authorizationKey.Key), UrlEncoder.Default.UrlEncode(authorizationKey.Value));
                        }
                        parameterBuilder.Length--;
                        var parameterString = parameterBuilder.ToString();

                        var resource_url = "https://api.twitter.com/1.1/account/verify_credentials.json";
                        var resource_query = "include_email=true";
                        var canonicalizedRequestBuilder = new StringBuilder();
                        canonicalizedRequestBuilder.Append(HttpMethod.Get.Method);
                        canonicalizedRequestBuilder.Append("&");
                        canonicalizedRequestBuilder.Append(UrlEncoder.Default.UrlEncode(resource_url));
                        canonicalizedRequestBuilder.Append("&");
                        canonicalizedRequestBuilder.Append(UrlEncoder.Default.UrlEncode(resource_query));
                        canonicalizedRequestBuilder.Append("%26");
                        canonicalizedRequestBuilder.Append(UrlEncoder.Default.UrlEncode(parameterString));

                        var signature = ComputeSignature(context.Options.ConsumerSecret, context.AccessTokenSecret, canonicalizedRequestBuilder.ToString());
                        authorizationParts.Add("oauth_signature", signature);

                        var authorizationHeaderBuilder = new StringBuilder();
                        authorizationHeaderBuilder.Append("OAuth ");
                        foreach (var authorizationPart in authorizationParts)
                        {
                            authorizationHeaderBuilder.AppendFormat(
                                "{0}=\"{1}\", ", authorizationPart.Key, UrlEncoder.Default.UrlEncode(authorizationPart.Value));
                        }
                        authorizationHeaderBuilder.Length = authorizationHeaderBuilder.Length - 2;

                        var request = new HttpRequestMessage(HttpMethod.Get, resource_url + "?include_email=true");
                        request.Headers.Add("Authorization", authorizationHeaderBuilder.ToString());

                        var response = await Backchannel.SendAsync(request, context.HttpContext.RequestAborted);
                        response.EnsureSuccessStatusCode();
                        string responseText = await response.Content.ReadAsStringAsync();

                        var result = JObject.Parse(responseText);

                        var email = result.Value<string>("email");
                        var identity = (ClaimsIdentity)context.Principal.Identity;
                        if (!string.IsNullOrEmpty(email))
                        {
                            identity.AddClaim(new Claim(ClaimTypes.Email, email, ClaimValueTypes.String, "Twitter"));
                        }
                    },
                };
            });
...


        private static string GenerateTimeStamp()
        {
            var secondsSinceUnixEpocStart = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return Convert.ToInt64(secondsSinceUnixEpocStart.TotalSeconds).ToString(CultureInfo.InvariantCulture);
        }

        private string ComputeSignature(string consumerSecret, string tokenSecret, string signatureData)
        {
            using (var algorithm = new HMACSHA1())
            {
                algorithm.Key = Encoding.ASCII.GetBytes(
                    string.Format(CultureInfo.InvariantCulture,
                        "{0}&{1}",
                        UrlEncoder.Default.UrlEncode(consumerSecret),
                        string.IsNullOrEmpty(tokenSecret) ? string.Empty : UrlEncoder.Default.UrlEncode(tokenSecret)));
                var hash = algorithm.ComputeHash(Encoding.ASCII.GetBytes(signatureData));
                return Convert.ToBase64String(hash);
            }
        }

@Eilon Eilon added this to the 1.0.0 milestone Apr 7, 2016

@Eilon Eilon added the 1 - Ready label Apr 7, 2016

@Eilon

This comment has been minimized.

Member

Eilon commented Apr 7, 2016

Let's add a specific option to the Twitter Options to enable grabbing the email.

@Tratcher Tratcher added 2 - Working and removed 1 - Ready labels Apr 27, 2016

Tratcher added a commit that referenced this issue Apr 27, 2016

Tratcher added a commit that referenced this issue Apr 28, 2016

Tratcher added a commit that referenced this issue Apr 28, 2016

@Tratcher Tratcher added 3 - Done and removed 2 - Working labels Apr 28, 2016

@Tratcher Tratcher closed this Apr 28, 2016

@danielserafimovik

This comment has been minimized.

danielserafimovik commented May 19, 2016

you have to change your code to call the GET account/verify_credentials method after the user is logged in with twitter. And it is important to set the parameter include_email to true. When this is set to true email will be returned in the user objects as a string. I'm using this library https://www.nuget.org/packages/linqtotwitter so that I do not have to write code for handling twitter api requests

var twitterCtx = new TwitterContext(authTwitter); var verifyResponse = await (from acct in twitterCtx.Account where (acct.Type == AccountType.VerifyCredentials) && (acct.IncludeEmail == true) select acct) .SingleOrDefaultAsync();

see how I have done this here http://www.bigbrainintelligence.com/Post/get-users-email-address-from-twitter-oauth-ap

it is an easy and clean solution

@AlexOliinyk1

This comment has been minimized.

AlexOliinyk1 commented Sep 3, 2017

Backchannel - can't resolve symbol. Any idea ?

@Tratcher

This comment has been minimized.

Member

Tratcher commented Sep 3, 2017

@AlexOliinyk1, @danielserafimovik's advice no longer applies, you can set the RetrieveUserDetails property to handle this now.

@AlexOliinyk1

This comment has been minimized.

AlexOliinyk1 commented Sep 3, 2017

@Tratcher thank you for quick update. But after enable I still can't to get email. http://prntscr.com/ggnq1m

@Tratcher

This comment has been minimized.

Member

Tratcher commented Sep 3, 2017

Did you follow these instructions? The only way to enable it is to contact Twitter support.
https://stackoverflow.com/questions/22627083/can-we-get-email-id-from-twitter-oauth-api/32852370#32852370

@AlexOliinyk1

This comment has been minimized.

AlexOliinyk1 commented Sep 3, 2017

@Tratcher code look like this

image

image

It is looks like it something wrong on the server side, but on the server side it is getting all data, except email.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.