v2.0.0
Version 2.0 of OmniAuth includes some changes that may be breaking depending on how you use OmniAuth in your app.
Many thanks to the folks who contributed in code and discussion for these changes.
OmniAuth now defaults to only POST as the allowed request_phase method.
Hopefully, you were already doing this as a result of the warnings due to CVE-2015-9284.
For detailed context, see:
#960
#809
Resolving CVE-2015-9284
This change also includes an additional configurable phase: request_validation_phase
.
Rack/Sinatra
By default, this uses rack-protection's AuthenticityToken class to validate authenticity tokens. If you are using a rack based framework like sinatra, you can find an example of how to add authenticity tokens to your view here.
Rails
Because Rails handles its CSRF protection in its RequestForgeryProtection class, and stores tokens in a non-vanilla-rack friendly way, you must pass a rails-friendly validator in instead, similar to what omniauth-rails_csrf_protection does.
Update: omniauth-rails_csrf_protection has released v1.0.0, which means if you're using this library already, you should be able to upgrade omniauth to the 2.0 series as long as omniauth-rails_csrf_protection is also upgraded '~> 1.0'
An example of creating your own non-dependency implementation is below, though I would recommend using the gem.
# Derived from https://github.com/cookpad/omniauth-rails_csrf_protection/blob/master/lib/omniauth/rails_csrf_protection/token_verifier.rb
# This specific implementation has been pared down and should not be taken as the most correct way to do this.
class TokenVerifier
include ActiveSupport::Configurable
include ActionController::RequestForgeryProtection
def call(env)
@request = ActionDispatch::Request.new(env.dup)
raise OmniAuth::AuthenticityError unless verified_request?
end
private
attr_reader :request
delegate :params, :session, to: :request
end
# in an initializer
OmniAuth.config.request_validation_phase = TokenVerifier.new
If you're using Rails' form helpers, they automatically include an authenticity token.
If you are using hyperlinks or buttons styled to redirect to your login route, you should update these to be a submit input or a submit type button wrapped in a form.
- <a href='/auth/developer'>Login with Developer</a>
+ <%= form_tag('/auth/developer', method: 'post') do %>
+ <button type='submit'>Login with Developer</button>
+ <% end %>
GET
Because using GET for login poses concerns (see OWASP Cheatsheet), after upgrading OmniAuth will log a :warn
level log with every GET request to a login path when your OmniAuth.config.allowed_request_methods
include :get
.
If you have a workflow that absolutely requires you to use GET for the request_phase, you can disable this warning using
OmniAuth.config.silence_get_warning = true
It is very important that you do not do this just to circumvent having to change your inputs or login flow, as using GET for most auth workflows is not what you want.
Unhandled Exceptions
OmniAuth now catches exceptions raised during the options_call, request_call, callback_call, and other_phase, and passes them to the OmniAuth.config.on_failure
handler. For most apps, this means they are passed to the default FailureEndpoint class that OmniAuth provides, and redirected to /auth/failure
. If your app is wrapping OmniAuth in another middleware such as this example in Discourse, then you may need to instead write your own failure handler.
Provider Namespacing
OmniAuth will no longer find constants from an ancestor class when looking for the strategy class. What this means is that
OmniAuth.builder.new(@app) do
provider :my_provider
end
Will no longer find ::MyProvider
as a strategy, and instead will only look under the OmniAuth::Strategies
namespace for the MyProvider
class.
Failure Route
The failure route will now respect a strategy's path_prefix option, meaning if your strategy uses /external
instead of /auth
as its path prefix, the failure route for that strategy will be /external/failure
.
Thread Safety
The OmniAuth middleware should now be thread-safe, as we run tests with rack-freeze to check for middleware mutability. This does not guarantee that the downstream strategy is thread-safe however. If you have concerns, ask your strategy maintainers.
Frozen Strings
OmniAuth will no longer throw errors if trying to run it in an app with RUBYOPT="--enable-frozen-string-literal"
.
Relative Root Apps
OmniAuth now respects the 'SCRIPT_NAME' env value, so if your app lives at myapp.com/super
, your request path will be /super/auth/provider
, your callback path /super/auth/provider/callback
and your failure path /super/auth/failure
.