Skip to content

Commit 561ddce

Browse files
authored
Merge pull request #144 from toupeira/verify-state-before-using-provider-errors
Verify state before using errors received from provider
2 parents 8438b89 + 98553d7 commit 561ddce

File tree

2 files changed

+40
-7
lines changed

2 files changed

+40
-7
lines changed

lib/omniauth/strategies/oauth2.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@ def token_params
8383

8484
def callback_phase # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
8585
error = request.params["error_reason"] || request.params["error"]
86-
if error
87-
fail!(error, CallbackError.new(request.params["error"], request.params["error_description"] || request.params["error_reason"], request.params["error_uri"]))
88-
elsif !options.provider_ignores_state && (request.params["state"].to_s.empty? || request.params["state"] != session.delete("omniauth.state"))
86+
if !options.provider_ignores_state && (request.params["state"].to_s.empty? || request.params["state"] != session.delete("omniauth.state"))
8987
fail!(:csrf_detected, CallbackError.new(:csrf_detected, "CSRF detected"))
88+
elsif error
89+
fail!(error, CallbackError.new(request.params["error"], request.params["error_description"] || request.params["error_reason"], request.params["error_uri"]))
9090
else
9191
self.access_token = build_access_token
9292
self.access_token = access_token.refresh! if access_token.expired?

spec/omniauth/strategies/oauth2_spec.rb

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,47 @@ def app
9797
end
9898

9999
describe "#callback_phase" do
100-
subject { fresh_strategy }
101-
it "calls fail with the client error received" do
102-
instance = subject.new("abc", "def")
100+
subject(:instance) { fresh_strategy.new("abc", "def") }
101+
102+
let(:params) { {"error_reason" => "user_denied", "error" => "access_denied", "state" => state} }
103+
let(:state) { "secret" }
104+
105+
before do
103106
allow(instance).to receive(:request) do
104-
double("Request", :params => {"error_reason" => "user_denied", "error" => "access_denied"})
107+
double("Request", :params => params)
108+
end
109+
110+
allow(instance).to receive(:session) do
111+
double("Session", :delete => state)
105112
end
113+
end
114+
115+
it "calls fail with the error received" do
116+
expect(instance).to receive(:fail!).with("user_denied", anything)
117+
118+
instance.callback_phase
119+
end
120+
121+
it "calls fail with the error received if state is missing and CSRF verification is disabled" do
122+
params["state"] = nil
123+
instance.options.provider_ignores_state = true
106124

107125
expect(instance).to receive(:fail!).with("user_denied", anything)
126+
127+
instance.callback_phase
128+
end
129+
130+
it "calls fail with a CSRF error if the state is missing" do
131+
params["state"] = nil
132+
133+
expect(instance).to receive(:fail!).with(:csrf_detected, anything)
134+
instance.callback_phase
135+
end
136+
137+
it "calls fail with a CSRF error if the state is invalid" do
138+
params["state"] = "invalid"
139+
140+
expect(instance).to receive(:fail!).with(:csrf_detected, anything)
108141
instance.callback_phase
109142
end
110143
end

0 commit comments

Comments
 (0)