add original_url to inst-fs jwt tokens

refs SAS-1610

test plan:

inst-fs jwt tokens should have a "original_url" claim

flag = none

Change-Id: I477d583ac7f9fd71e5e3233e5adc982d66d3c195
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/254239
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Levente Szabo <levente.szabo@instructure.com>
Reviewed-by: Jonathan Featherstone <jfeatherstone@instructure.com>
QA-Review: Nathan Mills <nathanm@instructure.com>
Product-Review: Nathan Mills <nathanm@instructure.com>
This commit is contained in:
Nathan Mills 2020-12-03 17:33:57 -07:00
parent b74093af55
commit 4540d77073
4 changed files with 42 additions and 7 deletions

View File

@ -1248,11 +1248,11 @@ module ApplicationHelper
end
def authenticated_download_url(attachment)
file_authenticator.download_url(attachment)
file_authenticator.download_url(attachment, options: {original_url: request.original_url})
end
def authenticated_inline_url(attachment)
file_authenticator.inline_url(attachment)
file_authenticator.inline_url(attachment, options: {original_url: request.original_url})
end
def authenticated_thumbnail_url(attachment, options={})

View File

@ -60,11 +60,12 @@ class FileAuthenticator
})
end
def download_url(attachment)
def download_url(attachment, options: {})
return nil unless attachment
migrate_legacy_attachment_to_instfs(attachment)
if attachment.instfs_hosted?
options = instfs_options(attachment, download: true)
options.merge!(instfs_options(attachment, download: true))
InstFS.authenticated_url(attachment, options)
else
# s3 doesn't distinguish authenticated and public urls
@ -72,11 +73,12 @@ class FileAuthenticator
end
end
def inline_url(attachment)
def inline_url(attachment, options: {})
return nil unless attachment
migrate_legacy_attachment_to_instfs(attachment)
if attachment.instfs_hosted?
options = instfs_options(attachment, download: false)
options.merge!(instfs_options(attachment, download: false))
InstFS.authenticated_url(attachment, options)
else
# s3 doesn't distinguish authenticated and public urls

View File

@ -400,7 +400,9 @@ module InstFS
resource: resource,
host: options[:oauth_host]
}
claims[:jti] = options[:jti] if options.has_key? :jti
original_url = parse_original_url(options[:original_url])
claims[:original_url] = original_url if original_url.present?
claims[:jti] = options[:jti] if options.key? :jti
if options[:acting_as] && options[:acting_as] != options[:user]
claims[:acting_as_user_id] = options[:acting_as].global_id.to_s
end
@ -477,8 +479,25 @@ module InstFS
}, expires_in)
end
def parse_original_url(url)
if url
uri = Addressable::URI.parse(url)
query = (uri.query_values || {}).with_indifferent_access
# We only want to redirect once, if the redirect param is present then we already redirected.
# In which case we don't send the original_url param again
if !Canvas::Plugin.value_to_boolean(query[:redirect])
query[:redirect] = true
uri.query_values = query
return uri.to_s
else
return nil
end
end
end
def amend_claims_for_access_token(claims, access_token, root_account)
return unless access_token
if whitelisted_access_token?(access_token)
# temporary workaround for legacy API consumers
claims[:legacy_api_developer_key_id] = access_token.global_developer_key_id.to_s

View File

@ -202,6 +202,20 @@ describe InstFS do
expect(Canvas::Security.decode_jwt(token, [ secret ])).to have_key(:jti)
end
it "includes the original_url claim with the redirect param" do
original_url = "https://example.test/preview"
url = InstFS.authenticated_url(@attachment, original_url: original_url)
token = url.split(/token=/).last
expect(Canvas::Security.decode_jwt(token, [ secret ])[:original_url]).to eq(original_url + "?redirect=true")
end
it "doesn't include the original_url claim if already redirected" do
original_url = "https://example.test/preview?redirect=true"
url = InstFS.authenticated_url(@attachment, original_url: original_url)
token = url.split(/token=/).last
expect(Canvas::Security.decode_jwt(token, [ secret ])).not_to have_key(:original_url)
end
describe "legacy api claims" do
let(:root_account) { Account.default }
let(:access_token) { instance_double("AccessToken", global_developer_key_id: 106) }