allow 5 minutes of future clock skew when verifying JWTs
fixes CORE-1439 Change-Id: Ia3ed12dd79cee475bedd0879323eacf3a0325476 Reviewed-on: https://gerrit.instructure.com/155617 Tested-by: Jenkins Reviewed-by: Brent Burgoyne <bburgoyne@instructure.com> Product-Review: Cody Cutrer <cody@instructure.com> QA-Review: Cody Cutrer <cody@instructure.com>
This commit is contained in:
parent
66f225be3f
commit
4014a971e0
|
@ -329,27 +329,29 @@ module Canvas::Security
|
||||||
class << self
|
class << self
|
||||||
private
|
private
|
||||||
def verify_jwt(body, ignore_expiration: false)
|
def verify_jwt(body, ignore_expiration: false)
|
||||||
|
verification_time = Time.now.utc
|
||||||
|
if body[:iat].present?
|
||||||
|
iat = timestamp_as_integer(body[:iat])
|
||||||
|
if iat > verification_time.to_i && iat < verification_time.to_i + 300
|
||||||
|
verification_time = iat
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if body[:exp].present? && !ignore_expiration
|
if body[:exp].present? && !ignore_expiration
|
||||||
if timestamp_is_expired?(body[:exp])
|
if timestamp_as_integer(body[:exp]) < verification_time.to_i
|
||||||
raise Canvas::Security::TokenExpired
|
raise Canvas::Security::TokenExpired
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if body[:nbf].present?
|
if body[:nbf].present?
|
||||||
if timestamp_is_future?(body[:nbf])
|
if timestamp_as_integer(body[:nbf]) > verification_time.to_i
|
||||||
raise Canvas::Security::InvalidToken
|
raise Canvas::Security::InvalidToken
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def timestamp_is_expired?(exp_val)
|
def timestamp_as_integer(timestamp)
|
||||||
now = Time.zone.now
|
timestamp.is_a?(Time) ? timestamp.to_i : timestamp
|
||||||
(exp_val.is_a?(Time) && exp_val <= now) || exp_val <= now.to_i
|
|
||||||
end
|
|
||||||
|
|
||||||
def timestamp_is_future?(nbf_val)
|
|
||||||
now = Time.zone.now
|
|
||||||
(nbf_val.is_a?(Time) && nbf_val > now) || nbf_val > now.to_i
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def services_encryption_secret
|
def services_encryption_secret
|
||||||
|
|
|
@ -136,6 +136,12 @@ describe Canvas::Security do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "allows 5 minutes of future clock skew" do
|
||||||
|
back_to_the_future_jwt = test_jwt(exp: 1.hour.from_now, nbf: 1.minutes.from_now, iat: 1.minutes.from_now)
|
||||||
|
body = Canvas::Security.decode_jwt(back_to_the_future_jwt, [ key ])
|
||||||
|
expect(body[:a]).to eq 1
|
||||||
|
end
|
||||||
|
|
||||||
it "produces an InvalidToken error if string isn't a jwt (even if it looks like one)" do
|
it "produces an InvalidToken error if string isn't a jwt (even if it looks like one)" do
|
||||||
# this is an example token which base64_decodes to a thing that looks like a jwt because of the periods
|
# this is an example token which base64_decodes to a thing that looks like a jwt because of the periods
|
||||||
not_a_jwt = Canvas::Security.base64_decode("1050~LvwezC5Dd3ZK9CR1lusJTRv24dN0263txia3KF3mU6pDjOv5PaoX8Jv4ikdcvoiy")
|
not_a_jwt = Canvas::Security.base64_decode("1050~LvwezC5Dd3ZK9CR1lusJTRv24dN0263txia3KF3mU6pDjOv5PaoX8Jv4ikdcvoiy")
|
||||||
|
|
Loading…
Reference in New Issue