Your actual question should be something like 'Is it possible to use DotNetOpenAuth to sign requests with or without access token?", to answer that question I should say I don't know and even I can't find it out by reading DotNetOpenAuth codebase.
There is no single page of documentation available for DotNetOpenAuth and the codebase is so huge that you can't read it and understand what is supported by it or not.
I guess making non-authenticated request is not an issue as it is simply a query string parameter added to your request.
But to make signed requests you need to follow a simple process:
- Collecting request parameters
- Calculating signature
- Making request(signed/protected)
Collecting request parameters
These are basically two categories of parameters, oauth specific parameters and Netflix API specific parameters.
Among the OAuth specific parameters is nonce
, this is the code in which you can use to generate a nonce value:
public static string GenerateNonce()
{
byte[] bytes = new byte[32];
var first = Guid.NewGuid().ToByteArray();
var second = Guid.NewGuid().ToByteArray();
for (var i = 0; i < 16; i++)
bytes[i] = first[i];
for (var i = 16; i < 32; i++)
bytes[i] = second[i - 16];
var result = Convert.ToBase64String(bytes, Base64FormattingOptions.None);
result = new string(result.ToCharArray().Where(char.IsLetter).ToArray());
return result;
}
And another OAuth specific parameter is timestamp
, this is the code in which you can use to calculate timestamp:
DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds
Other oauth specific parameters are easy to provision and no need to write a specific code for them.
API specific parameters are any value you add to query string or to the authorization headers(except the oauth_signature itself) or to the body request(if request content type is application/x-www-form-urlencoded).
Calculating signature
To make either a signed request or a protected signature you need to calculate a signature, which the process is almost the same, except the way that you create signing key:
- Calculate signature base string
- Calculate signing key
- Creating the signature by signing the signature base string using signing key
To calculate signature base string you need to first concatenate all parameters into a string and the percent encode the whole string. This is the code which helps you doing percent encoding:
public static string Encode(string source)
{
Func<char, string> encodeCharacter = c => {
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '.' || c == '-' || c == '_' || c == '~'))
return new string(c, 1);
return EncodeCharacter(c);
};
return string.Concat(source.ToCharArray().Select(encodeCharacter));
}
Also you need to sort parameters in alphabetical order and be concatenated using '&'. Here is the code which you may have to write to do this:
public static string CalculateParameterString(KeyValuePair<string, string>[] parameters)
{
var q = from entry in parameters
let encodedkey = PercentEncode.Encode(entry.Key)
let encodedValue = PercentEncode.Encode(entry.Value)
let encodedEntry = encodedkey + "=" + encodedValue
orderby encodedEntry
select encodedEntry;
var result = string.Join("&", q.ToArray());
return result;
}
Lets call the above string 'parameters string'. Then to calculate signature base string all you need is to concatenate http verb of your request, your request's url and parameters string together using '&'. Also you need to percent encode them first. Here is the code which does that:
public static string CalcualteSignatureBaseString(string httpMethod, string baseUri, string parametersString)
{
return httpMethod.ToUpper() + "&" + PercentEncode.Encode(baseUri) + "&" + PercentEncode.Encode(parametersString);
}
Once you have created signature base string then you the next step is to calculate signing key.
- If you just need to make a signed request, then you create signing key based on your consumer key(shared secret) only. This the signing key to be used to make a signed request.
- During authorization process, if you just made a request token request and recieved a temporary oauth token, then your singing key is based on your consumer key and that oauth token. This is the signing key used to make request to get the access token.
- If a user authorized your application and you have the relevant access token, then your signing key would be your consumer key and access token. This is the signing key to make a protected request.
This is the code that will generate the signing key:
public static string GetSigningKey(string ConsumerSecret, string OAuthTokenSecret = null)
{
return ConsumerSecret + "&" + (OAuthTokenSecret != null ? OAuthTokenSecret : "");
}
In your case, to make a signed request, you just need pass null
value for OAuthTokenSecret parameter.
Ok, now you have a signature base string, all you need to do now is to sign using HMAC-SHA1 algorithm:
public static string Sign(string signatureBaseString, string signingKey)
{
var keyBytes = System.Text.Encoding.ASCII.GetBytes(signingKey);
using (var myhmacsha1 = new System.Security.Cryptography.HMACSHA1(keyBytes)) {
byte[] byteArray = System.Text.Encoding.ASCII.GetBytes(signatureBaseString);
var stream = new MemoryStream(byteArray);
var signedValue = myhmacsha1.ComputeHash(stream);
var result = Convert.ToBase64String(signedValue, Base64FormattingOptions.None);
return result;
}
}
To sum up this is the whole process for calculating signature:
public virtual string GetSignature(string consumerSecret, string tokenSecret, string uri, string method, params ParameterSet[] parameters)
{
var allParameters = parameters.SelectMany(p => p.ToList()).ToArray();
var parametersString = CalculateSignatureBaseString(allParameters);
var signatureBaseString = OAuth1aUtil.CalcualteSignatureBaseString(method, uri, parametersString);
var sigingKey = GetSigningKey(consumerSecret, tokenSecret);
var signature = Sign(signatureBaseString, sigingKey);
return signature;
}
Making request
Now you just need to make a valid http request and add the oauth parameters to the request as the 'Authorization' header.