Search code examples
c#authenticationtwittertweetinvi

Publishing tweets from C# Windows service using Tweetinvi or similar


I am looking into publishing some service status updates on Twitter using Tweetinvi, which seems like a good library for doing that sort of thing, but I am just starting out looking into this so using it is not set in stone.

However, one thing my research has not yielded yet, is an obvious way to handle Twitter authentication in what is essentially a headless service. I have created an app with Twitter, so I have my consumer key and secret, and I can do the "app only" auth to request user info, get their followers etc., but of course I have no right to publish tweets.

So my ambition is (once this is out of beta) to create a proper twitter account, somehow have the service authenticate towards that account, and then publish status updates from the general service at defined intervals. It is a fairly simple idea.

Of course, I can do something like the PIN based authentication mentioned here:

https://github.com/linvi/tweetinvi/wiki/Authentication

I can run that manually, get the PIN code, and proceed with the workflow. But will this require reauthentication at regular intervals, or will it basically be valid "forever"? I am looking for a way to make this as automatic as possible, and having to redo the auth every x hours is a huge dent in this dream, if not a showstopper.

Of course I will have the password for the twitter account used to publish statuses, but I don't see a way to do a good old fashioned login without manual user intervention - what options do I have?


Solution

  • This behavior is by design. Twitter uses OAuth, which is a protocol with the purpose of allowing a user to authorize an application. This is good for the user because otherwise, you or anyone else can perform actions on their behalf without them knowing.

    With that in mind, the only way to do this is to have the user explicitly authorize your app. Here's an example of how to do this with LINQ to Twitter, which I wrote, using ASP.NET MVC. When the user visit's your page, you can have a button that re-directs them to the OAuthController below to the BeginAsync action.

    using System;
    using System.Configuration;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Web.Mvc;
    using LinqToTwitter;
    
    namespace MvcDemo.Controllers
    {
        public class OAuthController : AsyncController
        {
            public ActionResult Index()
            {
                return View();
            }
    
            public async Task<ActionResult> BeginAsync()
            {
                //var auth = new MvcSignInAuthorizer
                var auth = new MvcAuthorizer
                {
                    CredentialStore = new SessionStateCredentialStore
                    {
                        ConsumerKey = ConfigurationManager.AppSettings["consumerKey"],
                        ConsumerSecret = ConfigurationManager.AppSettings["consumerSecret"]
                    }
                };
    
                string twitterCallbackUrl = Request.Url.ToString().Replace("Begin", "Complete");
                return await auth.BeginAuthorizationAsync(new Uri(twitterCallbackUrl));
            }
    
            public async Task<ActionResult> CompleteAsync()
            {
                var auth = new MvcAuthorizer
                {
                    CredentialStore = new SessionStateCredentialStore()
                };
    
                await auth.CompleteAuthorizeAsync(Request.Url);
    
                // This is how you access credentials after authorization.
                // The oauthToken and oauthTokenSecret do not expire.
                // You can use the userID to associate the credentials with the user.
                // You can save credentials any way you want - database, 
                //   isolated storage, etc. - it's up to you.
                // You can retrieve and load all 4 credentials on subsequent 
                //   queries to avoid the need to re-authorize.
                // When you've loaded all 4 credentials, LINQ to Twitter will let 
                //   you make queries without re-authorizing.
                //
                //var credentials = auth.CredentialStore;
                //string oauthToken = credentials.OAuthToken;
                //string oauthTokenSecret = credentials.OAuthTokenSecret;
                //string screenName = credentials.ScreenName;
                //ulong userID = credentials.UserID;
                //
    
                return RedirectToAction("Index", "Home");
            }
        }
    }
    

    After the user authorizes your application, Twitter redirects them back to the CompleteAsync method. Notice the comments on how to extract values from the auth.CredentialStore. Save those in your DB and then retrieve them in your service to make calls on the user's behalf.

    Those credentials don't change, but the user can possibly de-authorize your application at some time in the future - at which time you'll need to get them to authorize again. You can get the entire sample code at the LINQ to Twitter ASP.NET Samples page.