public async Task <ActionResult <AuthenticationResponse> > GetTwitterJWT([FromBody] TwitterRequestTokenResponse twitterRequestTokenResponse)
        {
            // Step 1 : initializing variables
            string token      = string.Empty;
            var    httpClient = _httpClientFactory.CreateClient();

            // Step 2 : getting keys from appsettings.json
            var consumerKey     = _configuration["Authentication:Twitter:ConsumerKey"];
            var consumerSecrete = _configuration["Authentication:Twitter:ConsumerSecrete"];

            // Step 3 : requesting oauth_token & oauth_token_secrete
            var client = new RestClient("https://api.twitter.com"); // Note NO /1

            client.Authenticator = OAuth1Authenticator.ForAccessToken(
                consumerKey,
                consumerSecrete,
                twitterRequestTokenResponse.OAuthToken,
                twitterRequestTokenResponse.OAuthTokenSecrete,
                twitterRequestTokenResponse.OAuthVerifier
                );

            var request  = new RestRequest("/oauth/access_token", Method.Post);
            var response = await client.ExecuteAsync(request);

            var qs           = HttpUtility.ParseQueryString(response.Content);
            var _token       = qs["oauth_token"];
            var _tokenSecret = qs["oauth_token_secret"];

            // Step 4 : passing oauth_token & oauth_token_secrete to Twitter API to get email address of the user
            var emailAddress = await GetTwitterEmailAddress(_token, _tokenSecret);

            // Step 5 : try to find the user in the database or create a new account
            var loggedInUser = await GetUserByEmailAddress(emailAddress);

            // Step 6 : generate the token
            if (loggedInUser == null)
            {
                loggedInUser = await CreateExternalUser(emailAddress);
            }

            token = GenerateJwtToken(loggedInUser);
            httpClient.Dispose();

            // Step 7 : returning the token back to the client
            return(await Task.FromResult(new AuthenticationResponse()
            {
                Token = token
            }));
        }
    /*
     * This method conducts the request to Twitter's APIs.
     */
    public TwitterRequestTokenResponse ExecuteAuthentication()
    {
        /*
         * The response object we're expecting from Twitter. This is a custom object
         * defined in a class below.
         */
        TwitterRequestTokenResponse parsedResponse = null;

        try
        {
            string response = null;
            string error    = null;
            using (var client = new WebClient())
            {
                /*
                 * Using a try-catch within the Using statement should ensure that the WebClient is disposed.
                 *
                 * WebClient is an easy, but possibly not optimal, solution here. Not optimal because
                 * it doesn't provide any opportunity to catch the response before it throws an error.
                 * Hence the try-catch.
                 *
                 * Ideally, these calls would contain logic to catch the response code (400, 401, 404, 200, etc.)
                 * and react with messaging to the visitor accordingly.
                 */
                try
                {
                    client.Headers["Authorization"] = this.GetAuthorizationString();
                    response = client.UploadString(this.TwApiUrl, this.TwMethod, "");
                }
                catch (Exception ex)
                {
                    EkException.LogException(ex);
                    error = ex.Message;
                }
            }

            /*
             * The constructor for the Response object will parse the string.
             */
            parsedResponse = new TwitterRequestTokenResponse(response);
        }
        catch (Exception ex)
        {
            EkException.LogException(ex);
        }
        return(parsedResponse);
    }
        /// <summary>
        /// Retrieves a Twitter request token for the Twitter Request token auth flow
        /// </summary>
        /// <param name="options">The options for this request</param>
        /// <returns></returns>
        public async Task <string> GetTwitterRequestTokenAsync(RequestOptions options = null)
        {
            options = options ?? RequestOptions.CreateFromDefaults(ApiClient.Config);
            options.UseAccessToken = false;
            RestResponse response = await ApiClient.SendJsonAsync(
                "POST",
                "oauth/token",
                new
            {
                grant_type = "request_token",
                provider   = "twitter"
            },
                options).ConfigureAwait(false);

            TwitterRequestTokenResponse auth = await response.ReadAsJsonAsync <TwitterRequestTokenResponse>(ApiClient.Config).ConfigureAwait(false);

            return(auth.RequestToken);
        }
Exemple #4
0
        public async Task <string> GetTwitterJWTAsync(TwitterRequestTokenResponse twitterRequestTokenResponse)
        {
            using var httpMessageResponse = await _httpClient.PostAsJsonAsync("user/getTwitterjwt", twitterRequestTokenResponse);

            return((await httpMessageResponse.Content.ReadFromJsonAsync <AuthenticationResponse>()).Token);
        }
    /*
     * The Page_Load logic here handles
     */
    protected void Page_Load(object sender, EventArgs e)
    {
        /*
         * Detect if the user is logged in. This is the most efficient way to go about
         * it as it employs a static option. You could call upon the UserManager defined
         * above, but that may cause it to initialize unnecessarily.
         */
        if (Ektron.Cms.Framework.Context.UserContextService.Current.IsLoggedIn)
        {
            uxAuthenticationViews.SetActiveView(uxLogoutView);
        }
        else
        {
            /*
             * Ensure the login view is set. It should by default, but it's best to specify
             * it explicitly in case of inadvertent postbacks.
             */
            uxAuthenticationViews.SetActiveView(uxLoginView);

            /*
             * I'm not going to perform checks against the querystring until I know it has values.
             */
            if (Request.QueryString.Count > 1)
            {
                /*
                 * Try to get the values from the querystring.
                 *
                 * These are the values that are returned by Twitter when the user has successfully
                 * authenticated. Not to worry, we're not going to assume these values are valid
                 * for authentication without some double-checking.
                 */
                string oAuthToken    = Request.QueryString["oauth_token"];
                string oAuthVerifier = Request.QueryString["oauth_verifier"];

                /*
                 * Make sure the parameters have values. :)
                 */
                if (!string.IsNullOrEmpty(oAuthToken) && !string.IsNullOrEmpty(oAuthVerifier))
                {
                    /*
                     * Get the original request token values out of the Session.
                     */
                    TwitterRequestTokenResponse originalResponse = (TwitterRequestTokenResponse)Session["TwitterAuthValues"];

                    /*
                     * Compare the token recieved in the querystring with the Request Token API.
                     *
                     * If they're the same, then you can trust that the visitor is just arrived
                     * from your authentication request.
                     */
                    if (oAuthToken == originalResponse.OAuthToken)
                    {
                        /*
                         * Authentication successful!
                         *
                         * Now you need to use this information to get some information about the visitor
                         * who just authenticated to your site. In everything we've done so far, we still
                         * don't know the visitor's screen name or Twitter ID, for example.
                         *
                         * In addition, we can't make any requests on behalf of that user. The app that I've
                         * registered for this sample application is read-only. What I can do with that is
                         * read the profile and tweets of this user. I may be able to use that for some
                         * personalization. For example, I may want to know whether this visitor has mentioned
                         * my company by name or used any of the hashtags we're interested in.
                         *
                         * In order to request that information, I need another token, which I will also get
                         * in the following request. As mentioned above, I'm only making use of the visitor's
                         * screen name and user id below, not the token. And as such, this code does not
                         * show you how to store that token or use it in Twitter's APIs.
                         */

                        /*
                         * To kick things off, I'll create a new access token request. This is a custom class
                         * defined below which will hold data and make calculations specifically for this request.
                         *
                         * The request will make use of the newly received token and verifier that we got out
                         * of the querystring. I'm passing them to the new object as it's initialized.
                         */
                        var AccessRequest = new TwitterAccessTokenRequest(oAuthToken, oAuthVerifier);

                        /*
                         * Make the request. The workings of this method are described within its parent class
                         * below. It returns a response which contains an access token (to get read-only data),
                         * secret, as well as the visitor's Twitter Screen Name and User ID.
                         */
                        var AccessResponse = AccessRequest.ExecuteAccessTokenRequest();

                        /*
                         * Make sure it didn't incur any errors. If so, respond accordingly.
                         */
                        if (!string.IsNullOrEmpty(AccessResponse.ErrorMessage))
                        {
                            uxLoginError.InnerText = string.Format("We were unable to get an authentication token from Twitter. Error: {0}", AccessResponse.ErrorMessage);
                            uxLoginError.Visible   = true;
                        }
                        else
                        {
                            /*
                             * At this point, all has gone well. The user has granted permissions and we were able
                             * to verify their identity using Twitter's APIs. First, we attempt to login the user
                             * with the Authentication ID (defined as a private global above) and their Twitter
                             * User ID.
                             *
                             * The User ID is used here rather than their Screen Name because a Twitter user can
                             * alter their screen name at any time, but not their ID. As long as you use their ID
                             * then the visitor can alter their screen name at any time, yet still be albe to login
                             * to your site.
                             */

                            /*
                             * Establish initial user object. Set to null for now. If login is successful, then the
                             * object will be given a value.
                             */
                            UserData loggedInUser = null;
                            try
                            {
                                /*
                                 * Using the Authentication Type ID and Authentication User ID is the only method for
                                 * logging a user in without having a password. Hence, any 3rd party authentication
                                 * system used in your application should have a unique Type ID.
                                 *
                                 * I arbitrarily chose 6000 to represent Twitter. As I add authentication schemes, I may
                                 * increment that value by 100 for each. E.g., Facebook = 6100, Google = 6200. These
                                 * are not standard. They are chosen by the developer.
                                 */
                                loggedInUser = UserCRUD.Login(TwitterAuthenticationId, AccessResponse.UserId);
                            }
                            catch { }

                            /*
                             * If the login above fails, the user object will still be null. It's via this check that we will
                             * know whether the login is successful or not. Null = unsuccessful.
                             *
                             * For attempts that are authenticated against twitter, but don't have a user account within the
                             * application, I chose to create their account automatically. You may, instead, choose
                             * to redirect the user to a form to establish a more complete profile before actually
                             * adding the user to the system.
                             */
                            if (loggedInUser == null)
                            {
                                /*
                                 * Establish the new, empty user object.
                                 */
                                var newUser = new UserData();

                                /*
                                 * This setting is often overlooked - so make sure you set it or everyone who signs in via
                                 * Twitter will become CMS Authors. Yikes!
                                 */
                                newUser.IsMemberShip = true;

                                /*
                                 * I'm using the visitor's Twitter Screen Name as their Username and Display Name within Ektron.
                                 *
                                 * These values must be unique. In my case, it helps to prefix their names with an @ symbol
                                 * in order to more closely align them with Twitter. :)
                                 */
                                newUser.Username    = string.Format("@{0}", AccessResponse.ScreenName);
                                newUser.DisplayName = newUser.Username;

                                /*
                                 * Authentication type id must be the same for every user authenticated against Twitter.
                                 */
                                newUser.AuthenticationTypeId = TwitterAuthenticationId;

                                /*
                                 * In Twitter, screen names can change, but User IDs cannnot. Use the User ID for this
                                 * so the user can change their Twitter screen name but still log in to your site.
                                 */
                                newUser.AuthenticationUserId = AccessResponse.UserId;

                                /*
                                 * Random, meaningless password. Ektron provides the method below for generating a random password
                                 * based on the validation expression.
                                 */
                                newUser.Password = UserCRUD.GetRandomPasswordforDefaultRegex();

                                /*
                                 * The twitter methods used so far do not provide a reliable first and last name. Some Twitter
                                 * users choose to enter these, but many do not. You may use another API to request this information
                                 * from Twitter or, because the fields are required in Ektron, do as I have done and enter
                                 * placeholder values.
                                 */
                                newUser.FirstName = "not set";
                                newUser.LastName  = "not set";

                                /*
                                 * Time Zone is a required custom property in any default Ektron installation. You may have this or
                                 * other required fields for your users - develop accordingly.
                                 *
                                 * There are ways to *guess* at a user's current time zone that are beyond the scope of this sample.
                                 * Ideas include:
                                 * * Requesting the information with JavaScript in a previous page load
                                 * * Using GeoIP data to get the time zone
                                 *
                                 * The GetCustomPropertyList method below gets the full set of properties with their default values.
                                 * Simply set those you need and then assign the list to the new user object.
                                 */
                                var customProps = UserCRUD.GetCustomPropertyList();
                                customProps["Time Zone"].Value = "Eastern Standard Time";
                                newUser.CustomProperties       = customProps;

                                /*
                                 * Add the new user to the CMS.
                                 */
                                newUser = UserCRUD.Add(newUser);

                                /*
                                 * Login the new user.
                                 */
                                UserCRUD.Login(newUser.AuthenticationTypeId, newUser.AuthenticationUserId);
                            }

                            /*
                             * Use a Redirect here to ensure Ektron's ECM cookie is properly set as well as to remove any lingering
                             * postback and unneeded viewstate data.
                             *
                             * Also removing the querystring, which contained values used to verify the authentication of the
                             * current user.
                             */
                            Response.Redirect(Request.RawUrl.Split('?')[0]);
                        }
                    }
                }
            }
        }
    }