0
votes

I want to send post using Twitter api in C#, .Net Core 3.1. I can send post using "update/status" twitter api with OAuth 1.0 authentication successfully. But when I write comma inside query strings, api returns 401.

For Example, first request runs successfully but second one is not. Only diffrence is comma. I am using Uri.EscapeDataString(). But its not working. What am I missing? Please help me. Thank you.

public class OAuth1Manager : IOAuth1Service
{
    private OAuth1Request _request;
    private List<string> _requestParameters;
    private List<string> _signatureParameters;

    public List<string> GetQueryStrings(string url)
    {
        var splitted = url.Split("?");
        if (splitted.Length > 1)
        {
            return splitted[1].Split("&").ToList();
        }
        return new string[0].ToList();
    }

    public string GetSignedOAuthString(OAuth1Request request)
    {
        _request = request;
        _requestParameters = new List<string>
        {
            $"oauth_consumer_key={_request.OAuth.ConsumerKey}",
            $"oauth_signature_method=HMAC-SHA1",
            $"oauth_timestamp={GetTimeStamp()}",
            $"oauth_nonce={GetNonce()}",
            $"oauth_token={request.OAuth.AccessToken}",
            $"oauth_version=1.0",
        };

        _signatureParameters = new List<string>();
        _signatureParameters.AddRange(_requestParameters);
        _signatureParameters.AddRange(GetQueryStrings(_request.Url));

        _requestParameters.Add($"oauth_signature={GetSignature()}");

        for (int i = 0; i < _requestParameters.Count; i++)
        {
            var parameter = _requestParameters[i];
            var splitted = parameter.Split("=");
            _requestParameters[i] = $"{splitted[0]}=\"{splitted[1]}\"";
        }
        return $"OAuth {_requestParameters.JoinAsString(",")}";

    }

    private string GetNonce()
    {
        var rand = new Random();
        var nonce = rand.Next(1000000000);
        return nonce.ToString();
    }

    private string GetSignatureBaseString()
    {
        var sortedList = new List<string>(_signatureParameters);
        sortedList.Sort();
        var requestParametersSortedString = sortedList.JoinAsString("&");
        var url = ConstructRequestUrl();

        return _request.Method.GetEnumDescription().ToUpper() + "&" + Uri.EscapeDataString(url) + "&" +
              Uri.EscapeDataString(requestParametersSortedString);
    }

    private string ConstructRequestUrl()
    {
        var uri = new Uri(_request.Url, UriKind.Absolute);
        var normUrl = string.Format("{0}://{1}", uri.Scheme, uri.Host);
        if (!(uri.Scheme == "http" && uri.Port == 80 ||
              uri.Scheme == "https" && uri.Port == 443))
            normUrl += ":" + uri.Port;

        normUrl += uri.AbsolutePath;

        return normUrl;
    }

    private string GetSignature()
    {
        var hmacsha1 = new HMACSHA1();
        var key = Uri.EscapeDataString(_request.OAuth.ConsumerSecret) + "&" + (string.IsNullOrEmpty(_request.OAuth.TokenSecret)
                      ? ""
                      : Uri.EscapeDataString(_request.OAuth.TokenSecret));

        hmacsha1.Key = Encoding.ASCII.GetBytes(key);

        var dataBuffer = Encoding.ASCII.GetBytes(GetSignatureBaseString());
        var hashBytes = hmacsha1.ComputeHash(dataBuffer);
        return Uri.EscapeDataString(Convert.ToBase64String(hashBytes));
    }

    private string GetTimeStamp()
    {
        var ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
        return Convert.ToInt64(ts.TotalSeconds).ToString();
    }
}
1
Try https://api.twitter.com/1.1/statuses/update.json?status=test1%2Ctest2 and don't leave an empty space there, if you really need a space, you can use %20.Coke
Return $"OAuth {_requestParameters.JoinAsString("%2C")}"; from GetSignedOAuthString() function.Coke
I tried JoinAsString("%2C") then I get 400 bad request. But when I tried test1%2Ctest2, it worked. Thanks a lot.Ömer Emrecan TUNA
Awesome, 400 would mean that your request was incomplete, however this check happens after you have successfully authorized, so I think you just need to reconsider the way you build your request.Coke

1 Answers

1
votes

I replaced all commas with %2C like "test1%2Ctest2" instead of "test1,test2" then it worked.