atomic_lti 1.7.0 → 1.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/lib/atomic_lti/authorization.rb +1 -0
- data/app/lib/atomic_lti/lti.rb +14 -1
- data/app/lib/atomic_lti/services/names_and_roles.rb +3 -2
- data/app/views/atomic_lti/shared/redirect.html.erb +2 -1
- data/lib/atomic_lti/open_id_middleware.rb +39 -3
- data/lib/atomic_lti/version.rb +1 -1
- data/lib/atomic_lti.rb +6 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5a9ab9e61066b4cf5a463e83db17a6ffbded2fce44251b5506dbfb7a385d1df
|
4
|
+
data.tar.gz: 1922245e4850a6f2baa0cf7cd44a6ae05c3d2937ee957c8ddca46299fa10d302
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e1506ff8b48c8b65164be73cf73408a102af3235f6b1a241068ddca74c57bf8b5c7241e7f5308bf3152a2e6e3bb5288afc7c32aa36d2ef95f896e5ed62bf4ed
|
7
|
+
data.tar.gz: 6a114eefe55c0337690997eaa274685eb3025956a1ac82927c595cd6d716436a1ac2384a2155d568eece1fa002a96e0faa4c3226c9f0c6eb64bcb1328bdeaca7
|
@@ -119,6 +119,7 @@ module AtomicLti
|
|
119
119
|
def self.request_token_uncached(iss:, deployment_id:, scopes:)
|
120
120
|
# Details here:
|
121
121
|
# https://www.imsglobal.org/spec/security/v1p0/#using-json-web-tokens-with-oauth-2-0-client-credentials-grant
|
122
|
+
puts "GETTING TOKEN"
|
122
123
|
body = {
|
123
124
|
grant_type: "client_credentials",
|
124
125
|
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
|
data/app/lib/atomic_lti/lti.rb
CHANGED
@@ -83,7 +83,9 @@ module AtomicLti
|
|
83
83
|
|
84
84
|
# Validate that we are at the target_link_uri
|
85
85
|
target_link_uri = decoded_token[AtomicLti::Definitions::TARGET_LINK_URI_CLAIM]
|
86
|
-
|
86
|
+
|
87
|
+
if validate_target_link_url &&
|
88
|
+
!matching_uri?(target_link_uri, requested_target_link_uri, ignore_host: AtomicLti.update_target_link_host)
|
87
89
|
errors.push(
|
88
90
|
"LTI token target link uri '#{target_link_uri}' doesn't match url '#{requested_target_link_uri}'",
|
89
91
|
)
|
@@ -123,5 +125,16 @@ module AtomicLti
|
|
123
125
|
decoded_token["aud"]
|
124
126
|
end
|
125
127
|
end
|
128
|
+
|
129
|
+
def self.matching_uri?(target, actual, ignore_host:)
|
130
|
+
t = URI.parse(target)
|
131
|
+
a = URI.parse(actual)
|
132
|
+
|
133
|
+
t.scheme == a.scheme &&
|
134
|
+
t.path == a.path &&
|
135
|
+
t.query == a.query &&
|
136
|
+
t.fragment == a.fragment &&
|
137
|
+
(ignore_host || t.host == a.host)
|
138
|
+
end
|
126
139
|
end
|
127
140
|
end
|
@@ -2,8 +2,9 @@ module AtomicLti
|
|
2
2
|
module Services
|
3
3
|
class NamesAndRoles < AtomicLti::Services::Base
|
4
4
|
|
5
|
-
def initialize(id_token_decoded:)
|
6
|
-
|
5
|
+
def initialize(id_token_decoded: nil, iss: nil, deployment_id: nil, context_memberships_url: nil)
|
6
|
+
@context_memberships_url = context_memberships_url || id_token_decoded.dig(AtomicLti::Definitions::NAMES_AND_ROLES_CLAIM, "context_memberships_url")
|
7
|
+
super(id_token_decoded:, iss:, deployment_id:)
|
7
8
|
end
|
8
9
|
|
9
10
|
def scopes
|
@@ -1,6 +1,7 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html lang="en">
|
3
3
|
<head>
|
4
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
4
5
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined" rel="stylesheet">
|
5
6
|
<%= stylesheet_link_tag "atomic_lti/launch" %>
|
6
7
|
</head>
|
@@ -13,7 +14,7 @@
|
|
13
14
|
</p>
|
14
15
|
</div>
|
15
16
|
</noscript>
|
16
|
-
<form action="<%= @launch_url -%>" method="POST">
|
17
|
+
<form action="<%= @launch_url -%>" method="POST" accept-charset="UTF-8">
|
17
18
|
<% @launch_params.each do |name, value| -%>
|
18
19
|
<%= hidden_field_tag(name, value) %>
|
19
20
|
<% end -%>
|
@@ -31,13 +31,17 @@ module AtomicLti
|
|
31
31
|
headers = { "Content-Type" => "text/html" }
|
32
32
|
Rack::Utils.set_cookie_header!(
|
33
33
|
headers, "#{OPEN_ID_COOKIE_PREFIX}storage",
|
34
|
-
{ value: "1", path: "/", max_age: 365.days, http_only: false, secure: true, same_site: "None" }
|
34
|
+
{ value: "1", path: "/", max_age: 365.days, http_only: false, secure: true, same_site: "None", partitioned: true }
|
35
35
|
)
|
36
36
|
Rack::Utils.set_cookie_header!(
|
37
37
|
headers, "#{OPEN_ID_COOKIE_PREFIX}#{state}",
|
38
|
-
{ value: 1, path: "/", max_age: 1.minute, http_only: false, secure: true, same_site: "None" }
|
38
|
+
{ value: 1, path: "/", max_age: 1.minute, http_only: false, secure: true, same_site: "None", partitioned: true }
|
39
39
|
)
|
40
40
|
|
41
|
+
# Ensure our cookies are partitioned. This can be removed once our Rack version
|
42
|
+
# understands the partitioned: argument above.
|
43
|
+
headers[Rack::SET_COOKIE] = partition_cookies(headers[Rack::SET_COOKIE])
|
44
|
+
|
41
45
|
redirect_uri = [request.base_url, AtomicLti.oidc_redirect_path].join
|
42
46
|
response_url = build_oidc_response(request, state, nonce, redirect_uri)
|
43
47
|
|
@@ -111,6 +115,13 @@ module AtomicLti
|
|
111
115
|
target_link_uri = id_token_decoded[AtomicLti::Definitions::TARGET_LINK_URI_CLAIM] ||
|
112
116
|
File.join("#{uri.scheme}://#{uri.host}", AtomicLti.default_deep_link_path)
|
113
117
|
|
118
|
+
target = URI.parse(target_link_uri)
|
119
|
+
|
120
|
+
# Optionally update the target link host to match the redirect host
|
121
|
+
if AtomicLti.update_target_link_host && target.host != uri.host
|
122
|
+
target.host = uri.host
|
123
|
+
end
|
124
|
+
|
114
125
|
# We want to strip out the redirect path params from the request params
|
115
126
|
# so that we can support having the redirect path be the same as the
|
116
127
|
# launch path, only differentiated by a query parameter. This is needed
|
@@ -131,7 +142,7 @@ module AtomicLti
|
|
131
142
|
template: "atomic_lti/shared/redirect",
|
132
143
|
assigns: {
|
133
144
|
launch_params: launch_params,
|
134
|
-
launch_url:
|
145
|
+
launch_url: target,
|
135
146
|
},
|
136
147
|
)
|
137
148
|
|
@@ -363,5 +374,30 @@ module AtomicLti
|
|
363
374
|
platformOIDCUrl: platform.oidc_url,
|
364
375
|
}.compact
|
365
376
|
end
|
377
|
+
|
378
|
+
def partition_cookies(header)
|
379
|
+
# Some versions of rack add multiple cookies as a newline-separated string, and others
|
380
|
+
# as an array of strings.
|
381
|
+
case header
|
382
|
+
when String
|
383
|
+
header.split("\n").map do |cookie|
|
384
|
+
if !cookie.match? /partitioned/i
|
385
|
+
"#{cookie}; partitioned"
|
386
|
+
else
|
387
|
+
cookie
|
388
|
+
end
|
389
|
+
end.join("\n")
|
390
|
+
when Array
|
391
|
+
header.map do |cookie|
|
392
|
+
if !cookie.match? /partitioned/i
|
393
|
+
"#{cookie}; partitioned"
|
394
|
+
else
|
395
|
+
cookie
|
396
|
+
end
|
397
|
+
end
|
398
|
+
else
|
399
|
+
header
|
400
|
+
end
|
401
|
+
end
|
366
402
|
end
|
367
403
|
end
|
data/lib/atomic_lti/version.rb
CHANGED
data/lib/atomic_lti.rb
CHANGED
@@ -32,6 +32,12 @@ module AtomicLti
|
|
32
32
|
# requires this, but Canvas doesn't currently support it.
|
33
33
|
mattr_accessor :set_post_message_origin, default: false
|
34
34
|
|
35
|
+
# Set to true to update the target link uri host to match the oidc redirect host.
|
36
|
+
# Enable this when a single LTI install needs to support launches across multiple hosts.
|
37
|
+
# Setting this avoids state validation problems on launch since state cookies and
|
38
|
+
# postMessage storage won't work across different hosts.
|
39
|
+
mattr_accessor :update_target_link_host, default: false
|
40
|
+
|
35
41
|
mattr_accessor :privacy_policy_url, default: "#"
|
36
42
|
mattr_accessor :privacy_policy_message, default: nil
|
37
43
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: atomic_lti
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Petro
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2024-03-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: pg
|
@@ -133,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
133
|
- !ruby/object:Gem::Version
|
134
134
|
version: '0'
|
135
135
|
requirements: []
|
136
|
-
rubygems_version: 3.4.
|
136
|
+
rubygems_version: 3.4.10
|
137
137
|
signing_key:
|
138
138
|
specification_version: 4
|
139
139
|
summary: AtomicLti implements the LTI Advantage specification.
|