Too hard to preserve POST params prior to request phase
Currently params provided to the request phase via the query string in the GET request are stored as session["omniauth.params"]:
and then retrieved and made available in the callback phase as request.env["omniauth.params"]:
This useful feature, whilst mentioned in third-party blogs like here and here, is still lacking official documentation as mentioned in issue #909. That's unfortunate, but there is a further issue caused by a combination of two facts:
- This only works when the request phase is triggered with
GET. - When mitigating CVE-2015-9284 via the advice given in https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284, it is necessary to trigger the request phase via
POST, since allowingGET /auth/:provideris unsafe.
So when attempting to write code which uses omniauth safely, there is no obvious way to preserve custom application-specific parameters which are passed at login time.
By looking at lib/omniauth/strategy.rb I managed to figure out that I could do something like:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET']
provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']
before_request_phase do |env|
# Prior to login, save user parameters to session so that we can
# retrieve them after authentication in order to update the user's
# preferences.
#
# This API is basically undocumented and was figured from reading
# omniauth's strategy.rb.
env["rack.session"]["user_params"] = env["rack.request.form_hash"]["user"]
end
endThen later on after authentication has succeeded and the callback redirects to my users_controller.rb, I can access these custom parameters via session[:user_params]. However it does not seem good that developers should have to assume such knowledge about the internals of the middleware in order to write code which safely preserves parameters across the various HTTP requests in the authentication flow. Therefore I suggest that something similar to omniauth.params is implemented for POST requests - it could be called omniauth.form_params, for instance.
And of course, all of this should be clearly documented, and explained in https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284 too :-)
Source: omniauth/omniauth