I'm trying to connect to the Bricklink REST API using OAuth (http://apidev.bricklink.com/redmine/projects/bricklink-api/wiki/Authorization).
It should be pretty straight forward. However, I'm currently stuck and keep getting a SIGNATURE_INVALID error. My current attempt is shown below. Any suggestions?
const string consumerKey = "";
const string consumerSecret = "";
const string tokenSecret = "";
const string tokenValue = "";
const string url = "https://api.bricklink.com/api/store/v1/items/part/3001";
var httpWebRequest = (HttpWebRequest) WebRequest.Create(url);
httpWebRequest.Method = "GET";
var timeStamp = ((int) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
var nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(timeStamp));
var signatureBaseString = httpWebRequest.Method.ToUpper() + "&";
signatureBaseString = signatureBaseString + url.ToLower() + "&";
signatureBaseString = signatureBaseString + "oauth_consumer_key=" + consumerKey + "&";
signatureBaseString = signatureBaseString + "oauth_nonce=" + nonce + "&";
signatureBaseString = signatureBaseString + "oauth_signature_method=" + "HMAC-SHA1" + "&";
signatureBaseString = signatureBaseString + "oauth_timestamp=" + timeStamp + "&";
signatureBaseString = signatureBaseString + "oauth_token=" + tokenValue + "&";
signatureBaseString = signatureBaseString + "oauth_version=" + "1.0";
signatureBaseString = Uri.EscapeDataString(signatureBaseString);
Console.WriteLine(signatureBaseString);
var signatureEncoding = new ASCIIEncoding();
var keyBytes = signatureEncoding.GetBytes(consumerSecret + "&" + tokenSecret);
var signatureBaseBytes = signatureEncoding.GetBytes(signatureBaseString);
string signatureString;
using (var hmacsha1 = new HMACSHA1(keyBytes))
{
var hashBytes = hmacsha1.ComputeHash(signatureBaseBytes);
signatureString = Convert.ToBase64String(hashBytes);
}
signatureString = Uri.EscapeDataString(signatureString);
Console.WriteLine(signatureString);
string SimpleQuote(string x) => '"' + x + '"';
var header =
"OAuth realm=" + SimpleQuote("") + "," +
"oauth_consumer_key=" + SimpleQuote(consumerKey) + "," +
"oauth_nonce=" + SimpleQuote(nonce) + "," +
"oauth_signature_method=" + SimpleQuote("HMAC-SHA1") + "," +
"oauth_timestamp=" + SimpleQuote(timeStamp) + "," +
"oauth_token=" + SimpleQuote(tokenValue) + "," +
"oauth_version=" + SimpleQuote("1.0") + "," +
"oauth_signature= " + SimpleQuote(signatureString);
Console.WriteLine(header);
httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, header);
var response = httpWebRequest.GetResponse();
var characterSet = ((HttpWebResponse) response).CharacterSet;
var responseEncoding = characterSet == ""
? Encoding.UTF8
: Encoding.GetEncoding(characterSet ?? "utf-8");
var responsestream = response.GetResponseStream();
if (responsestream == null)
{
throw new ArgumentNullException(nameof(characterSet));
}
using (responsestream)
{
var reader = new StreamReader(responsestream, responseEncoding);
var result = reader.ReadToEnd();
Console.WriteLine(result);
}
I know that consumerKey, consumerSecret, tokenSecret, and tokenValue are correct as I can connect using the bricklink-api (https://www.npmjs.com/package/bricklink-api) using JavaScript.
After studying https://oauth.net/core/1.0/#signing_process again, I finally got it right. Note, the Escape function is not essential I just happened to stumble upon that one while trying to make things work.
const string consumerKey = "";
const string consumerSecret = "";
const string tokenSecret = "";
const string tokenValue = "";
const string url = "https://api.bricklink.com/api/store/v1/items/part/3001";
string Escape(string s)
{
// https://stackoverflow.com/questions/846487/how-to-get-uri-escapedatastring-to-comply-with-rfc-3986
var charsToEscape = new[] {"!", "*", "'", "(", ")"};
var escaped = new StringBuilder(Uri.EscapeDataString(s));
foreach (var t in charsToEscape)
{
escaped.Replace(t, Uri.HexEscape(t[0]));
}
return escaped.ToString();
}
var httpWebRequest = (HttpWebRequest) WebRequest.Create(url);
httpWebRequest.Method = "GET";
var timeStamp = ((int) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
var nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(timeStamp));
var signatureBaseString = Escape(httpWebRequest.Method.ToUpper()) + "&";
signatureBaseString += EscapeUriDataStringRfc3986(url.ToLower()) + "&";
signatureBaseString += EscapeUriDataStringRfc3986(
"oauth_consumer_key=" + EscapeUriDataStringRfc3986(consumerKey) + "&" +
"oauth_nonce=" + EscapeUriDataStringRfc3986(nonce) + "&" +
"oauth_signature_method=" + EscapeUriDataStringRfc3986("HMAC-SHA1") + "&" +
"oauth_timestamp=" + EscapeUriDataStringRfc3986(timeStamp) + "&" +
"oauth_token=" + EscapeUriDataStringRfc3986(tokenValue) + "&" +
"oauth_version=" + EscapeUriDataStringRfc3986("1.0"));
Console.WriteLine(#"signatureBaseString: " + signatureBaseString);
var key = EscapeUriDataStringRfc3986(consumerSecret) + "&" + EscapeUriDataStringRfc3986(tokenSecret);
Console.WriteLine(#"key: " + key);
var signatureEncoding = new ASCIIEncoding();
var keyBytes = signatureEncoding.GetBytes(key);
var signatureBaseBytes = signatureEncoding.GetBytes(signatureBaseString);
string signatureString;
using (var hmacsha1 = new HMACSHA1(keyBytes))
{
var hashBytes = hmacsha1.ComputeHash(signatureBaseBytes);
signatureString = Convert.ToBase64String(hashBytes);
}
signatureString = EscapeUriDataStringRfc3986(signatureString);
Console.WriteLine(#"signatureString: " + signatureString);
string SimpleQuote(string s) => '"' + s + '"';
var header =
"OAuth realm=" + SimpleQuote("") + "," +
"oauth_consumer_key=" + SimpleQuote(consumerKey) + "," +
"oauth_nonce=" + SimpleQuote(nonce) + "," +
"oauth_signature_method=" + SimpleQuote("HMAC-SHA1") + "," +
"oauth_timestamp=" + SimpleQuote(timeStamp) + "," +
"oauth_token=" + SimpleQuote(tokenValue) + "," +
"oauth_version=" + SimpleQuote("1.0") + "," +
"oauth_signature= " + SimpleQuote(signatureString);
Console.WriteLine(#"header: " + header);
httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, header);
var response = httpWebRequest.GetResponse();
var characterSet = ((HttpWebResponse) response).CharacterSet;
var responseEncoding = characterSet == ""
? Encoding.UTF8
: Encoding.GetEncoding(characterSet ?? "utf-8");
var responsestream = response.GetResponseStream();
if (responsestream == null)
{
throw new ArgumentNullException(nameof(characterSet));
}
using (responsestream)
{
var reader = new StreamReader(responsestream, responseEncoding);
var result = reader.ReadToEnd();
Console.WriteLine(#"result: " + result);
}
For anyone who is looking for way simpler solution. This works with WooCommerce and probably with other services. For WooCommerce token/tokenSecret is null.
var client = new RestClient($"{StoreHttp}/wp-json/wc/v3/products")
{
Authenticator = OAuth1Authenticator.ForProtectedResource(ConsumerKey, ConsumerSecret, token, tokenSecret)
};
var request = new RestRequest(Method.GET);
RestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Example with: RestSharp version: 108.0.3
Do not need to write code for signature creation. RestSharp does it all for you.
using System;
using RestSharp;
using RestSharp.Authenticators;
using RestSharp.Authenticators.OAuth;
using Newtonsoft.Json;
var client = new RestClient(URL);
var oAuth1 = OAuth1Authenticator.ForAccessToken(
consumerKey: ConsumerKey,
consumerSecret: ConsumerSecret,
token: Token,
tokenSecret: TokenSecret,
OAuthSignatureMethod.HmacSha256);
oAuth1.Realm = Realm; // if Realm has otherwise ignore
client.Authenticator = oAuth1;
var request = new RestRequest(URL, Method.Post);
request.AddHeader("Content-Type", "application/json");
string body = JsonConvert.SerializeObject(bodyObject);
request.AddParameter("application/json", body, ParameterType.RequestBody);
var response = client.Execute(request);
Related
OAuth1.0 authentication says:
Invalid signature - provided signature does not match." Error 401
I wanted to get data from an API provided by GravityForm, it completely works in Postman, but I can't get it through my own C# app.
I have tried different solutions provided by friends on Stackoverflow, but unfortunately, none of them work.
Here's my ultimate code:
private void button2_Click(object sender, EventArgs e)
{
string sig = GetAuthorizationToken();
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
var client = new RestClient("https://kashfsho.com/wp-json/gf/v2/entries/");
var request = new RestRequest(Method.GET);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("Content-Type", "application/json");
request.AddHeader("authorization", sig);
IRestResponse response = client.Execute(request);
}
public string GetAuthorizationToken()
{
timeStamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
nonce = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(timeStamp + timeStamp + timeStamp));
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("https://kashfsho.com/wp-json/gf/v2/entries/");
httpWebRequest.Method = "Get";
string consumer_secret = Uri.EscapeDataString(conSumerSecret);
string signature_base_string = GetSignatureBaseString(timeStamp, nonce);
SHA1HASH = GetSha1Hash(signature_base_string, consumer_secret); //also tried with nonEscaped consumer!
string Header =
"OAuth oauth_consumer_key=" + '"' + consumerKey + '"' + "," +
"oauth_nonce=" + '"' + nonce + '"' + "," +
"oauth_signature=" + '"' + SHA1HASH + '"' + "," +
"oauth_signature_method=" + '"' + #"HMAC-SHA1" + '"' + "," +
"oauth_timestamp=" + '"' + timeStamp + '"' + "," +
"oauth_version=" + '"' + "1.0" + '"';
return Header;
}
private string GetSha1Hash(string key, string t)
{
var encoding = new System.Text.ASCIIEncoding();
byte[] keyBytes = encoding.GetBytes(key);
byte[] messageBytes = encoding.GetBytes(t);
string strSignature = string.Empty;
using (HMACSHA1 SHA1 = new HMACSHA1(keyBytes))
{
var Hashed = SHA1.ComputeHash(messageBytes);
SHA1HASH = Convert.ToBase64String(Hashed);
}
return SHA1HASH;
}
public string GetSignatureBaseString(string TimeStamp, string Nonce)
{
//1.Convert the HTTP Method to uppercase and set the output string equal to this value.
string Signature_Base_String = "Get";
Signature_Base_String = Signature_Base_String.ToUpper();
//2.Append the ‘&’ character to the output string.
Signature_Base_String = Signature_Base_String + "&";
//3.Percent encode the URL and append it to the output string.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
string PercentEncodedURL = Uri.EscapeDataString("https://kashfsho.com/wp-json/gf/v2/entries/");
Signature_Base_String = Signature_Base_String + PercentEncodedURL;
//4.Append the ‘&’ character to the output string.
Signature_Base_String = Signature_Base_String + "&";
//5.append parameter string to the output string.
Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("oauth_consumer_key=" + consumerKey);
Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_nonce=" + Nonce);
Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_signature_method=" + "HMAC-SHA1");
Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_timestamp=" + TimeStamp);
Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_version=" + "1.0");
return Signature_Base_String;
}
Tried Solutions:
Generate OAuth1 signature in C#
Create OAuth Signature with HMAC-SHA1 Encryption returns HTTP 401
Using C# to create the Twitter authorization header for search
Oh, after about a month, I finally reached a solution. For authentication of GravityForm APIs, OAUTH 1.0 is not as stable as you may expect. Instead, you'd better use "BASIC AUTHENTICATION" like this:
USERNAME = consumerKey
Password = consumerSecret
Then you can use following solution:
RestSharp HttpBasicAuthentication - example
I am trying to call Azure Storage queue using REST API, but I am getting an error
The MAC signature found in the HTTP request
'UCiypkoySXueF4scXt+EqQESf5VXmAVLJUA93+3W10M=' is not the same as any
computed signature. The server used following string to sign: 'POST
text/plain
My C# Code is
var Client = new HttpClient();
var RequestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
if (Client.DefaultRequestHeaders.Contains("x-ms-date"))
Client.DefaultRequestHeaders.Remove("x-ms-date");
Client.DefaultRequestHeaders.Add("x-ms-date", RequestDateString);
var StorageAccountName = "storaxxxxxxxsnd";
var StorageKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==";
String urlPath = String.Format("{0}/messages", "splitator");
Uri uri = new Uri(string.Format("https://{0}.queue.core.windows.net/", StorageAccountName) + urlPath);
if (Client.DefaultRequestHeaders.Contains("Authorization"))
Client.DefaultRequestHeaders.Remove("Authorization");
var canonicalizedStringToBuild = string.Format("{0}\n{1}", RequestDateString, $"/{StorageAccountName}/{uri.AbsolutePath.TrimStart('/')}");
string signature;
using (var hmac = new HMACSHA256(Convert.FromBase64String(StorageKey)))
{
byte[] dataToHmac = Encoding.UTF8.GetBytes(canonicalizedStringToBuild);
signature = Convert.ToBase64String(hmac.ComputeHash(dataToHmac));
}
string authorizationHeader = string.Format($"{StorageAccountName}:" + signature);
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedKey", authorizationHeader);
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
if (Client.DefaultRequestHeaders.Contains("x-ms-version"))
Client.DefaultRequestHeaders.Remove("x-ms-version");
Client.DefaultRequestHeaders.Add("x-ms-version", "2015-12-11");
// if (httpMethod == HttpMethod.Delete || httpMethod == HttpMethod.Put)
// {
// if (Client.DefaultRequestHeaders.Contains("If-Match"))
// Client.DefaultRequestHeaders.Remove("If-Match");
// Currently I'm not using optimistic concurrency :-(
try
{
//Client.DefaultRequestHeaders.Add("If-Match", "*");
var stringContent = new StringContent("TESTAUTH", Encoding.UTF8, "text/plain");
var response= Client.PostAsync(uri, stringContent);
var resu=response.Result;
}
catch(Exception ex)
{
}
I am not sure what I am missing. I tried various combination but its failing.
I tried Microsoft recommended stringToSign formula too
I tried using canonical headers too
string signature;
var stringTosign = "POST\n" + "\n" + "\n" + "1024" + "\n" + "\n" + "text/plain\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + dateInRfc1123Format + "/xxxxxx/splitator/messages";
var hmac = new HMACSHA256(Convert.FromBase64String(accountKey));
var headerval= accountName + ":" + Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringTosign)));
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedKey", headerval);
Client.DefaultRequestHeaders.Accept.Clear();
I fixed the issue in your code, and now it's working. Please give it a try:
namespace ConsoleApp25
{
class Program
{
static void Main(string[] args)
{
var Client = new HttpClient();
var StorageAccountName = "yy1";
var StorageKey = "xxxx";
var apiversion = "2020-02-10";
var queue_name = "myqueue2";
String urlPath = String.Format("{0}/messages", queue_name);
Uri uri = new Uri(string.Format("https://{0}.queue.core.windows.net/{1}", StorageAccountName, urlPath));
//define a message to send
string raw_message = "TESTAUTH is ok";
//to send the message to the queue storage, the raw message must be formatted as below
string queue_message = $"<QueueMessage><MessageText>{raw_message}</MessageText></QueueMessage>";
//define the content type
string content_type = "text/plain; charset=utf-8";
//define date
var RequestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
string StringToSign = String.Format("POST\n"
+ "\n" // content encoding
+ "\n" // content language
+ queue_message.Length + "\n" // content length
+ "\n" // content md5
+ content_type +"\n" // content type
+ "\n" // date
+ "\n" // if modified since
+ "\n" // if match
+ "\n" // if none match
+ "\n" // if unmodified since
+ "\n" // range
+ "x-ms-date:" + RequestDateString + "\nx-ms-version:" + apiversion + "\n" // headers
+ "/{0}/{1}/{2}", StorageAccountName, queue_name, "messages"); //url
string auth = SignThis(StringToSign, StorageKey, StorageAccountName);
//define authorization header
if (Client.DefaultRequestHeaders.Contains("Authorization"))
Client.DefaultRequestHeaders.Remove("Authorization");
Client.DefaultRequestHeaders.Add("Authorization", auth);
Client.DefaultRequestHeaders.Accept.Clear();
//define x-ms-version header
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
if (Client.DefaultRequestHeaders.Contains("x-ms-version"))
Client.DefaultRequestHeaders.Remove("x-ms-version");
Client.DefaultRequestHeaders.Add("x-ms-version", apiversion);
//define the x-ms-date header
if (Client.DefaultRequestHeaders.Contains("x-ms-date"))
Client.DefaultRequestHeaders.Remove("x-ms-date");
Client.DefaultRequestHeaders.Add("x-ms-date", RequestDateString);
try
{
var stringContent = new StringContent(queue_message, Encoding.UTF8, "text/plain");
var response = Client.PostAsync(uri, stringContent);
var resu = response.Result;
}
catch (Exception ex)
{
}
Console.WriteLine("**completed**");
Console.ReadLine();
}
private static String SignThis(String StringToSign, string Key, string Account)
{
String signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(Key);
using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
{
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(StringToSign);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
Account,
signature);
return authorizationHeader;
}
}
}
And if you don't want to generate the shared key since it's not easy, you can use sas token for authentication in the rest api.
I am trying to generate a request_token using the oAuth method as mentioned in the links below:
https://dev.twitter.com/oauth/overview/creating-signatures
https://dev.twitter.com/oauth/reference/post/oauth/request_token
No matter how many times I go through the Twitter API oauth procedure, am failing to make my request work.
I came across this blog with an example on how to go about updating a user timeline.
https://garyshortblog.wordpress.com/2011/02/11/a-twitter-oauth-example-in-c/
Using the same concept I modified it a little to request a token
public string signedSignature(string status, string postBody, string oauth_consumer_key, string oauth_nonce, string oauth_signature_method,
string oauth_token, string callbackURL, string oauth_timestamp, string oauth_version)
{
//GS - When building the signature string the params
//must be in alphabetical order. I can't be bothered
//with that, get SortedDictionary to do it's thing
SortedDictionary<string, string> sd =
new SortedDictionary<string, string>();
//sd.Add("status", status);
sd.Add("include_entities", "true");
sd.Add("oauth_consumer_key", oauth_consumer_key);
sd.Add("oauth_nonce", oauth_nonce);
sd.Add("oauth_signature_method", oauth_signature_method);
sd.Add("oauth_timestamp", oauth_timestamp);
sd.Add("oauth_token", oauth_token);
sd.Add("oauth_version", oauth_version);
//GS - Build the signature string
string baseString = String.Empty;
baseString += "POST" + "&";
baseString += Uri.EscapeDataString(
"https://api.twitter.com/oauth/request_token")
+ "&";
foreach (KeyValuePair<string, string> entry in sd)
{
baseString += Uri.EscapeDataString(entry.Key +
"=" + entry.Value + "&");
}
//GS - Remove the trailing ambersand char, remember
//it's been urlEncoded so you have to remove the
//last 3 chars - %26
baseString =
baseString.Substring(0, baseString.Length - 3);
//GS - Build the signing key
string consumerSecret =
"<consumer Secret>";
string oauth_token_secret =
"<token secret>";
string signingKey =
Uri.EscapeDataString(consumerSecret) + "&" +
Uri.EscapeDataString(oauth_token_secret);
//GS - Sign the request
HMACSHA1 hasher = new HMACSHA1(
new ASCIIEncoding().GetBytes(signingKey));
string signatureString = Convert.ToBase64String(
hasher.ComputeHash(
new ASCIIEncoding().GetBytes(baseString)));
return signatureString;
}
public ActionResult AccessToken()
{
//GS - Get the oAuth params
string status = "Hello Ladies + Gentlemen, a signed OAuth request!";
string postBody = "status=" +
Uri.EscapeDataString(status);
string oauth_consumer_key = "bidjtABOkF0b3mvw1UaHWDf7x";
string oauth_nonce = Convert.ToBase64String(
new ASCIIEncoding().GetBytes(
DateTime.Now.Ticks.ToString()));
string oauth_signature_method = "HMAC-SHA1";
string oauth_token =
"84473240-brz5BNw9r2WfbufzJ2WjaLysCBHmJjhjJxMVGz8Od";
string callbackURL = Uri.EscapeDataString("http://localhost:37808/");
TimeSpan ts = DateTime.UtcNow -
new DateTime(1970, 1, 1, 0, 0, 0, 0);
string oauth_timestamp =
Convert.ToInt64(ts.TotalSeconds).ToString();
string oauth_version = "1.0";
string sSig = signedSignature(status, postBody, oauth_consumer_key, oauth_nonce, oauth_signature_method, oauth_token,
callbackURL, oauth_timestamp, oauth_version);
//GS - Tell Twitter we don't do the 100 continue thing
ServicePointManager.Expect100Continue = false;
//GS - Instantiate a web request and populate the
//authorization header
HttpWebRequest hwr =
(HttpWebRequest)WebRequest.Create(
#"https://api.twitter.com/oauth/request_token");
string authorizationHeaderParams = String.Empty;
authorizationHeaderParams += "OAuth ";
authorizationHeaderParams += "oauth_nonce=" + "\"" +
Uri.EscapeDataString(oauth_nonce) + "\",";
authorizationHeaderParams +=
"oauth_signature_method=" + "\"" +
Uri.EscapeDataString(oauth_signature_method) +
"\",";
authorizationHeaderParams += "oauth_callback=" + "\"" +
callbackURL + "\",";
authorizationHeaderParams += "oauth_timestamp=" + "\"" +
Uri.EscapeDataString(oauth_timestamp) + "\",";
authorizationHeaderParams += "oauth_consumer_key="
+ "\"" + Uri.EscapeDataString(
oauth_consumer_key) + "\",";
authorizationHeaderParams += "oauth_signature=" + "\""
+ Uri.EscapeDataString(sSig) + "\",";
authorizationHeaderParams += "oauth_version=" + "\"" +
Uri.EscapeDataString(oauth_version) + "\"";
hwr.Headers.Add(
"Authorization", authorizationHeaderParams);
//GS - POST off the request
hwr.Method = "POST";
hwr.ContentType = "application/x-www-form-urlencoded";
Stream stream = hwr.GetRequestStream();
byte[] bodyBytes =
new ASCIIEncoding().GetBytes(postBody);
stream.Write(bodyBytes, 0, bodyBytes.Length);
stream.Flush();
stream.Close();
//GS - Allow us a reasonable timeout in case
//Twitter's busy
hwr.Timeout = 3 * 60 * 1000;
try
{
HttpWebResponse rsp = hwr.GetResponse()
as HttpWebResponse;
rsp.StatusCode.ToString();
//GS - Do something with the return here...
}
catch (WebException e)
{
//GS - Do some clever error handling here...
}
return View();
}
I am not sure where exactly am going wrong. I have gone through the documents several times and cant seem to find out where I have gone wrong?
The error I get is 401 Unauthorized access
Out of no where, my twitter API calls, specificly my first step in the 3-legged auth, stopped working. I've compared the timestamps, keys and everything with the OAuth signature generator tool, and they all match (execpt oauth_nonce but thats the point I guess). Here is my code. Any suggestions or small observations would be appreciated.
protected void RequestToken()
{
string oauthcallback = Request.Url.Host + "/TwitterCallback.aspx";
string oauthconsumerkey = "xxx-consumerkey";
string oauthconsumersecret = "xxx-consumerSecret";
string oauthtokensecret = string.Empty;
string oauthtoken = string.Empty;
string oauthsignaturemethod = "HMAC-SHA1";
string oauthversion = "1.0";
string oauthnonce = Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
TimeSpan timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
string oauthtimestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();
string url = "https://api.twitter.com/oauth/request_token?oauth_callback=" + oauthcallback;
SortedDictionary<string, string> basestringParameters = new SortedDictionary<string, string>();
basestringParameters.Add("oauth_version", oauthversion);
basestringParameters.Add("oauth_consumer_key", oauthconsumerkey);
basestringParameters.Add("oauth_nonce", oauthnonce);
basestringParameters.Add("oauth_signature_method", oauthsignaturemethod);
basestringParameters.Add("oauth_timestamp", oauthtimestamp);
basestringParameters.Add("oauth_callback", Uri.EscapeDataString(oauthcallback));
//Build the signature string
string baseString = String.Empty;
baseString += "POST" + "&";
baseString += Uri.EscapeDataString(url.Split('?')[0]) + "&";
foreach (KeyValuePair<string, string> entry in basestringParameters)
{
baseString += Uri.EscapeDataString(entry.Key + "=" + entry.Value + "&");
}
//Remove the trailing ambersand char last 3 chars - %26
//baseString = baseString.Substring(0, baseString.Length - 3);
//Build the signing key
string signingKey = Uri.EscapeDataString(oauthconsumersecret) +
"&" + Uri.EscapeDataString(oauthtokensecret);
//Sign the request
HMACSHA1 hasher = new HMACSHA1(new ASCIIEncoding().GetBytes(signingKey));
string oauthsignature = Convert.ToBase64String(
hasher.ComputeHash(new ASCIIEncoding().GetBytes(baseString)));
//Tell Twitter we don't do the 100 continue thing
ServicePointManager.Expect100Continue = false;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(#url);
string authorizationHeaderParams = String.Empty;
authorizationHeaderParams += "OAuth ";
authorizationHeaderParams += "oauth_nonce=" + "\"" +
Uri.EscapeDataString(oauthnonce) + "\",";
authorizationHeaderParams += "oauth_signature_method=" + "\"" +
Uri.EscapeDataString(oauthsignaturemethod) + "\",";
authorizationHeaderParams += "oauth_timestamp=" + "\"" +
Uri.EscapeDataString(oauthtimestamp) + "\",";
authorizationHeaderParams += "oauth_consumer_key=" + "\"" +
Uri.EscapeDataString(oauthconsumerkey) + "\",";
authorizationHeaderParams += "oauth_signature=" + "\"" +
Uri.EscapeDataString(oauthsignature) + "\",";
authorizationHeaderParams += "oauth_version=" + "\"" +
Uri.EscapeDataString(oauthversion) + "\"";
webRequest.Headers.Add("Authorization", authorizationHeaderParams);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
//Allow us a reasonable timeout in case Twitter's busy
webRequest.Timeout = 3 * 60 * 1000;
try
{
HttpWebResponse webResponse = webRequest.GetResponse() as HttpWebResponse;
Stream dataStream = webResponse.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
var uri = new Uri("https://test.dk?" + responseFromServer);
var token = HttpUtility.ParseQueryString(uri.Query).Get("oauth_token"); ;
var tokensecret = HttpUtility.ParseQueryString(uri.Query).Get("oauth_token_secret");
Response.Write(responseFromServer);
Response.Redirect("https://api.twitter.com/oauth/authorize?force_login=true&oauth_token=" + token);
}
catch (Exception ex)
{
Response.Write(ex.GetBaseException());
}
}
The error obviously happens when I do the HTTP request webRequest.GetResponse()
It returns a 401 unauthorized
Apperently you have to include the oauth version number in the URL now, or else it will fall back to the oldest version (or maybe the newest, can't remember).
Providing /oath/1.0/ or /1.0/oauth/ or what ever solved my issue as i recall it (it's been a while).
Im trying to convert Java program to C#. This programe sent JSON object to server using a HTTP POST. Java program works fine. return 200. But C# program return 400 (bad request). What can be the cause
Java Code
String base_url = "https://test-url.com";
String username = "test-user";
String password = "test-pass";
String client_id = "test-client";
String client_secret = "test-key";
String loginUrl = base_url + "session/login";
Charset utf8 = Charset.forName("UTF-8");
ContentType jason_content_type = ContentType.create("application/json", utf8);
try {
HttpClient c = HttpClients.custom().setUserAgent(client_id + "/1.0").build();
HttpPost p = new HttpPost(loginUrl);
String json_str = "{" + "\"userId\":\"" + username + "\"," + "\"password\":\"" + password + "\"," + "\"clientId\":\"" + client_id + "\"," + "\"clientSecret\":\"" + client_secret + "\"" + "}";
p.setEntity(new StringEntity(json_str, jason_content_type));
HttpResponse r = c.execute(p);
int status = r.getStatusLine().getStatusCode();
} catch (IOException e) {
System.out.println(e);
}
C# Code
string base_url = "https://test-url.com";
string username = "test-user";
string password = "test-pass";
string client_id = "test-client";
string client_secret = "test-key";
string login_url = base_url + "session/login";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(login_url);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = WebRequestMethods.Http.Post;
httpWebRequest.UserAgent = client_id + "/1.0";
httpWebRequest.ProtocolVersion=HttpVersion.Version11;
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream(), Encoding.UTF8))
{
string json_str = "{" + "\"userId\":\"" + username + "\"," + "\"password\":\"" + password + "\"," + "\"clientId\":\"" + client_id + "\"," + "\"clientSecret\":\"" + client_secret + "\"" + "}";
streamWriter.Write(json_str);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
Try out adding in C# :
httpWebRequest.ContentType = "application/x-www-form-urlencoded";