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:
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?
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.