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?
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.
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.