400 bad request from POST request

I’m a relatively new programmer and I’m completely stumped by an oauth issue.

When I pass in grant_type: authorization_code into my post request (after properly receiving a code from my first GET request), I get a 400 bad request. However, when I pass in grant_type: client_credentials, the POST request works, albeit that’s not the access token I need. I’m completely stumped. Here’s my post request:

response = RestClient.post(“https://id.twitch.tv/oauth2/token”, {:client_id => “#{ENV[“id”]}”, :client_secret => “#{ENV[“secret”]}”, :code => session_code, :grant_type => “authorization_code”, :redirect_uri => “http://localhost:3000” })

Am I missing something here?

Refer to the HTTP Body of the response.

The code on it’s own is only part of the message.

The body will describe the problem with your request.

Apologies for being a total noob, but I’m not even getting a response. The request itself is not being recognized and therefore the error is thrown before I have access to the response variable

If you got a HTTP 400 bad request, then it should of returned a body.

What does you code look like that is making this request?

response = RestClient.post(“https://id.twitch.tv/oauth2/token”, {:client_id => “#{ENV[“id”]}”, :client_secret => “#{ENV[“secret”]}”, :code => session_code, :grant_type => “authorization_code”, :redirect_uri => “http://localhost:3000” })

and interestingly enough, if I swap :grant_type to “client_credentials”, this POST request works. I’m stumped.

You’ve posted screenshots, not code, and the bit of code I’m interested in is off to the right of the screenshot.

client_credentials is a different kind of token, so the POST request behaves different

Without the body of the response, I have no idea what the actual bug/problem is, I would guess the code is invalid, or was attempted to be used twice. Which the body response would tell you which.

Since you seem to be fetching code from session (sessioncode in “English” sounds wrong hence asking to see the code) when code should be fetched from query string parameters, so this sounds like a double code usage, and the second one fails as it’s already been exchanged.

User oAuth works as follows

  1. Redirect the user to twitch
  2. User comes back with a ?code in the URL
  3. You exchange the ?code for a token.

I’m not sure what you are doing here, since you posted screenshots of responses rather than the code.

Apologies.

  def create
    session_code = params[:code]
    puts session_code
    response = RestClient.post("https://id.twitch.tv/oauth2/token", {:client_id => "#{ENV["id"]}", 
          :client_secret => "#{ENV["secret"]}", 
          :code => session_code, 
          :grant_type => "authorization_code", 
          :redirect_uri => "http://localhost:3000" })
    access_token = JSON.parse(response)["access_token"]
    session[:token] = access_token
    client = Twitch::Client.new(:client_id => "#{ENV["id"]}",
          :client_secret => "#{ENV["secret"]}", 
          token_type: :user)
    puts client.access_token
    user = client.get_users(access_token: access_token).data.first
    @profile_data = { :image => user.profile_image_url, :name => user.display_name, :twitch_id => user.id }
    if User.find_by(@profile_data) == nil
      @profile = User.new(@profile_data)
      @profile.save
    else
      @profile = User.find_by(@profile_data)
    end
@profile_data = session[:profile_data] 

end

and my initial link is
const clientId = process.env.REACT_APP_id;
const redirect = “http://localhost:3001/auth/twitch/callback
const url = ‘https://id.twitch.tv/oauth2/authorize?client_id=’ + clientId + ‘&redirect_uri=’ + redirect + ‘&response_type=code&scope=user:read:email’;

Well theres you problem

On your initial link your redirect is http://localhost:3001/auth/twitch/callback and on your code exchange your redirect is http://localhost:3000

So you would of got a body message with your HTTP 4xx code of invalid redirect URI (or words to that effect)

RedirectURI was ignored/not checked when getting a client_credentials token which is why it worked

You’re an absolute genius. Please get a donate link on your personal page, you’d be a goddamn millionaire by now haha

mumbles that there is some on his github

I fixed the redirect_uris to be matching, and now i’m experiencing a different issue. I rewrote my code so that I could access a reponse.body and follow the errors. Now i’m having the error

{“status”:400,“message”:“Invalid authorization code”}.

From what I’ve read on your posts in the past, this is usually due to making 2 post requests, but idk what i’d be doing that would cause that.

here’s what i’m working with now-
def create

session_code = params[:code]

link = "https://id.twitch.tv/oauth2/token"

headers = {

  "client_id" => "#{ENV["id"]}",

  "client_secret" => "#{ENV["secret"]}",

  "code" => "#{session_code}",

  "grant_type" => "authorization_code",

  "redirect_uri" => "http://localhost:3001/auth/twitch/callback"

}

url = URI(link)

http = Net::HTTP.new(url.host, url.port)

http.use_ssl = true

response = http.post(url.path, URI.encode_www_form(headers))

puts JSON.parse(response.body)
#returns {"status"=>400, "message"=>"Invalid authorization code"}

access_token = JSON.parse(response)["access_token"]

session[:token] = access_token

client = Twitch::Client.new(:client_id => "#{ENV["id"]}",:client_secret => "#{ENV["secret"]}", token_type: :user)

puts client.access_token

user = client.get_users(access_token: access_token).data.first

@profile_data = { :image => user.profile_image_url, :name => user.display_name, :twitch_id => user.id }

if User.find_by(@profile_data) == nil

  @profile = User.new(@profile_data)

  @profile.save

else

  @profile = User.find_by(@profile_data)

end

@profile_data = session[:profile_data] 

end

it’s also worth noting that if i print

URI.encode_www_form(headers)

to the console, it returns

client_id=<redacted>&client_secret=<redacted>&code=fr03l<redacted>83wy&grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fauth%2Ftwitch%2Fcallback

which seems like it should be correct to me

also, the OG link is

const redirect = “http://localhost:3001/auth/twitch/callback

const url = 'https://id.twitch.tv/oauth2/authorize? 
response_type=code&client_id=' + clientId + '&redirect_uri=' + redirect + '&scope=user:read:email';

Now I’m noticing that if I change the redirect in the OG link to just localhost and copy the code from the web browser, I can paste it into postman and get a valid response… this leads me to believe my post request is in fact sending through the wrong code, as it’s generating 2. i just dont know why.

i’m using http outbound logging per your previous suggestions and think i’ll have it sorted in no time. thanks barry for all your help

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.