Tobias Geisler
Tobias Geisler

Reputation: 719

JSON parameters not available in request hash (Rails, omniauth-google-oauth2 gem)

Overview

I want to implement the Google OAuth2 server side (hybrid) with the Omniauth Google OAuth2 Gem (0.2.6). However, the code parameter I send to my app does not get added to the request.params hash. Thus, OmniAuth throws an error, as it can't find the code.

Details

After retrieving the auth code from Google I send it to the server (by AJAX):

// Send the code to the server
    $.ajax({
      type: 'POST',
      url: '/auth/google_oauth2/callback',
      contentType: 'application/json',
      success: function(result) {
        // Handle or verify the server response.
      },
      processData: false,
      data: JSON.stringify(password_result)
    });

This throws the error:

"error" : "invalid_request",
"error_description" : "Missing required parameter: code"

After going through the stack, I figured out the following:

  1. As long as I have 'application/json' set as content Type, Rack parses the params correctly and the env object contains the parsed parameters:

    "action_dispatch.request.request_parameters"=>{"code"=>"<sent_in_code>"}
    
  2. However, the request.params hash remains empty. Since OmniAuth checks for request.params['code'], this is the source of the error.

  3. request.POST is empty, which from looking at the source code of Rack is the underlying cause for the empty request.params hash.

  4. When sending the code in standard format as data:"code="+authResult['code'], the parameter is available in the request.params hash. (I get a strange undefined route error then, but this is a different issue.)

Questions

Now, even though I can avoid the issue by not using JSON, I'm still very intereted in the answers to the following questions:

  1. Why is the code parameter not available in request.POST/request.params, even though it gets parsed correctly?
  2. Is there a way to fix this, so I can still send the auth code in JSON to my app?

I've spent two afternoons trying to get the answers myself, but haven't really gotten to a good conclusion so far.

Upvotes: 2

Views: 570

Answers (1)

joni
joni

Reputation: 5462

omniauth-google-oauth2 tries to get the auth code from the Rack::Request.params hash. However, Rack apparently does not have JSON parsing built-in. Params calls POST which then calls form_data? which only looks for application/x-www-form-urlencoded or multipart/form-data. It then also tries parseable_data?, which does not parse JSON either. Seems like Rack does not support JSON out of the box, also look at this answer.

The "action_dispatch.request.request_parameters"=>{"code"=>"<sent_in_code>"} hash works because this is done by rails ActionDispatch::Request, which subclasses Rack::Request. However because The omniauth gem is included in your app as a Rack middleware, it does not know of the ActionDispatch request object.

The question remains why this example uses JSON.

Possible solutions:

  • money-Patch JSON Support into Rack - not recommended
  • just use application/x-www-form-urlencoded - recommended

Upvotes: 2

Related Questions