twittertwitter-oauthtweetinvi

AuthFlow.CreateCredentialsFromVerifierCode throws error only on load balancer


I am using Tweetinvi for posting images to Twitter. From our App servers its working fine to post to Twitter. But, When tried from our load balancer getting this error -

Error:The credentials are required as the URL does not contain the credentials identifier.

Stack Trace: at Tweetinvi.AuthFlow.CreateCredentialsFromVerifierCode(String verifierCode, String authorizationId, IAuthenticationContext authContext)

My code snippet is like this -

var verifierCode = Request.Params.Get("oauth_verifier");
var authorizationId = Request.Params.Get("authorization_id");
var userCreds = AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, authorizationId);

I see these parameters(oauth_verifier, authorization_id,..) being passed to the callback page. But still seeing the above error in the call back page.

Note: this issue is only when I try posting to Twitter on our loadbalancer (using the individual servers working fine). Should I use a different overloaded function?


Solution

  • So the problem comes from the fact that you are actually using a load balancer. But let me explain how the authentication works and how you can solve your problem.

    var appCredentials = new ConsumerCredentials("", "");
    var authContext = AuthFlow.InitAuthentication(appCredentials, "");
    

    When you call AuthFlow.InitAuthentication, it returns an IAuthenticationContext. This context contains all the information required to process the callback from Twitter.

    But in addition to this, Tweetinvi adds a parameter authorization_id to the callback so that it can map the callback request to an actual IAuthenticationContext.

    var authorizationId = Request.Params.Get("authorization_id");
    var userCreds = AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, authorizationId);
    

    When you call AuthFlow.CreateCredentialsFromVerifierCode with an authorization_id as a parameter it will look into the local dictionary and try to get the IAuthenticationContext.

    Because you are using a load balancer, the server executing the AuthFlow.InitAuthentication can be different from the server your receiving the callback request.

    Because your callback arrives at a different server, it actually result in the AuthenticationContext being null.

    This is what I tried to explain in the documentation.

    How to solve this?

    What you need to do is to store the IAuthenticationContext information required for the CreateCredentialsFromVerifierCode to continue its work when it receives the callback. I would suggest you store this in your database.

    When you receive your callback you will have to get back these information from your db. To do that I would suggest that when you initally call the `` you add to the callback url a parameter with the value storing the authentication id in your database (e.g. my_auth_db_id=42).

    var authContext = AuthFlow.InitAuthentication(appCredentials, "http://mywebsite.com?my_auth_db_id=42");
    

    When your callback arrives you will be able to do :

    var myDBAuthId = Request.Params.Get("my_auth_db_id");
    

    With this value you can now create a new token with the required information (stored in the db).

    var token = new AuthenticationToken()
    {
        AuthorizationKey = "<from_db>",
        AuthorizationSecret = "<from_db>",
        ConsumerCredentials = creds
    };
    

    Now you are ready to complete the operation:

    var userCreds = AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, token );
    

    I realize this is a big post, but I wanted to explain how it works. Please let me know if anything does not makes sense.