atomic_lti 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 265fc192cec38bb2a8dbac1f8fc4eaf3388f9240de43f5558ea28f52c3272047
4
- data.tar.gz: cd5cbbb67fc5f2bed2cf959421321aae77a0a8a73504c6ff3a1729d7e78bc8e2
3
+ metadata.gz: 9657315417130b6c1e170190e55603fff1aa97f2285518fa47645b6586b63c64
4
+ data.tar.gz: 5cc81825d70b45eb8d2de538b60ead7ac77742bf57f974762e9ab199d9101004
5
5
  SHA512:
6
- metadata.gz: 8b5c6de47055ebad0a7dfb6a8a8bfeb3f5fdf4598799bd0ed6805ae6c665282bf37130a6a8e37c31cacfdfb77bc10fd8971e85592e7eaca5ae9539015decfd05
7
- data.tar.gz: 775b35f941fd47e529c68906fe47541b3c2736c0c4659179485e5e3da2492edcae02bd537d9bcd4cd621a5f99539f3b466d8f91e0584fa0f14b5fa5c381df9f9
6
+ metadata.gz: 32921bce5874ad6e3066c14f2bc984747efc06fcfb229cb43c4e8fe13026823ff42b1d5582e677d27832b3d88735cdc1e0317e7d962020b6a2b380134bbf6802
7
+ data.tar.gz: e0255a4a3671f6ab6d56041179c28592f088d61f67d1c07632f374aba83657bb7831f94e6ba241fc4467ae0c0122885dd8d22a7578365e49714b432fb7ce5b00
@@ -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
- if validate_target_link_url && target_link_uri != requested_target_link_uri
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
@@ -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: target_link_uri,
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
@@ -1,3 +1,3 @@
1
1
  module AtomicLti
2
- VERSION = "1.7.0".freeze
2
+ VERSION = "1.8.0".freeze
3
3
  end
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.7.0
4
+ version: 1.8.0
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: 2023-12-26 00:00:00.000000000 Z
13
+ date: 2024-01-26 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.19
136
+ rubygems_version: 3.4.10
137
137
  signing_key:
138
138
  specification_version: 4
139
139
  summary: AtomicLti implements the LTI Advantage specification.