smart_app_launch_test_kit 0.4.0 → 0.4.1

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: 60325a0cc4d2866edb260627b289e76676d0847bd2e28523556f39170d424dac
4
- data.tar.gz: dd887ba5a645f71f16e9f2269886628ca5911d57c79e3d03699582d6ae810b7f
3
+ metadata.gz: f66c9b0314200d03d78422dc6412fe30cd0a091cd34d2a4701b9daa9a85d45f6
4
+ data.tar.gz: 7a34428293bfe281ebeebf83e8ee37597ebdfef2bf158cb8a3893598eca09876
5
5
  SHA512:
6
- metadata.gz: 16ee6a9963940d5ea882e894b5e1db23646c86a51e1f6dbe58868878c047708a581c0f353ba24d264a4c49cdc8f549f522afc40ee7bbd5127d89b0b9ac7f2e36
7
- data.tar.gz: 022f7b43c590f419638e23614a84dc0c5d106b87bbef38dd6d4b2e71650b58bf86db59bd6bb231c04280a0274e105b6486601fb41fa3749485ddfd534a15beb4
6
+ metadata.gz: d5f432c1b4b43a2c84be8613acb0b31dec557b80b1b76996773c76486db5197265a3dc1f0b9a9015eaa35c17c65d5b6b7eb506d940676e0cdae3b798b1cf8799
7
+ data.tar.gz: b63b86f90dbfc0ea88b7cc65e2075333b07a2cee7d42f88f21d209f4a51274545532706ed0278efad3cd4a0316be4ae32e948632f4ba66247d5451c68eff9559
@@ -0,0 +1,88 @@
1
+ require_relative 'backend_services_authorization_request_builder'
2
+ require_relative 'backend_services_invalid_grant_type_test'
3
+ require_relative 'backend_services_invalid_client_assertion_test'
4
+ require_relative 'backend_services_invalid_jwt_test'
5
+ require_relative 'backend_services_authorization_request_success_test'
6
+ require_relative 'backend_services_authorization_response_body_test'
7
+ require_relative 'token_exchange_stu2_test'
8
+
9
+ module SMARTAppLaunch
10
+ class BackendServicesAuthorizationGroup < Inferno::TestGroup
11
+ title 'SMART Backend Services Authorization'
12
+ short_description 'Demonstrate SMART Backend Services Authorization'
13
+
14
+ id :backend_services_authorization
15
+
16
+ input :smart_token_url,
17
+ title: 'Backend Services Token Endpoint',
18
+ description: <<~DESCRIPTION
19
+ The OAuth 2.0 Token Endpoint used by the Backend Services specification to provide bearer tokens.
20
+ DESCRIPTION
21
+
22
+ input :backend_services_client_id,
23
+ title: 'Backend Services Client ID',
24
+ description: 'Client ID provided at registration to the Inferno application.'
25
+ input :backend_services_requested_scope,
26
+ title: 'Backend Services Requested Scopes',
27
+ description: 'Backend Services Scopes provided at registration to the Inferno application; will be `system/` scopes',
28
+ default: 'system/*.read'
29
+
30
+ input :client_auth_encryption_method,
31
+ title: 'Encryption Method for Asymmetric Confidential Client Authorization',
32
+ description: <<~DESCRIPTION,
33
+ The server is required to suport either ES384 or RS384 encryption methods for JWT signature verification.
34
+ Select which method to use.
35
+ DESCRIPTION
36
+ type: 'radio',
37
+ default: 'ES384',
38
+ options: {
39
+ list_options: [
40
+ {
41
+ label: 'ES384',
42
+ value: 'ES384'
43
+ },
44
+ {
45
+ label: 'RS384',
46
+ value: 'RS384'
47
+ }
48
+ ]
49
+ }
50
+ input :backend_services_jwks_kid,
51
+ title: 'Backend Services JWKS kid',
52
+ description: <<~DESCRIPTION,
53
+ The key ID of the JWKS private key to use for signing the client assertion when fetching an auth token.
54
+ Defaults to the first JWK in the list if no kid is supplied.
55
+ DESCRIPTION
56
+ optional: true
57
+
58
+ output :bearer_token
59
+
60
+ test from: :tls_version_test do
61
+ title 'Authorization service token endpoint secured by transport layer security'
62
+ description <<~DESCRIPTION
63
+ The [SMART App Launch 2.0.0 IG specification for Backend Services](https://hl7.org/fhir/smart-app-launch/STU2/backend-services.html#request-1)
64
+ states "the client SHALL use the Transport Layer Security (TLS) Protocol Version 1.2 (RFC5246)
65
+ or a more recent version of TLS to authenticate the identity of the FHIR authorization server and to
66
+ establish an encrypted, integrity-protected link for securing all exchanges between the client and the
67
+ FHIR authorization server’s token endpoint. All exchanges described herein between the client and the
68
+ FHIR server SHALL be secured using TLS V1.2 or a more recent version of TLS."
69
+ DESCRIPTION
70
+ id :smart_backend_services_token_tls_version
71
+
72
+ config(
73
+ inputs: { url: { name: :smart_token_url } },
74
+ options: { minimum_allowed_version: OpenSSL::SSL::TLS1_2_VERSION }
75
+ )
76
+ end
77
+
78
+ test from: :smart_backend_services_invalid_grant_type
79
+
80
+ test from: :smart_backend_services_invalid_client_assertion
81
+
82
+ test from: :smart_backend_services_invalid_jwt
83
+
84
+ test from: :smart_backend_services_auth_request_success
85
+
86
+ test from: :smart_backend_services_auth_response_body
87
+ end
88
+ end
@@ -0,0 +1,74 @@
1
+ require 'json/jwt'
2
+ require_relative 'client_assertion_builder'
3
+
4
+ module SMARTAppLaunch
5
+ class BackendServicesAuthorizationRequestBuilder
6
+ def self.build(...)
7
+ new(...).authorization_request
8
+ end
9
+
10
+ attr_reader :encryption_method, :scope, :iss, :sub, :aud, :content_type, :grant_type, :client_assertion_type, :exp,
11
+ :jti, :kid
12
+
13
+ def initialize(
14
+ encryption_method:,
15
+ scope:,
16
+ iss:,
17
+ sub:,
18
+ aud:,
19
+ content_type: 'application/x-www-form-urlencoded',
20
+ grant_type: 'client_credentials',
21
+ client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
22
+ exp: 5.minutes.from_now,
23
+ jti: SecureRandom.hex(32),
24
+ kid: nil
25
+ )
26
+ @encryption_method = encryption_method
27
+ @scope = scope
28
+ @iss = iss
29
+ @sub = sub
30
+ @aud = aud
31
+ @content_type = content_type
32
+ @grant_type = grant_type
33
+ @client_assertion_type = client_assertion_type
34
+ @exp = exp
35
+ @jti = jti
36
+ @kid = kid
37
+ end
38
+
39
+ def authorization_request_headers
40
+ {
41
+ content_type:,
42
+ accept: 'application/json'
43
+ }.compact
44
+ end
45
+
46
+ def authorization_request_query_values
47
+ {
48
+ 'scope' => scope,
49
+ 'grant_type' => grant_type,
50
+ 'client_assertion_type' => client_assertion_type,
51
+ 'client_assertion' => client_assertion.to_s
52
+ }.compact
53
+ end
54
+
55
+ def client_assertion
56
+ @client_assertion ||= ClientAssertionBuilder.build(
57
+ client_auth_encryption_method: encryption_method,
58
+ iss: iss,
59
+ sub: sub,
60
+ aud: aud,
61
+ exp: exp.to_i,
62
+ jti: jti,
63
+ kid: kid
64
+ )
65
+ end
66
+
67
+ def authorization_request
68
+ uri = Addressable::URI.new
69
+ uri.query_values = authorization_request_query_values
70
+
71
+ { body: uri.query, headers: authorization_request_headers }
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,40 @@
1
+ require_relative 'backend_services_authorization_request_builder'
2
+ require_relative 'backend_services_authorization_group'
3
+
4
+ module SMARTAppLaunch
5
+ class BackendServicesAuthorizationRequestSuccessTest < Inferno::Test
6
+ id :smart_backend_services_auth_request_success
7
+ title 'Authorization request succeeds when supplied correct information'
8
+ description <<~DESCRIPTION
9
+ The [SMART App Launch 2.0.0 IG specification for Backend Services](https://hl7.org/fhir/smart-app-launch/STU2/backend-services.html#issue-access-token)
10
+ states "If the access token request is valid and authorized, the authorization server SHALL issue an access token in response."
11
+ DESCRIPTION
12
+
13
+ input :client_auth_encryption_method,
14
+ :backend_services_requested_scope,
15
+ :backend_services_client_id,
16
+ :smart_token_url,
17
+ :backend_services_jwks_kid
18
+
19
+ output :authentication_response
20
+
21
+ http_client :token_endpoint do
22
+ url :smart_token_url
23
+ end
24
+
25
+ run do
26
+ post_request_content = BackendServicesAuthorizationRequestBuilder.build(encryption_method: client_auth_encryption_method,
27
+ scope: backend_services_requested_scope,
28
+ iss: backend_services_client_id,
29
+ sub: backend_services_client_id,
30
+ aud: smart_token_url,
31
+ kid: backend_services_jwks_kid)
32
+
33
+ authentication_response = post(**{ client: :token_endpoint }.merge(post_request_content))
34
+
35
+ assert_response_status([200, 201])
36
+
37
+ output authentication_response: authentication_response.response_body
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ require_relative 'backend_services_authorization_request_builder'
2
+
3
+ module SMARTAppLaunch
4
+ class BackendServicesAuthorizationResponseBodyTest < Inferno::Test
5
+ id :smart_backend_services_auth_response_body
6
+ title 'Authorization request response body contains required information encoded in JSON'
7
+ description <<~DESCRIPTION
8
+ The [SMART App Launch 2.0.0 IG specification for Backend Services](https://hl7.org/fhir/smart-app-launch/STU2/backend-services.html#issue-access-token)
9
+ states The access token response SHALL be a JSON object with the following properties:
10
+
11
+ | Token Property | Required? | Description |
12
+ | --- | --- | --- |
13
+ | `access_token` | required | The access token issued by the authorization server. |
14
+ | `token_type` | required | Fixed value: `bearer`. |
15
+ | `expires_in` | required | The lifetime in seconds of the access token. The recommended value is `300`, for a five-minute token lifetime. |
16
+ | `scope` | required | Scope of access authorized. Note that this can be different from the scopes requested by the app. |
17
+ DESCRIPTION
18
+
19
+ input :authentication_response
20
+ output :bearer_token
21
+
22
+ run do
23
+ skip_if authentication_response.blank?, 'No authentication response received.'
24
+
25
+ assert_valid_json(authentication_response)
26
+ response_body = JSON.parse(authentication_response)
27
+
28
+ access_token = response_body['access_token']
29
+ assert access_token.present?, 'Token response did not contain access_token as required'
30
+
31
+ output bearer_token: access_token
32
+
33
+ required_keys = ['token_type', 'expires_in', 'scope']
34
+
35
+ required_keys.each do |key|
36
+ assert response_body[key].present?, "Token response did not contain #{key} as required"
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'backend_services_authorization_request_builder'
2
+
3
+ module SMARTAppLaunch
4
+ class BackendServicesInvalidClientAssertionTest < Inferno::Test
5
+ id :smart_backend_services_invalid_client_assertion
6
+ title 'Authorization request fails when supplied invalid client_assertion_type'
7
+ description <<~DESCRIPTION
8
+ The [SMART App Launch 2.0.0 IG specification for Backend Services](https://hl7.org/fhir/smart-app-launch/STU2/backend-services.html#request-1)
9
+ defines the required fields for the authorization request, made via HTTP POST to authorization
10
+ token endpoint.
11
+ This includes the `client_assertion_type` parameter, where the value must be `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`.
12
+
13
+ The [OAuth 2.0 Authorization Framework Section 4.3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-4.3.3)
14
+ describes the proper response for an invalid request in the client credentials grant flow:
15
+
16
+ "If the request failed client authentication or is invalid, the authorization server returns an
17
+ error response as described in [Section 5.2](https://tools.ietf.org/html/rfc6749#section-5.2)."
18
+ DESCRIPTION
19
+
20
+ input :client_auth_encryption_method,
21
+ :backend_services_requested_scope,
22
+ :backend_services_client_id,
23
+ :smart_token_url,
24
+ :backend_services_jwks_kid
25
+
26
+ http_client :token_endpoint do
27
+ url :smart_token_url
28
+ end
29
+
30
+ run do
31
+ post_request_content = BackendServicesAuthorizationRequestBuilder.build(encryption_method: client_auth_encryption_method,
32
+ scope: backend_services_requested_scope,
33
+ iss: backend_services_client_id,
34
+ sub: backend_services_client_id,
35
+ aud: smart_token_url,
36
+ client_assertion_type: 'not_an_assertion_type',
37
+ kid: backend_services_jwks_kid)
38
+
39
+ post(**{ client: :token_endpoint }.merge(post_request_content))
40
+
41
+ assert_response_status(400)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'backend_services_authorization_request_builder'
2
+
3
+ module SMARTAppLaunch
4
+ class BackendServicesInvalidGrantTypeTest < Inferno::Test
5
+ id :smart_backend_services_invalid_grant_type
6
+ title 'Authorization request fails when client supplies invalid grant_type'
7
+ description <<~DESCRIPTION
8
+ The [SMART App Launch 2.0.0 IG section on Backend Services](https://hl7.org/fhir/smart-app-launch/STU2/backend-services.html#request-1)
9
+ defines the required fields for the authorization request, made via HTTP POST to authorization
10
+ token endpoint.
11
+ This includes the `grant_type` parameter, where the value must be `client_credentials`.
12
+
13
+ The [OAuth 2.0 Authorization Framework Section 4.3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-4.3.3)
14
+ describes the proper response for an invalid request in the client credentials grant flow:
15
+
16
+ "If the request failed client authentication or is invalid, the authorization server returns an
17
+ error response as described in [Section 5.2](https://tools.ietf.org/html/rfc6749#section-5.2)."
18
+ DESCRIPTION
19
+
20
+ input :client_auth_encryption_method,
21
+ :backend_services_requested_scope,
22
+ :backend_services_client_id,
23
+ :smart_token_url,
24
+ :backend_services_jwks_kid
25
+
26
+ http_client :token_endpoint do
27
+ url :smart_token_url
28
+ end
29
+
30
+ run do
31
+ post_request_content = BackendServicesAuthorizationRequestBuilder.build(encryption_method: client_auth_encryption_method,
32
+ scope: backend_services_requested_scope,
33
+ iss: backend_services_client_id,
34
+ sub: backend_services_client_id,
35
+ aud: smart_token_url,
36
+ grant_type: 'not_a_grant_type',
37
+ kid: backend_services_jwks_kid)
38
+
39
+ post(**{ client: :token_endpoint }.merge(post_request_content))
40
+
41
+ assert_response_status(400)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,55 @@
1
+ require_relative 'backend_services_authorization_request_builder'
2
+
3
+ module SMARTAppLaunch
4
+ class BackendServicesInvalidJWTTest < Inferno::Test
5
+ id :smart_backend_services_invalid_jwt
6
+ title 'Authorization request fails when client supplies invalid JWT token'
7
+ description <<~DESCRIPTION
8
+ The [SMART App Launch 2.0.0 IG section on Backend Services](https://hl7.org/fhir/smart-app-launch/STU2/backend-services.html#request-1)
9
+ defines the required fields for the authorization request, made via HTTP POST to authorization
10
+ token endpoint.
11
+ This includes the `client_assertion` parameter, where the value must be
12
+ a valid JWT as specified in
13
+ [Asymmetric (public key) Client Authentication](https://hl7.org/fhir/smart-app-launch/STU2/client-confidential-asymmetric.html#authenticating-to-the-token-endpoint)
14
+ The JWT SHALL include the following claims, and SHALL be signed with the client’s private key.
15
+
16
+ | JWT Claim | Required? | Description |
17
+ | --- | --- | --- |
18
+ | `iss` | required | Issuer of the JWT -- the client's `client_id`, as determined during registration with the FHIR authorization server (note that this is the same as the value for the sub claim) |
19
+ | `sub` | required | The service's `client_id`, as determined during registration with the FHIR authorization server (note that this is the same as the value for the `iss` claim) |
20
+ | `aud` | required | The FHIR authorization server's "token URL" (the same URL to which this authentication JWT will be posted) |
21
+ | `exp` | required | Expiration time integer for this authentication JWT, expressed in seconds since the "Epoch" (1970-01-01T00:00:00Z UTC). This time SHALL be no more than five minutes in the future. |
22
+ | `jti` | required | A nonce string value that uniquely identifies this authentication JWT. |
23
+
24
+ The [OAuth 2.0 Authorization Framework Section 4.3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-4.3.3)
25
+ describes the proper response for an invalid request in the client credentials grant flow:
26
+
27
+ "If the request failed client authentication or is invalid, the authorization server returns an
28
+ error response as described in [Section 5.2](https://tools.ietf.org/html/rfc6749#section-5.2)."
29
+ DESCRIPTION
30
+
31
+ input :client_auth_encryption_method,
32
+ :backend_services_requested_scope,
33
+ :backend_services_client_id,
34
+ :smart_token_url,
35
+ :backend_services_jwks_kid
36
+
37
+ http_client :token_endpoint do
38
+ url :smart_token_url
39
+ end
40
+
41
+ run do
42
+ post_request_content = BackendServicesAuthorizationRequestBuilder.build(encryption_method: client_auth_encryption_method,
43
+ scope: backend_services_requested_scope,
44
+ iss: backend_services_client_id,
45
+ sub: backend_services_client_id,
46
+ aud: smart_token_url,
47
+ client_assertion_type: 'not_an_assertion_type',
48
+ kid: backend_services_jwks_kid)
49
+
50
+ post(**{ client: :token_endpoint }.merge(post_request_content))
51
+
52
+ assert_response_status(400)
53
+ end
54
+ end
55
+ end
@@ -16,7 +16,8 @@ module SMARTAppLaunch
16
16
  :grant_type,
17
17
  :iss,
18
18
  :jti,
19
- :sub
19
+ :sub,
20
+ :kid
20
21
 
21
22
  def initialize(
22
23
  client_auth_encryption_method:,
@@ -24,7 +25,8 @@ module SMARTAppLaunch
24
25
  sub:,
25
26
  aud:,
26
27
  exp: 5.minutes.from_now.to_i,
27
- jti: SecureRandom.hex(32)
28
+ jti: SecureRandom.hex(32),
29
+ kid: nil
28
30
  )
29
31
  @client_auth_encryption_method = client_auth_encryption_method
30
32
  @iss = iss
@@ -35,29 +37,35 @@ module SMARTAppLaunch
35
37
  @client_assertion_type = client_assertion_type
36
38
  @exp = exp
37
39
  @jti = jti
40
+ @kid = kid
38
41
  end
39
42
 
40
43
  def private_key
41
- @private_key ||=
42
- JWKS.jwks
43
- .find { |key| key[:key_ops]&.include?('sign') && key[:alg] == client_auth_encryption_method }
44
+ @private_key ||= JWKS.jwks
45
+ .select { |key| key[:key_ops]&.include?('sign') }
46
+ .select { |key| key[:alg] == client_auth_encryption_method }
47
+ .find { |key| !kid || key[:kid] == kid }
44
48
  end
45
49
 
46
50
  def jwt_payload
47
51
  { iss:, sub:, aud:, exp:, jti: }.compact
48
52
  end
49
53
 
50
- def kid
51
- private_key.kid
54
+ def signing_key
55
+ private_key()
56
+ if @private_key.nil?
57
+ raise Inferno::Exceptions::AssertionException, "No signing key found for inputs: encryption method = '#{client_auth_encryption_method}' and kid = '#{kid}'"
58
+ end
59
+ return @private_key.signing_key
52
60
  end
53
61
 
54
- def signing_key
55
- private_key.signing_key
62
+ def key_id
63
+ @private_key['kid']
56
64
  end
57
65
 
58
66
  def client_assertion
59
67
  @client_assertion ||=
60
- JWT.encode jwt_payload, signing_key, client_auth_encryption_method, { alg: client_auth_encryption_method, kid:, typ: 'JWT' }
68
+ JWT.encode jwt_payload, signing_key, client_auth_encryption_method, { alg: client_auth_encryption_method, kid: key_id, typ: 'JWT' }
61
69
  end
62
70
  end
63
71
  end
@@ -8,6 +8,7 @@ require_relative 'ehr_launch_group_stu2'
8
8
  require_relative 'openid_connect_group'
9
9
  require_relative 'token_introspection_group'
10
10
  require_relative 'token_refresh_group'
11
+ require_relative 'backend_services_authorization_group'
11
12
 
12
13
  module SMARTAppLaunch
13
14
  class SMARTSTU2Suite < Inferno::TestSuite
@@ -220,6 +221,23 @@ module SMARTAppLaunch
220
221
  }
221
222
  end
222
223
 
224
+ group do
225
+ title 'Backend Services'
226
+ id :smart_backend_services
227
+
228
+ input_instructions <<~INSTRUCTIONS
229
+ Please register the Inferno client with the authorization services with the
230
+ following JWK Set URL:
231
+
232
+ * `#{Inferno::Application[:base_url]}/custom/smart_stu2/.well-known/jwks.json`
233
+ INSTRUCTIONS
234
+
235
+ run_as_group
236
+
237
+ group from: :smart_discovery_stu2
238
+ group from: :backend_services_authorization
239
+ end
240
+
223
241
  group from: :smart_token_introspection
224
242
 
225
243
  end
@@ -14,21 +14,21 @@ module SMARTAppLaunch
14
14
  id :smart_token_exchange_stu2
15
15
 
16
16
  input :client_auth_encryption_method,
17
- title: 'Encryption Method (Confidential Asymmetric Client Auth Only)',
18
- type: 'radio',
19
- default: 'ES384',
20
- options: {
21
- list_options: [
22
- {
23
- label: 'ES384',
24
- value: 'ES384'
25
- },
26
- {
27
- label: 'RS384',
28
- value: 'RS384'
29
- }
30
- ]
17
+ title: 'Encryption Method (Confidential Asymmetric Client Auth Only)',
18
+ type: 'radio',
19
+ default: 'ES384',
20
+ options: {
21
+ list_options: [
22
+ {
23
+ label: 'ES384',
24
+ value: 'ES384'
25
+ },
26
+ {
27
+ label: 'RS384',
28
+ value: 'RS384'
31
29
  }
30
+ ]
31
+ }
32
32
 
33
33
  input :client_auth_type,
34
34
  title: 'Client Authentication Method',
@@ -1,3 +1,3 @@
1
1
  module SMARTAppLaunch
2
- VERSION = '0.4.0'.freeze
2
+ VERSION = '0.4.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_app_launch_test_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen MacVicar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-08 00:00:00.000000000 Z
11
+ date: 2024-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inferno_core
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.4.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: json-jwt
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.15.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.15.3
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: jwt
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -134,6 +148,13 @@ files:
134
148
  - lib/smart_app_launch/app_launch_test.rb
135
149
  - lib/smart_app_launch/app_redirect_test.rb
136
150
  - lib/smart_app_launch/app_redirect_test_stu2.rb
151
+ - lib/smart_app_launch/backend_services_authorization_group.rb
152
+ - lib/smart_app_launch/backend_services_authorization_request_builder.rb
153
+ - lib/smart_app_launch/backend_services_authorization_request_success_test.rb
154
+ - lib/smart_app_launch/backend_services_authorization_response_body_test.rb
155
+ - lib/smart_app_launch/backend_services_invalid_client_assertion_test.rb
156
+ - lib/smart_app_launch/backend_services_invalid_grant_type_test.rb
157
+ - lib/smart_app_launch/backend_services_invalid_jwt_test.rb
137
158
  - lib/smart_app_launch/client_assertion_builder.rb
138
159
  - lib/smart_app_launch/code_received_test.rb
139
160
  - lib/smart_app_launch/discovery_stu1_group.rb