I\'m creating an app with MVC4 that will authorize users using Twitter and lets them tweet from the app as well. I\'m able to get the user authenticated without a problem us
You can extract the oauth_token_secret from OAuthWebSecurity by designing your own TokenManager. You can register the token manager when you register your Twitter client in OAuthWebSecurity.RegisterClient.
I used this method to extract the needed values to be able to bypass the authorization step of the Linq-to-Twitter lib.
I will soon post my solution at my blog.
The DotNetOpenAuth.AspNet.Clients.TwitterClient
class only allows authentication, not authorization. So you wouldn't be able to post tweets as that user if you use that class.
Instead, you can use DotNetOpenAuth.ApplicationBlock.TwitterConsumer
, which does not share this limitation and you can even copy the source code for this type into your application and extend it as necessary.
You should be able to enhance the TwitterConsumer
class (once you've copied it into your own project) to implement the required interface so that the OAuthWebSecurity
class will accept it. Otherwise, you can just use TwitterConsumer
directly yourself to both authenticate and authorize your web app so the user only sees Twitter once but you get all the control you need. After all, folks using ASP.NET have been using TwitterConsumer
to both login and authorize for subsequent calls to Twitter for long before OAuthWebSecurity
even existed.
I've been banging my head against a wall with this for a few days now, but I finally have something that works. Would be interested to know if it's a valid solution though!
First off, create a new OAuthClient:
public class TwitterClient : OAuthClient
{
/// <summary>
/// The description of Twitter's OAuth protocol URIs for use with their "Sign in with Twitter" feature.
/// </summary>
public static readonly ServiceProviderDescription TwitterServiceDescription = new ServiceProviderDescription
{
RequestTokenEndpoint =
new MessageReceivingEndpoint(
"https://api.twitter.com/oauth/request_token",
HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
UserAuthorizationEndpoint =
new MessageReceivingEndpoint(
"https://api.twitter.com/oauth/authenticate",
HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
AccessTokenEndpoint =
new MessageReceivingEndpoint(
"https://api.twitter.com/oauth/access_token",
HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
};
public TwitterClient(string consumerKey, string consumerSecret) :
base("twitter", TwitterServiceDescription, consumerKey, consumerSecret) { }
/// Check if authentication succeeded after user is redirected back from the service provider.
/// The response token returned from service provider authentication result.
protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response)
{
string accessToken = response.AccessToken;
string accessSecret = (response as ITokenSecretContainingMessage).TokenSecret;
string userId = response.ExtraData["user_id"];
string userName = response.ExtraData["screen_name"];
var extraData = new Dictionary<string, string>()
{
{"accesstoken", accessToken},
{"accesssecret", accessSecret}
};
return new AuthenticationResult(
isSuccessful: true,
provider: ProviderName,
providerUserId: userId,
userName: userName,
extraData: extraData);
}
}
The important part is where you cast the response to an ITokenSecretContainingMessage. It appears that the response has the TokenSecret all along, but it is only on an internal property. By casting it, you get access to a public property. I can't say that I'm a fan of doing this, but then I also don't understand why DotNetOpenAuth the Asp.Net team have hidden the property in the first place. There must be a good reason.
You then register this client in AuthConfig:
OAuthWebSecurity.RegisterClient( new TwitterClient(
consumerKey: "",
consumerSecret: ""), "Twitter", null);
Now, in the ExternalLoginCallback method on the AccountController, the accessSecret is available in the ExtraData dictionary.
For a WebForms project template which references Microsoft.AspNet.Membership.OpenAuth in AuthConfig.cs instead of Microsoft.Web.WebPages.OAuth (MVC4 Internet Application) I was able to modify Paul Manzotti's answer to get it to work:
Create a custom twitter client class that derives from DotNetOpenAuth.AspNet.Clients.TwitterClient
public class CustomTwitterClient : TwitterClient { public CustomTwitterClient(string consumerKey, string consumerSecret) : base(consumerKey, consumerSecret) { }
protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response)
{
//return base.VerifyAuthenticationCore(response);
string accessToken = response.AccessToken;
string accessSecret = (response as ITokenSecretContainingMessage).TokenSecret;
string userId = response.ExtraData["user_id"];
string userName = response.ExtraData["screen_name"];
var extraData = new Dictionary<string, string>()
{
{"accesstoken", accessToken},
{"accesssecret", accessSecret}
};
return new AuthenticationResult(
isSuccessful: true,
provider: ProviderName,
providerUserId: userId,
userName: userName,
extraData: extraData);
}
}
Add the custom client in AuthConfig.cs
public static void RegisterOpenAuth()
{
OpenAuth.AuthenticationClients.Add("Twitter", () => new CustomTwitterClient(
consumerKey: ConfigurationManager.AppSettings["twitterConsumerKey"],
consumerSecret: ConfigurationManager.AppSettings["twitterConsumerSecret"]));
}
Ta-dow! Now you can haz access secret.