我使用doorkeeper
引擎和devise
构建OAuth2提供程序。在我的客户端应用中,我使用了自定义omniauth-oauth2 -v 1.3.1
策略。一切都运作良好,但在我登录后如果我点击浏览器上的后退按钮,我得到
我挖掘了omniauth-oath2代码,看起来我认为有两种方法与这个问题密切相关,一种是从url params创建session["omniauth.state"]
:
def authorize_params
options.authorize_params[:state] = SecureRandom.hex(24)
params = options.authorize_params.merge(options_for("authorize"))
if OmniAuth.config.test_mode
@env ||= {}
@env["rack.session"] ||= {}
end
session["omniauth.state"] = params[:state]
params
end
和一个检查这个并在回调过程中从会话中删除它的人:
def callback_phase # rubocop:disable AbcSize, CyclomaticComplexity, MethodLength, PerceivedComplexity
error = request.params["error_reason"] || request.params["error"]
if error
fail!(error, CallbackError.new(request.params["error"], request.params["error_description"] || request.params["error_reason"], request.params["error_uri"]))
elsif !options.provider_ignores_state && (request.params["state"].to_s.empty? || request.params["state"] != session.delete("omniauth.state"))
fail!(:csrf_detected, CallbackError.new(:csrf_detected, "CSRF detected"))
else
self.access_token = build_access_token
self.access_token = access_token.refresh! if access_token.expired?
super
end
rescue ::OAuth2::Error, CallbackError => e
fail!(:invalid_credentials, e)
rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
fail!(:timeout, e)
rescue ::SocketError => e
fail!(:failed_to_connect, e)
end
似乎某种方式从浏览器回来时没有调用第一种方法。是否有人遇到同样的问题,如果没有将:provider_ignores_state
设置为true
,是否有解决此问题的方法。我是否需要在提供商处设置一些内容,我真的无法获得它,而且我似乎无法在网络上的任何地方发现此问题而且我非常怀疑它是我第一个认识到它,但我可能是第一个在不影响安全性的情况下找不到合理解决方案的人。