0

1st. step, getting url to verify, and verifier is ok.

Using the same method that in the request_token to sign the request, I get "unauthorized", "oauth_problem = signature invalid".

I verify the code letter by letter, and I can't find the problem.

  1. step, request token -> OK
  2. Get verifier code in the url -> OK
  3. Generating the access_token, signature invalid.

I had serveral functions, but I put the code readable in a single function to find the problem:

public void GetAccessToken(string oauthVerifier)
    {
        IRestResponse response;

        RestClient client = new RestClient(apiURI);
        string timeStamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
        string atNonce = Guid.NewGuid().ToString();


        RestRequest request = new RestRequest(GET_ACCESS_TOKEN_URL, Method.GET);

        request.AddParameter("oauth_consumer_key", consumerKey);
        request.AddParameter("oauth_timestamp", timeStamp);
        request.AddParameter("oauth_nonce", atNonce);
        request.AddParameter("oauth_signature_method", SIGNATURE_METHOD);
        request.AddParameter("oauth_signature", "");
        request.AddParameter("oauth_token", token);
        request.AddParameter("oauth_verifier", oauthVerifier);

        //var parameters = new SortedDictionary<string, string>();


        var parameters = new SortedDictionary<string, string>
        {
            {"oauth_consumer_key", consumerKey},
            {"oauth_timestamp", timeStamp},
            {"oauth_nonce", atNonce},
            {"oauth_signature_method", SIGNATURE_METHOD},
            { "oauth_token", token },
            { "oauth_verifier", oauthVerifier }
        };

        var sb = new StringBuilder();
        sb.Append("GET");
        sb.Append("&" + WebUtility.UrlEncode(apiURI + GET_ACCESS_TOKEN_URL));
        sb.Append("&" + WebUtility.UrlEncode(NormalizeParameters(parameters)));

        var signatureBase = sb.ToString();
        var signatureKey = string.Format("{0}&{1}", WebUtility.UrlEncode(consumerSecret), WebUtility.UrlEncode(tokenSecret));

        var hmac = new HMACSHA1(Encoding.ASCII.GetBytes(signatureKey));
        string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.ASCII.GetBytes(signatureBase)));

        request.Parameters[4].Value = signature;


        response = client.Execute(request);
    }

The response variable get "unauthorized" because the "signature_invalid".

Any help is welcome, thank you in advance!

Update 1

Oauth documentation says that the signature have to be urlencoded too, then I after convert it to base 64 string, I urlencode it too:

request.Parameters[4].Value = WebUtility.UrlEncode(signature);

Whatever, still returning "signature invalid".

Some light from the sky there? Thank you!

bakerwitz
  • 48
  • 3
  • 8
  • 1
    Is your `token` variable already encoded before using it in the request params and sig. base string? Also please show your `NormalizeParameters` method. – Anthony McGrath Aug 09 '20 at 14:19
  • 1
    Did you ever get this to work? Having the same issue – Adrian Aug 18 '21 at 04:46
  • I just managed to get this work. For me the issue was ridiculous. The token secret coming back with the request token was being url encoded in C# automatically. So when I created the hmac hash for the access token it was being doubly url encoded. I simply had to url decode it. – Adrian Aug 18 '21 at 05:43
  • For reference, this one worked immediately https://stackoverflow.com/questions/65442903/etrade-api-frequently-returns-http-401-unauthorized-when-fetching-an-access-tok – EtradeTester Oct 14 '22 at 19:15

2 Answers2

0

also review this header from E-Trade link, I might have missed out some specifics

Authorization: OAuth oauth_nonce="0bba225a40d1bbac2430aa0c6163ce44",oauth_timestamp="1344885636",oauth_consumer_key="c5bb4dcb7bd6826c7c4340df3f791188",oauth_token="VbiNYl63EejjlKdQM6FeENzcnrLACrZ2JYD6NQROfVI%3D",oauth_signature="%2FXiv96DzZabnUG2bzPZIH2RARHM%3D",oauth_signature_method="HMAC-SHA1"

`public void GetAccessToken(string oauthVerifier) { IRestResponse response;

    RestClient client = new RestClient(apiURI);
    string timeStamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
    string atNonce = Guid.NewGuid().ToString();


    RestRequest request = new RestRequest(GET_ACCESS_TOKEN_URL, Method.GET);

    var parameters = new SortedDictionary<string, string>
    {
        {"oauth_consumer_key", consumerKey},
        {"oauth_timestamp", timeStamp},
        {"oauth_nonce", atNonce},
        {"oauth_signature_method", SIGNATURE_METHOD},
        {"oauth_token", token },
        {"oauth_verifier", oauthVerifier }
    };

    var sb = new StringBuilder();
    sb.Append("GET");
    sb.Append("&" + WebUtility.UrlEncode(apiURI + GET_ACCESS_TOKEN_URL));

    //does NormalizeParameters seperate by "&"
    sb.Append("&" + WebUtility.UrlEncode(NormalizeParameters(parameters)));

    var signatureBase = sb.ToString();
    var signatureKey = string.Format("{0}&{1}", WebUtility.UrlEncode(consumerSecret), WebUtility.UrlEncode(tokenSecret));

    var hmac = new HMACSHA1(Encoding.ASCII.GetBytes(signatureKey));
    string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.ASCII.GetBytes(signatureBase)));

    //encode signature
    signature = "oauth_signature=\"" + WebUtility.UrlEncode(signature) + "\""

    //TODO: generate header_string seperated by ","
    request.AddHeader("Authorization",$"OAuth {<<header_string>>},{signature}");

    response = client.Execute(request);
}`
Ralph
  • 309
  • 1
  • 8
  • Hi Ralph, thanks for you answer! Is not the case. Still getting signature invalid. I also tested it putting in the same sequence than the signature, and changing both. Also e-trade docs says that the sequence doesn't matter: https://developer.etrade.com/getting-started/developer-guides (see signature section). But I tried anyway, unfortunately with same result. – bakerwitz Jun 14 '20 at 03:40
  • Have edited the code above, I think you missed out the authorization header :). also the <> has to be seperated by "," – Ralph Jun 14 '20 at 04:49
  • Also make sure you maintain this format after encoding value oauth_nonce="0bba225a40d1bbac2430aa0c6163ce44",next.... – Ralph Jun 14 '20 at 05:12
  • Also the reason I would use the "header" instead of "querystring" is because they have not given an example of how the querystring would look. You would have to do a lot of trial and error to figure that out – Ralph Jun 14 '20 at 05:23
  • I get the signature in request_token request and it works without this header that you say, the signature is only with the other parameters, why to duplicate the info?. Whatever, I tested your code and doesn't work. – bakerwitz Jun 14 '20 at 15:11
  • I will try building the same thing tomorrow, and give you a more definite outcome, OAuth can be a bit complicated, especially when u r dealing with multiple providers, hence Pathfix. If you do manage to crack it by yourself, then do post back. I have done with Twitter which seems to follow the exact same mechanism. – Ralph Jun 14 '20 at 18:19
  • Thank you so much. Also in this link (https://developer.etrade.com/getting-started/developer-guides) is an example with the variables and the signature that you have to make, I'm trying with this now but I don't know why isn't working. Thank you for your help Ralph, I hope that I can solve this soon! If you try and it works, it would be great. Thank you again! – bakerwitz Jun 15 '20 at 01:31
  • Trying to get a developer account, long drawn process :( – Ralph Jun 15 '20 at 02:57
  • I don’t have a SSN and can’t sign up without it. So until ETrade makes it simpler for developers to sign up, I can test my code. Would have loved to though as I have implemented several OAuth 1.0 and 2.0 platforms. Seemed like a good challenge:) – Ralph Jun 16 '20 at 16:21
  • I'm working for a trader, he have an account. Can't do it work yet, there are a lot of parameters that have to stay OK each one to get the signature, and is really a hard work. – bakerwitz Jun 17 '20 at 01:09
  • Is there a way you can share the temporary clientId and clientsecret with me using privnote.com and I will research it for you – Ralph Jun 17 '20 at 03:02
0

Are you using the sandbox or live?

Getting it working in the sandbox first is a good step.

After that, you have to get the key from e-trade.

Also, I believe there are sites that will validate your oauth signature that would give you a more informative error.

BWhite
  • 713
  • 1
  • 7
  • 24
  • I have sandbox credentials until I make it work. I can't get the exacly signature yet, still working without luck. – bakerwitz Jun 17 '20 at 01:11