torii-backend 0.0.2

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.
Files changed (30) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +120 -0
  3. data/spec/server-v1.json +1 -0
  4. data/src/torii/backend/auth.rb +28 -0
  5. data/src/torii/backend/authenticate_request.rb +56 -0
  6. data/src/torii/backend/client.rb +232 -0
  7. data/src/torii/backend/errors.rb +34 -0
  8. data/src/torii/backend/generated/lib/torii-backend-generated/api/server_sessions_api.rb +217 -0
  9. data/src/torii/backend/generated/lib/torii-backend-generated/api/server_users_api.rb +486 -0
  10. data/src/torii/backend/generated/lib/torii-backend-generated/api_client.rb +396 -0
  11. data/src/torii/backend/generated/lib/torii-backend-generated/api_error.rb +58 -0
  12. data/src/torii/backend/generated/lib/torii-backend-generated/api_model_base.rb +88 -0
  13. data/src/torii/backend/generated/lib/torii-backend-generated/configuration.rb +301 -0
  14. data/src/torii/backend/generated/lib/torii-backend-generated/models/create_user_request.rb +205 -0
  15. data/src/torii/backend/generated/lib/torii-backend-generated/models/cursor_page_response_user_response.rb +206 -0
  16. data/src/torii/backend/generated/lib/torii-backend-generated/models/problem_detail.rb +194 -0
  17. data/src/torii/backend/generated/lib/torii-backend-generated/models/server_user_search_request.rb +217 -0
  18. data/src/torii/backend/generated/lib/torii-backend-generated/models/update_user_request.rb +228 -0
  19. data/src/torii/backend/generated/lib/torii-backend-generated/models/user_response.rb +387 -0
  20. data/src/torii/backend/generated/lib/torii-backend-generated/models/user_session_response.rb +323 -0
  21. data/src/torii/backend/generated/lib/torii-backend-generated/version.rb +15 -0
  22. data/src/torii/backend/generated/lib/torii-backend-generated.rb +49 -0
  23. data/src/torii/backend/patch.rb +23 -0
  24. data/src/torii/backend/rack.rb +69 -0
  25. data/src/torii/backend/verify.rb +162 -0
  26. data/src/torii/backend/version.rb +7 -0
  27. data/src/torii/backend/webhook.rb +19 -0
  28. data/src/torii/backend.rb +22 -0
  29. data/src/torii-backend-generated.rb +26 -0
  30. metadata +163 -0
@@ -0,0 +1,15 @@
1
+ =begin
2
+ #OpenAPI definition
3
+
4
+ #No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
5
+
6
+ The version of the OpenAPI document: v0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.22.0
10
+
11
+ =end
12
+
13
+ module ToriiBackendGenerated
14
+ VERSION = '1.0.0'
15
+ end
@@ -0,0 +1,49 @@
1
+ =begin
2
+ #OpenAPI definition
3
+
4
+ #No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
5
+
6
+ The version of the OpenAPI document: v0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.22.0
10
+
11
+ =end
12
+
13
+ # Common files
14
+ require 'torii-backend-generated/api_client'
15
+ require 'torii-backend-generated/api_error'
16
+ require 'torii-backend-generated/api_model_base'
17
+ require 'torii-backend-generated/version'
18
+ require 'torii-backend-generated/configuration'
19
+
20
+ # Models
21
+ require 'torii-backend-generated/models/create_user_request'
22
+ require 'torii-backend-generated/models/cursor_page_response_user_response'
23
+ require 'torii-backend-generated/models/problem_detail'
24
+ require 'torii-backend-generated/models/server_user_search_request'
25
+ require 'torii-backend-generated/models/update_user_request'
26
+ require 'torii-backend-generated/models/user_response'
27
+ require 'torii-backend-generated/models/user_session_response'
28
+
29
+ # APIs
30
+ require 'torii-backend-generated/api/server_sessions_api'
31
+ require 'torii-backend-generated/api/server_users_api'
32
+
33
+ module ToriiBackendGenerated
34
+ class << self
35
+ # Customize default settings for the SDK using block.
36
+ # ToriiBackendGenerated.configure do |config|
37
+ # config.username = "xxx"
38
+ # config.password = "xxx"
39
+ # end
40
+ # If no block given, return the default Configuration object.
41
+ def configure
42
+ if block_given?
43
+ yield(Configuration.default)
44
+ else
45
+ Configuration.default
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Torii
4
+ module Backend
5
+ # Tri-state wrapper for PATCH body fields. Mirrors the server-side
6
+ # Kotlin PatchValue<T> (Included + NotIncluded; Included(nil) clears).
7
+ #
8
+ # - Patch.set(value) with a non-nil value -> server updates field
9
+ # - Patch.set(nil) -> server clears field (JSON null)
10
+ # - omit the kwarg entirely -> server leaves field unchanged
11
+ class Patch
12
+ attr_reader :value
13
+
14
+ def initialize(value)
15
+ @value = value
16
+ end
17
+
18
+ def self.set(value)
19
+ new(value)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ require_relative 'authenticate_request'
6
+ require_relative 'errors'
7
+
8
+ module Torii
9
+ module Backend
10
+ # Rack middleware. Rails-compatible — mount with
11
+ #
12
+ # config.middleware.use Torii::Backend::Rack::RequireAuth,
13
+ # issuer: 'https://acme.torii.so'
14
+ #
15
+ # On success the verified +Torii::Backend::Auth+ is placed at
16
+ # +env['torii.auth']+ before the rest of the stack runs. On failure
17
+ # the middleware short-circuits with a 401 JSON body matching the
18
+ # shape used by Node/Python SDKs:
19
+ #
20
+ # { "error": { "code": "authentication_failed", "message": "..." } }
21
+ module Rack
22
+ class RequireAuth
23
+ # @param app [#call] the inner Rack app.
24
+ # @param issuer [String] required — the per-tenant issuer URL.
25
+ # @param audience [String, Array<String>, nil] optional +aud+ to
26
+ # enforce.
27
+ # @param leeway [Integer] clock-skew tolerance in seconds.
28
+ # @param header [String] which incoming header to read the bearer
29
+ # token from. Defaults to the Rack-canonical
30
+ # +HTTP_AUTHORIZATION+; pass a friendlier name like
31
+ # +"authorization"+ if you prefer.
32
+ def initialize(app, issuer:, audience: nil, leeway: 30, header: 'HTTP_AUTHORIZATION')
33
+ raise ArgumentError, 'issuer is required' if !issuer.is_a?(String) || issuer.empty?
34
+
35
+ @app = app
36
+ @issuer = issuer
37
+ @audience = audience
38
+ @leeway = leeway
39
+ @header = header
40
+ end
41
+
42
+ def call(env)
43
+ auth = Torii::Backend.authenticate_request(
44
+ env,
45
+ issuer: @issuer,
46
+ audience: @audience,
47
+ leeway: @leeway,
48
+ header: @header,
49
+ )
50
+ env['torii.auth'] = auth
51
+ @app.call(env)
52
+ rescue Torii::Backend::AuthError => e
53
+ unauthorized(e.message)
54
+ end
55
+
56
+ private
57
+
58
+ def unauthorized(message)
59
+ body = JSON.generate(error: { code: 'authentication_failed', message: message })
60
+ [
61
+ 401,
62
+ { 'content-type' => 'application/json', 'content-length' => body.bytesize.to_s },
63
+ [body],
64
+ ]
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jwt'
4
+ require 'json'
5
+ require 'net/http'
6
+ require 'uri'
7
+
8
+ require_relative 'auth'
9
+ require_relative 'errors'
10
+
11
+ module Torii
12
+ module Backend
13
+ # Networkless JWT verification. The first call to +verify_token+ for a
14
+ # given issuer fetches that issuer's JWKS; subsequent calls reuse the
15
+ # cached set until the TTL expires or a kid miss forces a re-fetch.
16
+ #
17
+ # This is the core DX win behind a backend SDK — verify_token has no
18
+ # per-request round trip to torii.
19
+ module_function
20
+
21
+ # Time-to-live for the JWKS cache, in seconds. Matches the Node and
22
+ # Python SDKs (5 minutes).
23
+ JWKS_TTL_SECONDS = 300
24
+
25
+ # Internal: cached JWKS entry. +jwks+ is a JWT::JWK::Set, +fetched_at+ is
26
+ # a monotonic timestamp so cache TTL is robust against wall-clock changes.
27
+ @jwks_cache = {}
28
+ @jwks_cache_mutex = Mutex.new
29
+
30
+ class << self
31
+ attr_accessor :jwks_cache
32
+ attr_reader :jwks_cache_mutex
33
+ end
34
+
35
+ # Verify a torii-issued JWT against the issuer's JWKS.
36
+ #
37
+ # @param token [String] Compact JWS as received from the customer frontend.
38
+ # @param issuer [String] Expected issuer URL (per-tenant), e.g.
39
+ # +https://acme.torii.so+ or +https://auth.acme.com+.
40
+ # @param audience [String, Array<String>, nil] Optional +aud+ claim to
41
+ # enforce. torii doesn't set +aud+ today, so +nil+ skips the check.
42
+ # @param leeway [Integer] Clock-skew tolerance in seconds for +exp+/+nbf+.
43
+ # @return [Torii::Backend::Auth]
44
+ # @raise [Torii::Backend::AuthError] if signature, issuer, expiry, or
45
+ # required claims fail validation.
46
+ def verify_token(token, issuer:, audience: nil, leeway: 30)
47
+ raise AuthError, 'verify_token: token must be a non-empty string' if !token.is_a?(String) || token.empty?
48
+ raise AuthError, 'verify_token: issuer is required' if !issuer.is_a?(String) || issuer.empty?
49
+
50
+ jwks = jwks_for_issuer(issuer)
51
+ verify_options = {
52
+ algorithm: 'ES256',
53
+ iss: issuer,
54
+ verify_iss: true,
55
+ verify_iat: true,
56
+ leeway: leeway,
57
+ jwks: jwks,
58
+ }
59
+ if audience
60
+ verify_options[:aud] = audience
61
+ verify_options[:verify_aud] = true
62
+ end
63
+
64
+ payload, =
65
+ begin
66
+ ::JWT.decode(token, nil, true, verify_options)
67
+ rescue ::JWT::JWKError, ::JWT::DecodeError, ::JWT::VerificationError => e
68
+ # kid miss can happen after rotation; flush this issuer's cache and
69
+ # retry once before giving up.
70
+ if e.is_a?(::JWT::DecodeError) && e.message.include?('Could not find public key')
71
+ invalidate_jwks(issuer)
72
+ begin
73
+ ::JWT.decode(token, nil, true, verify_options.merge(jwks: jwks_for_issuer(issuer)))
74
+ rescue ::JWT::DecodeError => retry_err
75
+ raise AuthError.new("JWT verification failed: #{retry_err.message}", cause: retry_err)
76
+ end
77
+ else
78
+ raise AuthError.new("JWT verification failed: #{e.message}", cause: e)
79
+ end
80
+ end
81
+
82
+ user_id = payload['sub']
83
+ environment_id = payload['pid']
84
+ iss = payload['iss']
85
+ unless user_id.is_a?(String) && environment_id.is_a?(String) && iss.is_a?(String)
86
+ raise AuthError,
87
+ "JWT is missing required string claims (sub=#{!user_id.nil?}, pid=#{!environment_id.nil?}, iss=#{!iss.nil?})"
88
+ end
89
+ raise AuthError, 'JWT missing iat claim' unless payload['iat']
90
+ raise AuthError, 'JWT missing exp claim' unless payload['exp']
91
+
92
+ locale = payload['locale']
93
+ Auth.new(
94
+ user_id: user_id,
95
+ environment_id: environment_id,
96
+ issuer: iss,
97
+ email_verified: payload['email_verified'] == true,
98
+ # profile_complete defaults to true when claim is absent (mirrors Node/Python SDK).
99
+ profile_complete: payload['profile_complete'] != false,
100
+ impersonating: payload['impersonating'] == true,
101
+ locale: locale.is_a?(String) ? locale : nil,
102
+ raw: payload,
103
+ )
104
+ end
105
+
106
+ # Internal: fetch+cache the JWKS for an issuer.
107
+ def jwks_for_issuer(issuer)
108
+ normalized = issuer.sub(%r{/+\z}, '')
109
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
110
+ @jwks_cache_mutex.synchronize do
111
+ entry = @jwks_cache[normalized]
112
+ return entry[:jwks] if entry && (now - entry[:fetched_at]) < JWKS_TTL_SECONDS
113
+ end
114
+
115
+ fetched = fetch_jwks(normalized)
116
+ @jwks_cache_mutex.synchronize do
117
+ @jwks_cache[normalized] = { jwks: fetched, fetched_at: now }
118
+ end
119
+ fetched
120
+ end
121
+
122
+ # Internal: HTTP-fetch and parse the issuer's JWKS document.
123
+ def fetch_jwks(normalized_issuer)
124
+ url = URI.parse("#{normalized_issuer}/_torii/.well-known/jwks.json")
125
+ response =
126
+ begin
127
+ http = Net::HTTP.new(url.host, url.port)
128
+ http.use_ssl = (url.scheme == 'https')
129
+ http.open_timeout = 10
130
+ http.read_timeout = 10
131
+ http.request_get(url.request_uri, { 'accept' => 'application/json' })
132
+ rescue StandardError => e
133
+ raise AuthError.new("Failed to fetch JWKS from #{url}: #{e.message}", cause: e)
134
+ end
135
+
136
+ unless response.is_a?(Net::HTTPSuccess)
137
+ raise AuthError, "Failed to fetch JWKS from #{url}: HTTP #{response.code}"
138
+ end
139
+
140
+ begin
141
+ parsed = JSON.parse(response.body)
142
+ rescue JSON::ParserError => e
143
+ raise AuthError.new("JWKS at #{url} is not valid JSON: #{e.message}", cause: e)
144
+ end
145
+
146
+ ::JWT::JWK::Set.new(parsed)
147
+ end
148
+
149
+ # Internal: drop the cache entry for a specific issuer.
150
+ def invalidate_jwks(issuer)
151
+ normalized = issuer.sub(%r{/+\z}, '')
152
+ @jwks_cache_mutex.synchronize { @jwks_cache.delete(normalized) }
153
+ end
154
+
155
+ # Test-only: clear all cached JWKS. Production code should not need
156
+ # this — the cache TTL plus rotation-on-kid-miss handles real-world
157
+ # key rotation automatically.
158
+ def clear_jwks_cache_for_tests
159
+ @jwks_cache_mutex.synchronize { @jwks_cache.clear }
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Torii
4
+ module Backend
5
+ VERSION = '0.0.2'
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors'
4
+
5
+ module Torii
6
+ module Backend
7
+ module_function
8
+
9
+ # Verify an outbound torii webhook signature.
10
+ #
11
+ # WARNING: torii's outbound webhook subsystem is not yet available. This
12
+ # stub reserves the SDK surface so adopting it later won't be a breaking
13
+ # change for callers.
14
+ def verify_webhook(secret:, headers:, payload:) # rubocop:disable Lint/UnusedMethodArgument
15
+ raise AuthError,
16
+ "verifyWebhook: torii's outbound webhook subsystem is not yet available."
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Public entry point for torii-backend. Requires lazy-load all
4
+ # sub-modules — load order matters only to keep cycles out, not for
5
+ # correctness, since each sub-module +require_relative+s its own
6
+ # dependencies.
7
+
8
+ require_relative 'backend/version'
9
+ require_relative 'backend/errors'
10
+ require_relative 'backend/auth'
11
+ require_relative 'backend/verify'
12
+ require_relative 'backend/authenticate_request'
13
+ require_relative 'backend/webhook'
14
+ require_relative 'backend/patch'
15
+ require_relative 'backend/client'
16
+ require_relative 'backend/rack'
17
+
18
+ module Torii
19
+ # Backend SDK for torii. See {https://torii.so torii.so} for documentation.
20
+ module Backend
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Bridge shim: the openapi-generator output is vendored under
4
+ # +lib/torii/backend/generated/lib+ to keep it isolated from
5
+ # hand-written code. We add that directory to +$LOAD_PATH+ here and
6
+ # then load the generated entry point so callers can simply
7
+ # +require 'torii-backend-generated'+ from anywhere in the gem.
8
+
9
+ generated_root = File.expand_path('torii/backend/generated/lib', __dir__)
10
+ $LOAD_PATH.unshift(generated_root) unless $LOAD_PATH.include?(generated_root)
11
+
12
+ require 'torii-backend-generated/api_client'
13
+ require 'torii-backend-generated/api_error'
14
+ require 'torii-backend-generated/api_model_base'
15
+ require 'torii-backend-generated/version'
16
+ require 'torii-backend-generated/configuration'
17
+
18
+ require 'torii-backend-generated/models/create_user_request'
19
+ require 'torii-backend-generated/models/cursor_page_response_user_response'
20
+ require 'torii-backend-generated/models/server_user_search_request'
21
+ require 'torii-backend-generated/models/update_user_request'
22
+ require 'torii-backend-generated/models/user_response'
23
+ require 'torii-backend-generated/models/user_session_response'
24
+
25
+ require 'torii-backend-generated/api/server_sessions_api'
26
+ require 'torii-backend-generated/api/server_users_api'
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: torii-backend
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - torii
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-05-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jwt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: typhoeus
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '13.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '13.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.13'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.13'
83
+ - !ruby/object:Gem::Dependency
84
+ name: webrick
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.8'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.8'
97
+ description: |
98
+ Backend SDK for torii. Verify end-user JWTs without a per-request
99
+ round-trip, call /api/server/v1/** with a secret key, and react to
100
+ events from torii. Ships with Rack middleware that works with Rails,
101
+ Sinatra, Roda, and anything else Rack-compatible.
102
+ email:
103
+ - hello@torii.so
104
+ executables: []
105
+ extensions: []
106
+ extra_rdoc_files: []
107
+ files:
108
+ - README.md
109
+ - spec/server-v1.json
110
+ - src/torii-backend-generated.rb
111
+ - src/torii/backend.rb
112
+ - src/torii/backend/auth.rb
113
+ - src/torii/backend/authenticate_request.rb
114
+ - src/torii/backend/client.rb
115
+ - src/torii/backend/errors.rb
116
+ - src/torii/backend/generated/lib/torii-backend-generated.rb
117
+ - src/torii/backend/generated/lib/torii-backend-generated/api/server_sessions_api.rb
118
+ - src/torii/backend/generated/lib/torii-backend-generated/api/server_users_api.rb
119
+ - src/torii/backend/generated/lib/torii-backend-generated/api_client.rb
120
+ - src/torii/backend/generated/lib/torii-backend-generated/api_error.rb
121
+ - src/torii/backend/generated/lib/torii-backend-generated/api_model_base.rb
122
+ - src/torii/backend/generated/lib/torii-backend-generated/configuration.rb
123
+ - src/torii/backend/generated/lib/torii-backend-generated/models/create_user_request.rb
124
+ - src/torii/backend/generated/lib/torii-backend-generated/models/cursor_page_response_user_response.rb
125
+ - src/torii/backend/generated/lib/torii-backend-generated/models/problem_detail.rb
126
+ - src/torii/backend/generated/lib/torii-backend-generated/models/server_user_search_request.rb
127
+ - src/torii/backend/generated/lib/torii-backend-generated/models/update_user_request.rb
128
+ - src/torii/backend/generated/lib/torii-backend-generated/models/user_response.rb
129
+ - src/torii/backend/generated/lib/torii-backend-generated/models/user_session_response.rb
130
+ - src/torii/backend/generated/lib/torii-backend-generated/version.rb
131
+ - src/torii/backend/patch.rb
132
+ - src/torii/backend/rack.rb
133
+ - src/torii/backend/verify.rb
134
+ - src/torii/backend/version.rb
135
+ - src/torii/backend/webhook.rb
136
+ homepage: https://github.com/Torii-ApS/torii-sdk-ruby
137
+ licenses:
138
+ - MIT
139
+ metadata:
140
+ homepage_uri: https://github.com/Torii-ApS/torii-sdk-ruby
141
+ source_code_uri: https://github.com/Torii-ApS/torii-sdk-ruby
142
+ bug_tracker_uri: https://github.com/Torii-ApS/torii-sdk-ruby/issues
143
+ rubygems_mfa_required: 'true'
144
+ post_install_message:
145
+ rdoc_options: []
146
+ require_paths:
147
+ - src
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '3.1'
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ requirements: []
159
+ rubygems_version: 3.3.27
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: Backend SDK for torii — verify JWTs and call the server API.
163
+ test_files: []