As promissed in
my previous post, where I dived in the the difference between a 2-legged and a 0-lgeed oauth,
I will show in this post how to build a 0-legged oauth using the DotNetOpenAuth library. Just to remember, a 0-legged oauth consists of a consumer accessing the protected resources submitting oauth signed requests using just the consumer key and the consumer secret.
I will take as an example the UserVoice API, the method to list all the users for a given site, which requires a 0-legged API.
Before you use the UserVoice API or another oauth API from a service provider, the first thing to to is to get a consumer key and a consumer secret. This process is more or less the same in all service providers, but you have to check with the service provider how to get them. Here is a screenshot how I got this data from UserVoice site, in the admin console
Next, in our visual studio project, we have to get the libraries of dotnetopenauth. Since we are consuming an oauth API, we have to get the Nuget package DotNetOpenAuth.OAuth.Consumer.
The main class when consuming an API is the class WebConsumer in namespace DotNetOpenAuth.OAuth. The constructor of this class receives two arguments as show below
public WebConsumer(ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager);
In our case the serviceDescription is something like this
var providerDesc = new ServiceProviderDescription()
{
RequestTokenEndpoint = new MessageReceivingEndpoint("https://bfcamara.uservoice.com/oauth/request_token", HttpDeliveryMethods.PostRequest),
AccessTokenEndpoint = new MessageReceivingEndpoint("https://bfcamara.uservoice.com/oauth/access_token", HttpDeliveryMethods.PostRequest),
UserAuthorizationEndpoint = new MessageReceivingEndpoint("https://bfcamara.uservoice.com/oauth/authorize", HttpDeliveryMethods.PostRequest),
ProtocolVersion = ProtocolVersion.V10a,
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] {
new HmacSha1SigningBindingElement()
}
};
Basically we are describing the oauth endpoints that will be used in the oauth dance, the oauth version, and the signing policy used in the service provider, which in this case is the method HMAC-SHA1 defined in RFC2104. Next we have to write our token manager, which must implement the interface IConsumerTokenManager (whic must implement the ITokenManager interface). Using the Alt-F10 Implement Interface of Visual Studio we get the skeleton of our class
public class ZeroLeggedTokenManager : IConsumerTokenManager
{
public string ConsumerKey
{
get { throw new NotImplementedException(); }
}
public string ConsumerSecret
{
get { throw new NotImplementedException(); }
}
public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret)
{
throw new NotImplementedException();
}
public string GetTokenSecret(string token)
{
throw new NotImplementedException();
}
public TokenType GetTokenType(string token)
{
throw new NotImplementedException();
}
public void StoreNewRequestToken(DotNetOpenAuth.OAuth.Messages.UnauthorizedTokenRequest request, DotNetOpenAuth.OAuth.Messages.ITokenSecretContainingMessage response)
{
throw new NotImplementedException();
}
}
Since we are using a 0-legged oauth, we have just to worry with the GetTokenSecret method, and the getter properties of our consumer key and consumer secret. Here is the final version of our token manager
public class ZeroLeggedTokenManager : IConsumerTokenManager
{
private string _consumerKey;
private string _consumerSecret;
public ZeroLeggedTokenManager(string consumerKey, string consumerSecret)
{
_consumerKey = consumerKey;
_consumerSecret = consumerSecret;
}
public string ConsumerKey { get { return _consumerKey; }}
public string ConsumerSecret { get { return _consumerSecret; } }
public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret)
{
throw new NotImplementedException();
}
public string GetTokenSecret(string token)
{
return "";
}
public TokenType GetTokenType(string token)
{
throw new NotImplementedException();
}
public void StoreNewRequestToken(DotNetOpenAuth.OAuth.Messages.UnauthorizedTokenRequest request, DotNetOpenAuth.OAuth.Messages.ITokenSecretContainingMessage response)
{
throw new NotImplementedException();
}
}
Now we can create our token manager
var tokenManager = new ZeroLeggedTokenManager(CONSUMER_KEY, CONSUMER_SECRET);
The CONSUMER_KEY and CONSUMER_SECRET are constants which contains the values of the consumer key and secret respectively.
Finally we can create our consumer and use it to make the call, using the method PrepareAuthorizeRequestAndSend
var zeroLeggedWebConsumer = new DotNetOpenAuth.OAuth.WebConsumer(providerDesc, tokenManager);
var response = zeroLeggedWebConsumer.PrepareAuthorizedRequestAndSend(
new MessageReceivingEndpoint("https://bfcamara.uservoice.com/api/v1/users.json",
HttpDeliveryMethods.GetRequest), "DUMMY");
When calling the PrepareAuthorizedRequestToken, we have to pass the endpoint to call, and the token to use, which will be used by the consumer to ask to our token manager what is the secret associated with this token. There is a little trick here: since our secret is always an empty secret returned by the token manager, it's quite irrelevant what you pass to the method, however it cannot be null or empty, which is not allowed. In our case we pass "DUMMY" as the token. (If you pass an empty or null token you will get an exception at runtime thrown by dotnetopenauth library).
Using Fiddler Web Debugger, you can check the content of the request/response
Now you can parse the response as you want.
Sumarizing, in this post, I demonstrated how to use the DotNetOpenAuth library to consume API's with a 0-legged OAuth.