ims-lti 2.1.2 → 2.3.3

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
- SHA1:
3
- metadata.gz: 2bdd06e5c60fc13eb134e231cf0e0ee7738eb9a8
4
- data.tar.gz: 56c1d472a02e4d5359b9e03977a0d9f604a3a09f
2
+ SHA256:
3
+ metadata.gz: 2471bb32ba4e415a4134bca8b7fd89e395e6d2fcea9cf694ae3a094599bed683
4
+ data.tar.gz: 9978a2ca0c9f89cd4fdd03217cb0f13bde37098f45c319e2d813c3fad6102b31
5
5
  SHA512:
6
- metadata.gz: 264a0293b2ccad3c5047d081ba08d6f2967a3e26c621855a1add4cafd113f3627d95cb75d95b491cc47293a35ded64ef9d82aa6ac61e393dde2e69189398fb91
7
- data.tar.gz: 47cfe33a68b1a8ee738ab6d80bc8e8e8d4b75d8fc47c25da6e42fef69b9ca55f04a5b343b82687d161434943670f6149f75da13ec6fb5be30c2485f965bc6819
6
+ metadata.gz: b96119ce642dde977d998fb405576b21ca755311b841b49d9a985f556bf0fdfbbab60798027060f641463edd1329505a4a53ad916f75a9ce344d9c4723d1ab20
7
+ data.tar.gz: 5e4fd658b0658adcdbcca33feacf429f04e8a0f354eb6db1d031cfa4b0655f9a8478131919f215d833d872478462677bfcd04ed6ee298a00ed85bcb921f3313c
data/README.md CHANGED
@@ -37,7 +37,7 @@ return false unless authenticator.valid_signature?
37
37
  # check if `params['oauth_nonce']` has already been used
38
38
 
39
39
  #check if the message is too old
40
- return false if DateTime.strptime(request.request_parameters['oauth_timestamp'],'%s') > 5.minutes.ago
40
+ return false if DateTime.strptime(request.request_parameters['oauth_timestamp'],'%s') < 5.minutes.ago
41
41
 
42
42
  ```
43
43
 
@@ -0,0 +1,11 @@
1
+ module IMS::LTI::Errors
2
+ class AuthenticationFailedError < StandardError
3
+
4
+ attr_reader :response
5
+
6
+ def initialize(response: nil)
7
+ @response = response
8
+ end
9
+
10
+ end
11
+ end
@@ -3,5 +3,6 @@ module IMS::LTI
3
3
  require_relative 'errors/invalid_lti_config_error'
4
4
  require_relative 'errors/tool_proxy_registration_error'
5
5
  require_relative 'errors/invalid_tool_consumer_profile'
6
+ require_relative 'errors/authentication_failed_error'
6
7
  end
7
8
  end
@@ -1,3 +1,5 @@
1
+ require 'uri'
2
+
1
3
  module IMS::LTI::Models
2
4
  class LTIModel
3
5
  LTI_VERSION_2P0 = 'LTI-2p0'.freeze
@@ -90,8 +92,13 @@ module IMS::LTI::Models
90
92
  end
91
93
 
92
94
  def from_json(json)
93
- # JSON.parse(json.to_json) is a quick and dirty way to clone the json object passed in
94
- data = json.is_a?(String) ? JSON.parse(json) : JSON.parse(json.to_json)
95
+ json = json.to_json unless json.is_a?(String)
96
+ begin
97
+ data = JSON.parse(json)
98
+ rescue
99
+ data = JSON.parse(URI::DEFAULT_PARSER.unescape(json))
100
+ end
101
+
95
102
  if data.is_a? Array
96
103
  data.map { |hash| self.class.from_json(hash.to_json) }
97
104
  else
@@ -1,6 +1,6 @@
1
1
  module IMS::LTI::Models::MembershipService
2
2
  class LISPerson < Person
3
- attr_reader :email, :result_sourced_id, :sourced_id, :user_id
3
+ attr_reader :email, :result_sourced_id, :sourced_id, :user_id, :sis_id
4
4
 
5
5
  def initialize(opts={})
6
6
  super(opts)
@@ -8,6 +8,7 @@ module IMS::LTI::Models::MembershipService
8
8
  @result_sourced_id = opts[:result_sourced_id]
9
9
  @sourced_id = opts[:sourced_id]
10
10
  @user_id = opts[:user_id]
11
+ @sis_id = opts[:sis_id]
11
12
  end
12
13
  end
13
14
  end
@@ -3,7 +3,8 @@ module IMS::LTI::Models::Messages
3
3
 
4
4
  add_required_params :resource_link_id
5
5
  add_recommended_params :context_id, :launch_presentation_return_url, :tool_consumer_instance_guid
6
- add_optional_params :context_type, :role_scope_mentor, :user_image
6
+ add_optional_params :context_type, :role_scope_mentor, :user_image,
7
+ :lis_outcome_service_url, :lis_person_sourced_id, :lis_result_sourcedid
7
8
  add_deprecated_params :context_title, :context_label, :resource_link_title, :resource_link_description,
8
9
  :lis_person_name_given, :lis_person_name_family, :lis_person_name_full,
9
10
  :lis_person_contact_email_primary, :user_image, :lis_person_sourcedid,
@@ -40,13 +40,26 @@ module IMS::LTI::Models::Messages
40
40
  def inherited(klass)
41
41
  @descendants ||= Set.new
42
42
  @descendants << klass
43
- superclass.inherited(klass) unless(self == Message)
43
+ superclass.inherited(klass) unless (self == Message)
44
44
  end
45
45
 
46
46
  def descendants
47
47
  @descendants || Set.new
48
48
  end
49
49
 
50
+ # For signature generation -- see usage in signed_post_params
51
+ def convert_param_values_to_crlf_endings(hash)
52
+ hash.transform_values do |val|
53
+ if val.is_a?(String)
54
+ # Convert to all newlines first, for consistency, just in case there
55
+ # is some weird mix of newlines & carriage returns in input
56
+ val.encode(universal_newline: true).encode(crlf_newline: true)
57
+ else
58
+ val
59
+ end
60
+ end
61
+ end
62
+
50
63
  private
51
64
 
52
65
  def add_params(instance_variable, param, *params)
@@ -81,20 +94,34 @@ module IMS::LTI::Models::Messages
81
94
  OAUTH_KEYS = :oauth_callback, :oauth_consumer_key, :oauth_nonce, :oauth_signature, :oauth_signature_method,
82
95
  :oauth_timestamp, :oauth_token, :oauth_verifier, :oauth_version
83
96
 
84
- attr_accessor :launch_url, *OAUTH_KEYS
97
+ attr_accessor :launch_url, :jwt, *OAUTH_KEYS
85
98
  attr_reader :unknown_params, :custom_params, :ext_params
86
99
 
87
100
  add_required_params :lti_message_type, :lti_version
88
101
 
89
- def self.generate(params)
90
- klass = self.descendants.select{|d| d::MESSAGE_TYPE == params['lti_message_type']}.first
91
- klass ? klass.new(params) : Message.new(params)
102
+ def self.generate(launch_params)
103
+ params = launch_params.key?('jwt') ? parse_jwt(jwt: launch_params['jwt']) : launch_params
104
+ klass = self.descendants.select {|d| d::MESSAGE_TYPE == params['lti_message_type']}.first
105
+ message = klass ? klass.new(params) : Message.new(params)
106
+ message.jwt = launch_params['jwt'] if launch_params.key?('jwt')
107
+ message
92
108
  end
93
109
 
94
- def initialize(attrs = {})
110
+ def self.parse_jwt(jwt:)
111
+ decoded_jwt = JSON::JWT.decode(jwt, :skip_verification)
112
+ params = decoded_jwt['org.imsglobal.lti.message'] || {}
113
+ custom = params.delete(:custom)
114
+ custom.each {|k,v| params["custom_#{k}"] = v }
115
+ params['consumer_key'] = decoded_jwt[:sub]
116
+ ext = params.delete(:ext)
117
+ ext.each {|k,v| params["ext_#{k}"] = v }
118
+ params
119
+ end
120
+
121
+ def initialize(attrs = {}, custom_params = {}, ext_params = {})
95
122
 
96
- @custom_params = {}
97
- @ext_params = {}
123
+ @custom_params = custom_params
124
+ @ext_params = ext_params
98
125
  @unknown_params = {}
99
126
 
100
127
  attrs.each do |k, v|
@@ -114,20 +141,32 @@ module IMS::LTI::Models::Messages
114
141
  end
115
142
 
116
143
  def add_custom_params(params)
117
- params.each { |k, v| k.to_s.start_with?('custom_') ? @custom_params[k.to_s] = v : @custom_params["custom_#{k.to_s}"] = v }
144
+ params.each {|k, v| k.to_s.start_with?('custom_') ? @custom_params[k.to_s] = v : @custom_params["custom_#{k.to_s}"] = v}
118
145
  end
119
146
 
120
147
  def get_custom_params
121
- @custom_params.inject({}) { |hash, (k, v)| hash[k.gsub(/\Acustom_/, '')] = v; hash }
148
+ @custom_params.inject({}) {|hash, (k, v)| hash[k.gsub(/\Acustom_/, '')] = v; hash}
149
+ end
150
+
151
+ def get_ext_params
152
+ @ext_params.inject({}) {|hash, (k, v)| hash[k.gsub(/\Aext_/, '')] = v; hash}
122
153
  end
123
154
 
124
155
  def post_params
125
156
  unknown_params.merge(@custom_params).merge(@ext_params).merge(parameters)
126
157
  end
127
158
 
159
+ def jwt_params(private_key:, originating_domain:, algorithm: :HS256)
160
+ { 'jwt' => to_jwt(private_key: private_key, originating_domain: originating_domain, algorithm: algorithm) }
161
+ end
162
+
128
163
  def signed_post_params(secret)
129
- message_params = { oauth_consumer_key: oauth_consumer_key}.merge(post_params)
130
- @message_authenticator = IMS::LTI::Services::MessageAuthenticator.new(launch_url, message_params, secret )
164
+ # The params will be used in an HTML form, and browsers will always use
165
+ # newlines+carriage return line endings for submitted form data. The
166
+ # signature needs to match, and signature generation does not add carriage
167
+ # returns, so we ensure CRLF endings here.
168
+ message_params = self.class.convert_param_values_to_crlf_endings(oauth_params.merge(post_params))
169
+ @message_authenticator = IMS::LTI::Services::MessageAuthenticator.new(launch_url, message_params, secret)
131
170
  @message_authenticator.signed_params
132
171
  end
133
172
 
@@ -165,6 +204,27 @@ module IMS::LTI::Models::Messages
165
204
  end
166
205
  end
167
206
 
207
+ def to_jwt(private_key:, originating_domain:, algorithm: :HS256)
208
+ now = Time.now
209
+ exp = now + 60 * 5
210
+ ims = unknown_params.merge(parameters)
211
+ ims[:custom] = get_custom_params
212
+ ims[:ext] = get_ext_params
213
+ claim = {
214
+ iss: originating_domain,
215
+ sub: consumer_key,
216
+ aud: launch_url,
217
+ iat: now,
218
+ exp: exp,
219
+ jti: SecureRandom.uuid,
220
+ "org.imsglobal.lti.message" => ims
221
+ }
222
+ jwt = JSON::JWT.new(claim).sign(private_key, algorithm)
223
+ jwt.to_s
224
+ end
225
+
226
+ alias_attribute :consumer_key, :oauth_consumer_key
227
+
168
228
  private
169
229
 
170
230
  def collect_attributes(attributes)
@@ -176,4 +236,4 @@ module IMS::LTI::Models::Messages
176
236
  end
177
237
 
178
238
  end
179
- end
239
+ end
@@ -1,7 +1,8 @@
1
1
  module IMS::LTI::Models::Messages
2
2
  class RegistrationRequest < RequestMessage
3
3
 
4
- add_required_params :reg_key, :reg_password, :tc_profile_url, :launch_presentation_return_url
4
+ add_required_params :reg_key, :reg_password, :tc_profile_url, :launch_presentation_return_url, :tool_proxy_guid,
5
+ :tool_proxy_url
5
6
 
6
7
 
7
8
  MESSAGE_TYPE = 'ToolProxyRegistrationRequest'
@@ -16,4 +17,4 @@ module IMS::LTI::Models::Messages
16
17
  end
17
18
 
18
19
  end
19
- end
20
+ end
@@ -1,10 +1,10 @@
1
1
  module IMS::LTI::Models::Messages
2
- class ToolProxyReregistrationRequest < RequestMessage
2
+ class ToolProxyUpdateRequest < RequestMessage
3
3
 
4
4
  add_required_params :tc_profile_url, :launch_presentation_return_url
5
5
 
6
6
 
7
- MESSAGE_TYPE = 'ToolProxyReregistrationRequest'
7
+ MESSAGE_TYPE = 'ToolProxyUpdateRequest'
8
8
 
9
9
  def initialize(attrs = {})
10
10
  super(attrs)
@@ -6,6 +6,6 @@ module IMS::LTI::Models
6
6
  require_relative 'messages/basic_lti_launch_request'
7
7
  require_relative 'messages/content_item_selection_request'
8
8
  require_relative 'messages/content_item_selection'
9
- require_relative 'messages/tool_proxy_reregistration_request'
9
+ require_relative 'messages/tool_proxy_update_request'
10
10
  end
11
11
  end
@@ -11,6 +11,7 @@ module IMS::LTI::Models
11
11
  add_attribute :id, json_key:'@id'
12
12
  add_attribute :type, json_key:'@type'
13
13
  add_attribute :context, json_key:'@context'
14
+ add_attribute :security_profile, relation: 'IMS::LTI::Models::SecurityProfile'
14
15
  add_attribute :product_instance, relation:'IMS::LTI::Models::ProductInstance'
15
16
  add_attribute :service_offered, relation: 'IMS::LTI::Models::RestService'
16
17
 
@@ -33,7 +34,12 @@ module IMS::LTI::Models
33
34
  end
34
35
 
35
36
  def reregistration_capable?
36
- @capability_offered.include?(Messages::ToolProxyReregistrationRequest::MESSAGE_TYPE)
37
+ @capability_offered.include?(Messages::ToolProxyUpdateRequest::MESSAGE_TYPE)
37
38
  end
39
+
40
+ def security_profile_by_name(security_profile_name:)
41
+ security_profiles.find { |sp| sp.security_profile_name == security_profile_name}
42
+ end
43
+
38
44
  end
39
45
  end
@@ -7,5 +7,6 @@ module IMS::LTI::Serializers::MembershipService
7
7
  set_attribute :result_sourced_id, key: :resultSourcedId
8
8
  set_attribute :sourced_id, key: :sourcedId
9
9
  set_attribute :user_id, key: :userId
10
+ set_attribute :sis_id, key: :sisId, optional: true
10
11
  end
11
12
  end
@@ -0,0 +1,67 @@
1
+ module IMS::LTI::Services
2
+ class AuthenticationService
3
+
4
+ attr_accessor :connection, :iss, :aud, :sub, :secret, :grant_type,
5
+ :additional_claims, :additional_params
6
+ attr_writer :secret
7
+
8
+ def initialize(iss:, aud:, sub:, secret:)
9
+ @iss = iss
10
+ @aud = aud
11
+ @sub = sub
12
+ @secret = secret
13
+ @additional_claims = {}
14
+ @additional_params = {}
15
+ @grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
16
+ end
17
+
18
+ def connection
19
+ @connection ||= Faraday.new
20
+ end
21
+
22
+ def access_token
23
+ access_token_request['access_token']
24
+ end
25
+
26
+ def expiration
27
+ expires_in = access_token_request['expires_in'].to_i
28
+ @_response_time + expires_in
29
+ end
30
+
31
+ def expired?
32
+ expiration < Time.now
33
+ end
34
+
35
+ def invalidate!
36
+ @_access_token_request = nil
37
+ @_response_time = nil
38
+ end
39
+
40
+ private
41
+
42
+ def access_token_request
43
+ @_access_token_request ||= begin
44
+ assertion = JSON::JWT.new(
45
+ iss: iss,
46
+ sub: sub,
47
+ aud: aud.to_s,
48
+ iat: Time.now.to_i,
49
+ exp: 1.minute.from_now,
50
+ jti: SecureRandom.uuid
51
+ )
52
+ assertion.merge!(@additional_claims)
53
+ assertion = assertion.sign(@secret, :HS256).to_s
54
+ body = {
55
+ grant_type: grant_type,
56
+ assertion: assertion
57
+ }
58
+ body.merge!(@additional_params)
59
+ response = connection.post(aud, body)
60
+ raise IMS::LTI::Errors::AuthenticationFailedError.new(response: response) unless response.success?
61
+ @_response_time = Time.now
62
+ response.body
63
+ end
64
+ end
65
+
66
+ end
67
+ end
@@ -14,7 +14,7 @@ module IMS::LTI::Services
14
14
 
15
15
 
16
16
  def valid_signature?
17
- simple_oauth_header.valid?(signature: signature)
17
+ message.jwt ? valid_jwt? : simple_oauth_header.valid?(signature: signature)
18
18
  end
19
19
 
20
20
  def message
@@ -33,8 +33,7 @@ module IMS::LTI::Services
33
33
  @options.merge(
34
34
  {
35
35
  consumer_key: consumer_key,
36
- consumer_secret: @secret,
37
- callback: 'about:blank'
36
+ consumer_secret: @secret
38
37
  }
39
38
  )
40
39
  )
@@ -47,11 +46,24 @@ module IMS::LTI::Services
47
46
  end
48
47
 
49
48
  def signed_params
50
- simple_oauth_header.signed_attributes.merge(params)
49
+ simple_oauth_header.signed_attributes.merge(@parsed_params)
51
50
  end
52
51
 
53
52
 
54
53
  private
54
+
55
+ def valid_jwt?
56
+ begin
57
+ jwt = JSON::JWT.decode(message.jwt, @secret)
58
+ aud1 = Addressable::URI.parse(jwt['aud'])
59
+ aud2 = Addressable::URI.parse(launch_url)
60
+ [aud1, aud2].each{ |aud| aud.fragment = '' }
61
+ aud1.normalize == aud2.normalize
62
+ rescue JSON::JWS::VerificationFailed
63
+ false
64
+ end
65
+ end
66
+
55
67
  def parse_params(params)
56
68
  params.inject([{}, {}]) do |array, (k, v)|
57
69
  attr = k.to_s.sub('oauth_', '').to_sym
@@ -65,4 +77,4 @@ module IMS::LTI::Services
65
77
  end
66
78
 
67
79
  end
68
- end
80
+ end
@@ -0,0 +1,18 @@
1
+ module IMS::LTI::Services
2
+
3
+ class OAuth2Client
4
+ attr_accessor :token, :base_url
5
+ attr_writer :connection
6
+
7
+ def initialize(token:, base_url: nil)
8
+ @base_url = base_url
9
+ @token = token
10
+ end
11
+
12
+ def connection
13
+ @connection ||= Faraday.new base_url do |conn|
14
+ conn.authorization :Bearer, token
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module IMS::LTI::Services
2
+ class ToolConsumerProfileService
3
+
4
+ attr_accessor :tcp
5
+
6
+ def initialize(tool_consumer_profile)
7
+ @tcp = tool_consumer_profile
8
+ end
9
+
10
+ def supports_capabilities?(capability, *capabilities)
11
+ capabilities.unshift(capability)
12
+ (capabilities - tcp.capabilities_offered).empty?
13
+ end
14
+
15
+ end
16
+ end
@@ -76,7 +76,7 @@ module IMS::LTI::Services
76
76
  end
77
77
 
78
78
  def reregistration?
79
- @registration_request.is_a?(IMS::LTI::Models::Messages::ToolProxyReregistrationRequest)
79
+ @registration_request.is_a?(IMS::LTI::Models::Messages::ToolProxyUpdateRequest)
80
80
  end
81
81
 
82
82
 
@@ -85,25 +85,42 @@ module IMS::LTI::Services
85
85
  ret_val
86
86
  end
87
87
 
88
+ def invalid_security_profiles
89
+ security_profiles = tool_proxy.tool_profile.security_profiles
90
+ array = security_profiles.each_with_object([]) do |sp, array|
91
+ tcp_sp = tool_consumer_profile.security_profile_by_name(security_profile_name: sp.security_profile_name)
92
+ if tcp_sp
93
+ supported_algorithms = sp.digest_algorithms & tcp_sp.digest_algorithms
94
+ unsupported_algorithms = sp.digest_algorithms - supported_algorithms
95
+ unless unsupported_algorithms.empty?
96
+ array << { name: sp.security_profile_name, algorithms: unsupported_algorithms }
97
+ end
98
+ else
99
+ array << { name: sp.security_profile_name }
100
+ end
101
+ end
102
+ array
103
+ end
104
+
88
105
  def errors
89
106
  ret_val = {}
90
107
  ret_val[:invalid_security_contract] = invalid_security_contract unless invalid_security_contract.empty?
91
108
  ret_val[:invalid_capabilities] = invalid_capabilities unless invalid_capabilities.empty?
92
109
  ret_val[:invalid_message_handlers] = invalid_message_handlers unless invalid_message_handlers.empty?
93
110
  ret_val[:invalid_services] = invalid_services unless invalid_services.empty?
94
-
111
+ ret_val[:invalid_security_profiles] = invalid_security_profiles unless invalid_security_profiles.empty?
95
112
  ret_val
96
113
  end
97
114
 
98
115
  def valid?
99
- invalid_capabilities.empty? && invalid_security_contract.empty? && invalid_services.empty? && invalid_message_handlers.empty?
116
+ errors.keys.empty?
100
117
  end
101
118
 
102
119
  private
103
120
 
104
121
  def normalize_strings(string, *strings)
105
122
  strings.push(string)
106
- normalized = strings.map { |s| s.upcase.strip }
123
+ normalized = strings.map {|s| s.upcase.strip}
107
124
  normalized
108
125
  end
109
126
 
@@ -112,7 +129,7 @@ module IMS::LTI::Services
112
129
  invalid_capabilities = mh.enabled_capabilities - capabilities_offered
113
130
  invalid_parameters = validate_parameters(mh.parameters)
114
131
  if !invalid_parameters.empty? || !invalid_capabilities.empty?
115
- hash = {message_type: mh.message_type, }
132
+ hash = { message_type: mh.message_type, }
116
133
  hash[:invalid_capabilities] = invalid_capabilities unless invalid_capabilities.empty?
117
134
  hash[:invalid_parameters] = invalid_parameters unless invalid_parameters.empty?
118
135
  array << hash
@@ -124,7 +141,7 @@ module IMS::LTI::Services
124
141
  def validate_parameters(parameters)
125
142
  parameters.each_with_object([]) do |p, array|
126
143
  if !p.fixed? && !capabilities_offered.include?(p.variable)
127
- array << {name: p.name, variable: p.variable}
144
+ array << { name: p.name, variable: p.variable }
128
145
  end
129
146
  end
130
147
  end
@@ -142,7 +159,7 @@ module IMS::LTI::Services
142
159
  invalid_mhs = validate_message_handlers(rh.messages)
143
160
  if !invalid_mhs.empty? || !invalid_message_types.empty?
144
161
  hash = {
145
- code: rh.resource_type.code,
162
+ code: rh.resource_type.code,
146
163
  }
147
164
  hash[:messages] = invalid_mhs unless invalid_mhs.empty?
148
165
  hash[:invalid_message_types] = invalid_message_types unless invalid_message_types.empty?
@@ -161,6 +178,5 @@ module IMS::LTI::Services
161
178
  hash
162
179
  end
163
180
 
164
-
165
181
  end
166
182
  end
@@ -1,8 +1,11 @@
1
1
  module IMS::LTI
2
2
  module Services
3
+ require_relative 'services/oauth2_client'
3
4
  require_relative 'services/tool_proxy_registration_service'
4
5
  require_relative 'services/tool_config'
5
6
  require_relative 'services/tool_proxy_validator'
6
7
  require_relative 'services/message_authenticator'
8
+ require_relative 'services/tool_consumer_profile_service'
9
+ require_relative 'services/authentication_service'
7
10
  end
8
- end
11
+ end
@@ -1,5 +1,5 @@
1
1
  module IMS
2
2
  module LTI
3
- VERSION = "2.0.0.beta.27"
3
+ VERSION = "2.3.3"
4
4
  end
5
5
  end
data/lib/ims/lti.rb CHANGED
@@ -1,17 +1,19 @@
1
- require 'json'
2
- require 'securerandom'
3
- require 'simple_oauth'
1
+ require 'addressable/uri'
2
+ require 'builder'
4
3
  require 'faraday'
5
4
  require 'faraday_middleware'
6
- require 'builder'
5
+ require 'json'
6
+ require 'json/jwt'
7
7
  require 'rexml/document'
8
+ require 'securerandom'
9
+ require 'simple_oauth'
8
10
 
9
11
  module IMS
10
12
  module LTI
11
- require_relative 'lti/models'
12
13
  require_relative 'lti/converters'
13
- require_relative 'lti/services'
14
14
  require_relative 'lti/errors'
15
+ require_relative 'lti/models'
15
16
  require_relative 'lti/serializers'
17
+ require_relative 'lti/services'
16
18
  end
17
19
  end
metadata CHANGED
@@ -1,99 +1,133 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ims-lti
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Instructure
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-27 00:00:00.000000000 Z
11
+ date: 2023-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: simple_oauth
14
+ name: addressable
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '='
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.5'
20
+ - - ">="
18
21
  - !ruby/object:Gem::Version
19
- version: '0.2'
22
+ version: 2.5.1
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - '='
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.5'
30
+ - - ">="
25
31
  - !ruby/object:Gem::Version
26
- version: '0.2'
32
+ version: 2.5.1
27
33
  - !ruby/object:Gem::Dependency
28
- name: faraday
34
+ name: builder
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '0.8'
39
+ version: '3.2'
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '0.8'
46
+ version: '3.2'
47
+ - !ruby/object:Gem::Dependency
48
+ name: faraday
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "<"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.0'
41
61
  - !ruby/object:Gem::Dependency
42
62
  name: faraday_middleware
43
63
  requirement: !ruby/object:Gem::Requirement
44
64
  requirements:
45
- - - "~>"
65
+ - - "<"
46
66
  - !ruby/object:Gem::Version
47
- version: '0.8'
67
+ version: '2.0'
48
68
  type: :runtime
49
69
  prerelease: false
50
70
  version_requirements: !ruby/object:Gem::Requirement
51
71
  requirements:
52
- - - "~>"
72
+ - - "<"
53
73
  - !ruby/object:Gem::Version
54
- version: '0.8'
74
+ version: '2.0'
55
75
  - !ruby/object:Gem::Dependency
56
- name: builder
76
+ name: json-jwt
57
77
  requirement: !ruby/object:Gem::Requirement
58
78
  requirements:
59
79
  - - "~>"
60
80
  - !ruby/object:Gem::Version
61
- version: '3.2'
81
+ version: '1.7'
62
82
  type: :runtime
63
83
  prerelease: false
64
84
  version_requirements: !ruby/object:Gem::Requirement
65
85
  requirements:
66
86
  - - "~>"
67
87
  - !ruby/object:Gem::Version
68
- version: '3.2'
88
+ version: '1.7'
69
89
  - !ruby/object:Gem::Dependency
70
- name: rake
90
+ name: simple_oauth
71
91
  requirement: !ruby/object:Gem::Requirement
72
92
  requirements:
73
93
  - - "~>"
74
94
  - !ruby/object:Gem::Version
75
- version: '10.4'
76
- type: :development
95
+ version: 0.3.1
96
+ type: :runtime
77
97
  prerelease: false
78
98
  version_requirements: !ruby/object:Gem::Requirement
79
99
  requirements:
80
100
  - - "~>"
81
101
  - !ruby/object:Gem::Version
82
- version: '10.4'
102
+ version: 0.3.1
83
103
  - !ruby/object:Gem::Dependency
84
- name: rspec
104
+ name: rexml
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: byebug
85
119
  requirement: !ruby/object:Gem::Requirement
86
120
  requirements:
87
121
  - - "~>"
88
122
  - !ruby/object:Gem::Version
89
- version: '3.2'
123
+ version: '9.0'
90
124
  type: :development
91
125
  prerelease: false
92
126
  version_requirements: !ruby/object:Gem::Requirement
93
127
  requirements:
94
128
  - - "~>"
95
129
  - !ruby/object:Gem::Version
96
- version: '3.2'
130
+ version: '9.0'
97
131
  - !ruby/object:Gem::Dependency
98
132
  name: guard
99
133
  requirement: !ruby/object:Gem::Requirement
@@ -128,14 +162,14 @@ dependencies:
128
162
  requirements:
129
163
  - - "~>"
130
164
  - !ruby/object:Gem::Version
131
- version: '2.10'
165
+ version: '3.0'
132
166
  type: :development
133
167
  prerelease: false
134
168
  version_requirements: !ruby/object:Gem::Requirement
135
169
  requirements:
136
170
  - - "~>"
137
171
  - !ruby/object:Gem::Version
138
- version: '2.10'
172
+ version: '3.0'
139
173
  - !ruby/object:Gem::Dependency
140
174
  name: pry
141
175
  requirement: !ruby/object:Gem::Requirement
@@ -151,19 +185,47 @@ dependencies:
151
185
  - !ruby/object:Gem::Version
152
186
  version: '0.10'
153
187
  - !ruby/object:Gem::Dependency
154
- name: byebug
188
+ name: rake
155
189
  requirement: !ruby/object:Gem::Requirement
156
190
  requirements:
157
191
  - - "~>"
158
192
  - !ruby/object:Gem::Version
159
- version: '8.2'
193
+ version: '12.0'
160
194
  type: :development
161
195
  prerelease: false
162
196
  version_requirements: !ruby/object:Gem::Requirement
163
197
  requirements:
164
198
  - - "~>"
165
199
  - !ruby/object:Gem::Version
166
- version: '8.2'
200
+ version: '12.0'
201
+ - !ruby/object:Gem::Dependency
202
+ name: rspec
203
+ requirement: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - "~>"
206
+ - !ruby/object:Gem::Version
207
+ version: '3.2'
208
+ type: :development
209
+ prerelease: false
210
+ version_requirements: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - "~>"
213
+ - !ruby/object:Gem::Version
214
+ version: '3.2'
215
+ - !ruby/object:Gem::Dependency
216
+ name: timecop
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - "~>"
220
+ - !ruby/object:Gem::Version
221
+ version: '0.8'
222
+ type: :development
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - "~>"
227
+ - !ruby/object:Gem::Version
228
+ version: '0.8'
167
229
  description:
168
230
  email: opensource@instructure.com
169
231
  executables: []
@@ -189,6 +251,7 @@ files:
189
251
  - lib/ims/lti/converters.rb
190
252
  - lib/ims/lti/converters/time_json_converter.rb
191
253
  - lib/ims/lti/errors.rb
254
+ - lib/ims/lti/errors/authentication_failed_error.rb
192
255
  - lib/ims/lti/errors/invalid_lti_config_error.rb
193
256
  - lib/ims/lti/errors/invalid_tool_consumer_profile.rb
194
257
  - lib/ims/lti/errors/tool_proxy_registration_error.rb
@@ -226,7 +289,7 @@ files:
226
289
  - lib/ims/lti/models/messages/message.rb
227
290
  - lib/ims/lti/models/messages/registration_request.rb
228
291
  - lib/ims/lti/models/messages/request_message.rb
229
- - lib/ims/lti/models/messages/tool_proxy_reregistration_request.rb
292
+ - lib/ims/lti/models/messages/tool_proxy_update_request.rb
230
293
  - lib/ims/lti/models/parameter.rb
231
294
  - lib/ims/lti/models/product_family.rb
232
295
  - lib/ims/lti/models/product_info.rb
@@ -259,8 +322,11 @@ files:
259
322
  - lib/ims/lti/serializers/membership_service/page_serializer.rb
260
323
  - lib/ims/lti/serializers/membership_service/person_serializer.rb
261
324
  - lib/ims/lti/services.rb
325
+ - lib/ims/lti/services/authentication_service.rb
262
326
  - lib/ims/lti/services/message_authenticator.rb
327
+ - lib/ims/lti/services/oauth2_client.rb
263
328
  - lib/ims/lti/services/tool_config.rb
329
+ - lib/ims/lti/services/tool_consumer_profile_service.rb
264
330
  - lib/ims/lti/services/tool_proxy_registration_service.rb
265
331
  - lib/ims/lti/services/tool_proxy_validator.rb
266
332
  - lib/ims/lti/version.rb
@@ -283,8 +349,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
283
349
  - !ruby/object:Gem::Version
284
350
  version: '0'
285
351
  requirements: []
286
- rubyforge_project:
287
- rubygems_version: 2.6.8
352
+ rubygems_version: 3.2.22
288
353
  signing_key:
289
354
  specification_version: 4
290
355
  summary: Ruby library for creating IMS LTI tool providers and consumers