ims-lti 2.1.2 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2bdd06e5c60fc13eb134e231cf0e0ee7738eb9a8
4
- data.tar.gz: 56c1d472a02e4d5359b9e03977a0d9f604a3a09f
3
+ metadata.gz: 64af3f1aebf17f2f5cc0029cabbead8ecc7a0370
4
+ data.tar.gz: 33ba505d3df21a88f8a10e9bc810ba9b4f4605fc
5
5
  SHA512:
6
- metadata.gz: 264a0293b2ccad3c5047d081ba08d6f2967a3e26c621855a1add4cafd113f3627d95cb75d95b491cc47293a35ded64ef9d82aa6ac61e393dde2e69189398fb91
7
- data.tar.gz: 47cfe33a68b1a8ee738ab6d80bc8e8e8d4b75d8fc47c25da6e42fef69b9ca55f04a5b343b82687d161434943670f6149f75da13ec6fb5be30c2485f965bc6819
6
+ metadata.gz: 194581f7c78f74ba27eb759eb0a39bc23c4c913a085737be6e5839b5d26fe74989c146bbd8e803cc1eb22d7419dbedf5ef0070480e9066068799de32821c0b6a
7
+ data.tar.gz: b0973c1dbfb50d420d7a93416d30f1d78370735dfbf0dde8be16684042911f4987e1b00fdc3a75d6de01dd0095d7815656a5f15e80338ec7b5226698bef0f42e
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
 
@@ -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
@@ -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
@@ -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
@@ -40,7 +40,7 @@ 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
@@ -81,20 +81,34 @@ module IMS::LTI::Models::Messages
81
81
  OAUTH_KEYS = :oauth_callback, :oauth_consumer_key, :oauth_nonce, :oauth_signature, :oauth_signature_method,
82
82
  :oauth_timestamp, :oauth_token, :oauth_verifier, :oauth_version
83
83
 
84
- attr_accessor :launch_url, *OAUTH_KEYS
84
+ attr_accessor :launch_url, :jwt, *OAUTH_KEYS
85
85
  attr_reader :unknown_params, :custom_params, :ext_params
86
86
 
87
87
  add_required_params :lti_message_type, :lti_version
88
88
 
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)
89
+ def self.generate(launch_params)
90
+ params = launch_params.key?('jwt') ? parse_jwt(jwt: launch_params['jwt']) : launch_params
91
+ klass = self.descendants.select {|d| d::MESSAGE_TYPE == params['lti_message_type']}.first
92
+ message = klass ? klass.new(params) : Message.new(params)
93
+ message.jwt = launch_params['jwt'] if launch_params.key?('jwt')
94
+ message
92
95
  end
93
96
 
94
- def initialize(attrs = {})
97
+ def self.parse_jwt(jwt:)
98
+ decoded_jwt = JSON::JWT.decode(jwt, :skip_verification)
99
+ params = decoded_jwt['org.imsglobal.lti.message'] || {}
100
+ custom = params.delete(:custom)
101
+ custom.each {|k,v| params["custom_#{k}"] = v }
102
+ params['consumer_key'] = decoded_jwt[:sub]
103
+ ext = params.delete(:ext)
104
+ ext.each {|k,v| params["ext_#{k}"] = v }
105
+ params
106
+ end
107
+
108
+ def initialize(attrs = {}, custom_params = {}, ext_params = {})
95
109
 
96
- @custom_params = {}
97
- @ext_params = {}
110
+ @custom_params = custom_params
111
+ @ext_params = ext_params
98
112
  @unknown_params = {}
99
113
 
100
114
  attrs.each do |k, v|
@@ -114,20 +128,28 @@ module IMS::LTI::Models::Messages
114
128
  end
115
129
 
116
130
  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 }
131
+ params.each {|k, v| k.to_s.start_with?('custom_') ? @custom_params[k.to_s] = v : @custom_params["custom_#{k.to_s}"] = v}
118
132
  end
119
133
 
120
134
  def get_custom_params
121
- @custom_params.inject({}) { |hash, (k, v)| hash[k.gsub(/\Acustom_/, '')] = v; hash }
135
+ @custom_params.inject({}) {|hash, (k, v)| hash[k.gsub(/\Acustom_/, '')] = v; hash}
136
+ end
137
+
138
+ def get_ext_params
139
+ @ext_params.inject({}) {|hash, (k, v)| hash[k.gsub(/\Aext_/, '')] = v; hash}
122
140
  end
123
141
 
124
142
  def post_params
125
143
  unknown_params.merge(@custom_params).merge(@ext_params).merge(parameters)
126
144
  end
127
145
 
146
+ def jwt_params(private_key:, originating_domain:, algorithm: :HS256)
147
+ { 'jwt' => to_jwt(private_key: private_key, originating_domain: originating_domain, algorithm: algorithm) }
148
+ end
149
+
128
150
  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 )
151
+ message_params = { oauth_consumer_key: oauth_consumer_key }.merge(post_params)
152
+ @message_authenticator = IMS::LTI::Services::MessageAuthenticator.new(launch_url, message_params, secret)
131
153
  @message_authenticator.signed_params
132
154
  end
133
155
 
@@ -165,6 +187,27 @@ module IMS::LTI::Models::Messages
165
187
  end
166
188
  end
167
189
 
190
+ def to_jwt(private_key:, originating_domain:, algorithm: :HS256)
191
+ now = Time.now
192
+ exp = now + 60 * 5
193
+ ims = unknown_params.merge(parameters)
194
+ ims[:custom] = get_custom_params
195
+ ims[:ext] = get_ext_params
196
+ claim = {
197
+ iss: originating_domain,
198
+ sub: consumer_key,
199
+ aud: launch_url,
200
+ iat: now,
201
+ exp: exp,
202
+ jti: SecureRandom.uuid,
203
+ "org.imsglobal.lti.message" => ims
204
+ }
205
+ jwt = JSON::JWT.new(claim).sign(private_key, algorithm)
206
+ jwt.to_s
207
+ end
208
+
209
+ alias_attribute :consumer_key, :oauth_consumer_key
210
+
168
211
  private
169
212
 
170
213
  def collect_attributes(attributes)
@@ -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
 
@@ -35,5 +36,10 @@ module IMS::LTI::Models
35
36
  def reregistration_capable?
36
37
  @capability_offered.include?(Messages::ToolProxyReregistrationRequest::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
@@ -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
@@ -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
@@ -52,6 +52,19 @@ module IMS::LTI::Services
52
52
 
53
53
 
54
54
  private
55
+
56
+ def valid_jwt?
57
+ begin
58
+ jwt = JSON::JWT.decode(message.jwt, @secret)
59
+ aud1 = Addressable::URI.parse(jwt['aud'])
60
+ aud2 = Addressable::URI.parse(launch_url)
61
+ [aud1, aud2].each{ |aud| aud.fragment = '' }
62
+ aud1.normalize == aud2.normalize
63
+ rescue JSON::JWS::VerificationFailed
64
+ false
65
+ end
66
+ end
67
+
55
68
  def parse_params(params)
56
69
  params.inject([{}, {}]) do |array, (k, v)|
57
70
  attr = k.to_s.sub('oauth_', '').to_sym
@@ -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
@@ -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
metadata CHANGED
@@ -1,29 +1,49 @@
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.1.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: 2017-06-28 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
18
  - !ruby/object:Gem::Version
19
- version: '0.2'
19
+ version: '2.5'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
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
+ - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '0.2'
29
+ version: '2.5'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.5.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: builder
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.2'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.2'
27
47
  - !ruby/object:Gem::Dependency
28
48
  name: faraday
29
49
  requirement: !ruby/object:Gem::Requirement
@@ -53,47 +73,47 @@ dependencies:
53
73
  - !ruby/object:Gem::Version
54
74
  version: '0.8'
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.2'
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.2'
83
103
  - !ruby/object:Gem::Dependency
84
- name: rspec
104
+ name: byebug
85
105
  requirement: !ruby/object:Gem::Requirement
86
106
  requirements:
87
107
  - - "~>"
88
108
  - !ruby/object:Gem::Version
89
- version: '3.2'
109
+ version: '8.2'
90
110
  type: :development
91
111
  prerelease: false
92
112
  version_requirements: !ruby/object:Gem::Requirement
93
113
  requirements:
94
114
  - - "~>"
95
115
  - !ruby/object:Gem::Version
96
- version: '3.2'
116
+ version: '8.2'
97
117
  - !ruby/object:Gem::Dependency
98
118
  name: guard
99
119
  requirement: !ruby/object:Gem::Requirement
@@ -151,19 +171,47 @@ dependencies:
151
171
  - !ruby/object:Gem::Version
152
172
  version: '0.10'
153
173
  - !ruby/object:Gem::Dependency
154
- name: byebug
174
+ name: rake
155
175
  requirement: !ruby/object:Gem::Requirement
156
176
  requirements:
157
177
  - - "~>"
158
178
  - !ruby/object:Gem::Version
159
- version: '8.2'
179
+ version: '10.4'
160
180
  type: :development
161
181
  prerelease: false
162
182
  version_requirements: !ruby/object:Gem::Requirement
163
183
  requirements:
164
184
  - - "~>"
165
185
  - !ruby/object:Gem::Version
166
- version: '8.2'
186
+ version: '10.4'
187
+ - !ruby/object:Gem::Dependency
188
+ name: rspec
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - "~>"
192
+ - !ruby/object:Gem::Version
193
+ version: '3.2'
194
+ type: :development
195
+ prerelease: false
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - "~>"
199
+ - !ruby/object:Gem::Version
200
+ version: '3.2'
201
+ - !ruby/object:Gem::Dependency
202
+ name: timecop
203
+ requirement: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - "~>"
206
+ - !ruby/object:Gem::Version
207
+ version: '0.8'
208
+ type: :development
209
+ prerelease: false
210
+ version_requirements: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - "~>"
213
+ - !ruby/object:Gem::Version
214
+ version: '0.8'
167
215
  description:
168
216
  email: opensource@instructure.com
169
217
  executables: []
@@ -189,6 +237,7 @@ files:
189
237
  - lib/ims/lti/converters.rb
190
238
  - lib/ims/lti/converters/time_json_converter.rb
191
239
  - lib/ims/lti/errors.rb
240
+ - lib/ims/lti/errors/authentication_failed_error.rb
192
241
  - lib/ims/lti/errors/invalid_lti_config_error.rb
193
242
  - lib/ims/lti/errors/invalid_tool_consumer_profile.rb
194
243
  - lib/ims/lti/errors/tool_proxy_registration_error.rb
@@ -259,8 +308,11 @@ files:
259
308
  - lib/ims/lti/serializers/membership_service/page_serializer.rb
260
309
  - lib/ims/lti/serializers/membership_service/person_serializer.rb
261
310
  - lib/ims/lti/services.rb
311
+ - lib/ims/lti/services/authentication_service.rb
262
312
  - lib/ims/lti/services/message_authenticator.rb
313
+ - lib/ims/lti/services/oauth2_client.rb
263
314
  - lib/ims/lti/services/tool_config.rb
315
+ - lib/ims/lti/services/tool_consumer_profile_service.rb
264
316
  - lib/ims/lti/services/tool_proxy_registration_service.rb
265
317
  - lib/ims/lti/services/tool_proxy_validator.rb
266
318
  - lib/ims/lti/version.rb
@@ -284,7 +336,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
284
336
  version: '0'
285
337
  requirements: []
286
338
  rubyforge_project:
287
- rubygems_version: 2.6.8
339
+ rubygems_version: 2.6.11
288
340
  signing_key:
289
341
  specification_version: 4
290
342
  summary: Ruby library for creating IMS LTI tool providers and consumers