Twitter api, failed to get access_token by 2/oauth/token with PKCE

Viewed 137

I want to make desktop application using twitter api with C#.

I have successed to get authorize code by i/oauth2/authorize api following how to connect with PKCE. https://developer.twitter.com/en/docs/authentication/oauth-2-0/user-access-token

But step3, 2/oauth2/token always returns error. Error is “invalid_request” and “Value passed for the token was invalid.”

Somebody know mistake in my code?

using System.Diagnostics;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;

public async Task Authorize()
{
    var state = GenerateRandomString(inLength: 200);
    var codeVerifier = GenerateRandomString(inLength: 100);
    var challenge = codeVerifier;
    //var challenge = GenerateCodeS256Challenge(codeVerifier);
    var challengeMethod = "plain";
    var scope = "tweet.read tweet.write users.read offline.access".Replace(" ", "%20");

    var url = "https://twitter.com/i/oauth2/authorize";
    url = $"{url}?response_type=code&client_id={ClientID}&redirect_uri={RedirectUrl}&scope={scope}&state={state}&code_challenge={challenge}&code_challenge_method={challengeMethod}";

    var http = new HttpListener();
    http.Prefixes.Add(RedirectUrl);
    http.Start();

    Process.Start(new ProcessStartInfo
    {
        FileName = url,
        UseShellExecute = true,
    });

    var context = await http.GetContextAsync();
    var httpResponse = context.Response;
    var buffer = Encoding.UTF8.GetBytes("<html><body>Please return to the app.</body></html>");
    httpResponse.ContentLength64 = buffer.Length;
    var responseOutput = httpResponse.OutputStream;
    await responseOutput.WriteAsync(buffer, 0, buffer.Length);
    responseOutput.Close();
    http.Stop();

    if (context.Request.QueryString.Get("state") == state)
    {
        var code = context.Request.QueryString.Get("code");

        var request = new HttpRequestMessage(HttpMethod.Post, "https://api.twitter.com/2/oauth2/token");
        //request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(
        //        "Basic",
        //        Convert.ToBase64String(Encoding.ASCII.GetBytes($"{ClientID}:{ClientSecret}"))
        //    );
        request.Content = new FormUrlEncodedContent(new Dictionary<string, string>
        {
            { "code", code },
            { "grant_type", "authorization_code" },
            { "client_id", ClientID },
            { "redirect_url", RedirectUrl},
            { "code_verifier", codeVerifier },
        });

        // status code: 400, Bad Request
        var response = await _httpClient.SendAsync(request);
        // {
        //      "error":"invalid_request",
        //      "error_description":"Value passed for the token was invalid."
        // }
        var json = await response.Content.ReadAsStringAsync();
    }
}
1 Answers

Tried curl command on ms-dos terminal, successed to get token response.

For now, I make bat file calling curl command, and run the file and read output.

oauth2_token.bat:

@set CODE=%1
@set CLIENT_ID=%2
@set REDIRECT_URL=%3
@set CODE_VERIFIER=%4

@curl --location --request POST https://api.twitter.com/2/oauth2/token --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode "code=%CODE%" --data-urlencode "grant_type=authorization_code" --data-urlencode "client_id=%CLIENT_ID%" --data-urlencode "redirect_uri=%REDIRECT_URL%" --data-urlencode "code_verifier=%CODE_VERIFIER%"

C# code:

var psInfo = new ProcessStartInfo();
psInfo.FileName = "oauth2_token.bat";
psInfo.Arguments = $"{code} {inClientID} {inRedirectUrl} {codeVerifier}";
psInfo.CreateNoWindow = true;
psInfo.UseShellExecute = false;
psInfo.RedirectStandardOutput = true;
            
var process = Process.Start(psInfo)!;

var json = "";
while ((json = process.StandardOutput.ReadLine()) != null)
{
    break;
}
var deserialized = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
var bearerToken = deserialized["access_token"];

I don't know yet why my first code failed.

Related