Search code examples
ruby-on-railsdeviseomniauth-google-oauth2

Is The Rails Gem 'omniauth-google-oauth2' Secure / How Does request.env work?


I've implemented the 'omniauth-google-oauth2' gem in my rails/devise app using the example pattern given on https://github.com/zquestz/omniauth-google-oauth2. However, I'm concerned that this pattern is not secure.

I have attempted to review the source code on git hub, and the official google documentation at https://developers.google.com/identity/sign-in/web/devconsole-project, however I have not been able to convince myself this pattern is secure.

From the google docs, the flow is supposed to look like this:

Google OAuth Flow

My security concern lies with not having a great understanding of how request.env works.

Question 1: Can a user set request.env values (for example, with something like cURL requests)?

Question 2: If so, what is stopping a malicious user from hitting an app's omniauth callback endpoint and setting the values of request.env so they can impersonate another user? For example, in the sample shown on github the callback endpoint in the controller is:

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

def google_oauth2

 # You need to implement the method below in your model (e.g. app/models/user.rb)

 @user = User.from_omniauth(request.env["omniauth.auth"])

 if @user.persisted?

   flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google"

   sign_in_and_redirect @user, :event => :authentication

 else

   session["devise.google_data"] = request.env["omniauth.auth"].except(:extra) #Removing extra as it can overflow some session stores

   redirect_to new_user_registration_url, alert: @user.errors.full_messages.join("\n")

 end

end

end

Question 3: My rails app server (I'm using puma) doesn't seem to be logging the request from step 5 in the diagram (exchanging code for token). I can't see that from the user's perspective in Chrome because the user isn't involved in that communication. How can I see/log/verify that call is taking place?


Solution

  • Question 1: Can a user set request.env values (for example, with something like cURL requests)?

    Yes. request.env contains a bunch of things like incoming headers and params. But the user cannot set request.env['omniauth.auth'] as its populated with values fetched by a server side request to the provider.

    Using env and request.env to pass values is a pretty standard way to pass data from Rack middleware down the pipeline. Its not a gaping security hole since user input is limited to to params and headers.

    Question 2: If so, what is stopping a malicious user from hitting an app's omniauth callback endpoint and setting the values of request.env so they can impersonate another user?

    The only input accepted from the user is the access token, id token and one time code. Aquiring these would require a brute force attack (on the provider) or a man in the middle attack.

    Question 3: My rails app server (I'm using puma) doesn't seem to be logging the request from step 5 in the diagram (exchanging code for token). I can't see that from the user's perspective in Chrome because the user isn't involved in that communication. How can I see/log/verify that call is taking place?

    There is nothing in the logs since the calls are being made from your rails server to the provider. You can use something like httplog to debug but really you should have tests which cover these aspects of the Omniauth strategy.