omniauth_openid_federation 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +16 -0
- data/LICENSE.md +22 -0
- data/README.md +822 -0
- data/SECURITY.md +129 -0
- data/examples/README_INTEGRATION_TESTING.md +399 -0
- data/examples/README_MOCK_OP.md +243 -0
- data/examples/app/controllers/users/omniauth_callbacks_controller.rb.example +33 -0
- data/examples/app/jobs/jwks_rotation_job.rb.example +60 -0
- data/examples/app/models/user.rb.example +39 -0
- data/examples/config/initializers/devise.rb.example +97 -0
- data/examples/config/initializers/federation_endpoint.rb.example +206 -0
- data/examples/config/mock_op.yml.example +83 -0
- data/examples/config/open_id_connect_config.rb.example +210 -0
- data/examples/config/routes.rb.example +12 -0
- data/examples/db/migrate/add_omniauth_to_users.rb.example +16 -0
- data/examples/integration_test_flow.rb +1334 -0
- data/examples/jobs/README.md +194 -0
- data/examples/jobs/federation_cache_refresh_job.rb.example +78 -0
- data/examples/jobs/federation_files_generation_job.rb.example +87 -0
- data/examples/mock_op_server.rb +775 -0
- data/examples/mock_rp_server.rb +435 -0
- data/lib/omniauth_openid_federation/access_token.rb +504 -0
- data/lib/omniauth_openid_federation/cache.rb +39 -0
- data/lib/omniauth_openid_federation/cache_adapter.rb +173 -0
- data/lib/omniauth_openid_federation/configuration.rb +135 -0
- data/lib/omniauth_openid_federation/constants.rb +13 -0
- data/lib/omniauth_openid_federation/endpoint_resolver.rb +168 -0
- data/lib/omniauth_openid_federation/entity_statement_reader.rb +122 -0
- data/lib/omniauth_openid_federation/errors.rb +52 -0
- data/lib/omniauth_openid_federation/federation/entity_statement.rb +331 -0
- data/lib/omniauth_openid_federation/federation/entity_statement_builder.rb +188 -0
- data/lib/omniauth_openid_federation/federation/entity_statement_fetcher.rb +142 -0
- data/lib/omniauth_openid_federation/federation/entity_statement_helper.rb +87 -0
- data/lib/omniauth_openid_federation/federation/entity_statement_parser.rb +198 -0
- data/lib/omniauth_openid_federation/federation/entity_statement_validator.rb +502 -0
- data/lib/omniauth_openid_federation/federation/metadata_policy_merger.rb +276 -0
- data/lib/omniauth_openid_federation/federation/signed_jwks.rb +210 -0
- data/lib/omniauth_openid_federation/federation/trust_chain_resolver.rb +225 -0
- data/lib/omniauth_openid_federation/federation_endpoint.rb +949 -0
- data/lib/omniauth_openid_federation/http_client.rb +70 -0
- data/lib/omniauth_openid_federation/instrumentation.rb +383 -0
- data/lib/omniauth_openid_federation/jwks/cache.rb +76 -0
- data/lib/omniauth_openid_federation/jwks/decode.rb +174 -0
- data/lib/omniauth_openid_federation/jwks/fetch.rb +153 -0
- data/lib/omniauth_openid_federation/jwks/normalizer.rb +49 -0
- data/lib/omniauth_openid_federation/jwks/rotate.rb +97 -0
- data/lib/omniauth_openid_federation/jwks/selector.rb +101 -0
- data/lib/omniauth_openid_federation/jws.rb +416 -0
- data/lib/omniauth_openid_federation/key_extractor.rb +173 -0
- data/lib/omniauth_openid_federation/logger.rb +99 -0
- data/lib/omniauth_openid_federation/rack_endpoint.rb +187 -0
- data/lib/omniauth_openid_federation/railtie.rb +29 -0
- data/lib/omniauth_openid_federation/rate_limiter.rb +55 -0
- data/lib/omniauth_openid_federation/strategy.rb +2029 -0
- data/lib/omniauth_openid_federation/string_helpers.rb +30 -0
- data/lib/omniauth_openid_federation/tasks_helper.rb +428 -0
- data/lib/omniauth_openid_federation/utils.rb +166 -0
- data/lib/omniauth_openid_federation/validators.rb +126 -0
- data/lib/omniauth_openid_federation/version.rb +3 -0
- data/lib/omniauth_openid_federation.rb +98 -0
- data/lib/tasks/omniauth_openid_federation.rake +376 -0
- data/sig/federation.rbs +218 -0
- data/sig/jwks.rbs +63 -0
- data/sig/omniauth_openid_federation.rbs +254 -0
- data/sig/strategy.rbs +60 -0
- metadata +352 -0
data/sig/federation.rbs
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
module OmniauthOpenidFederation
|
|
2
|
+
module Federation
|
|
3
|
+
class EntityStatement
|
|
4
|
+
attr_reader entity_statement: String
|
|
5
|
+
attr_reader fingerprint: String
|
|
6
|
+
attr_reader metadata: Hash[Symbol, untyped]?
|
|
7
|
+
|
|
8
|
+
def initialize: (String entity_statement_content, ?fingerprint: String?) -> void
|
|
9
|
+
|
|
10
|
+
def self.fetch_from_issuer!: (
|
|
11
|
+
String | URI issuer_uri,
|
|
12
|
+
?entity_statement_endpoint: String?,
|
|
13
|
+
?fingerprint: String?,
|
|
14
|
+
?previous_statement: untyped,
|
|
15
|
+
?timeout: Integer
|
|
16
|
+
) -> EntityStatement
|
|
17
|
+
|
|
18
|
+
def self.fetch!: (
|
|
19
|
+
String url,
|
|
20
|
+
?fingerprint: String?,
|
|
21
|
+
?previous_statement: untyped,
|
|
22
|
+
?timeout: Integer
|
|
23
|
+
) -> EntityStatement
|
|
24
|
+
|
|
25
|
+
def calculate_fingerprint: () -> String
|
|
26
|
+
def validate_fingerprint: (String expected_fingerprint) -> bool
|
|
27
|
+
def validate_against_previous: (untyped previous_statement) -> bool
|
|
28
|
+
def parse: () -> Hash[Symbol, untyped]
|
|
29
|
+
def save_to_file: (String file_path) -> void
|
|
30
|
+
def decode_payload: () -> Hash[String, untyped]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module EntityStatementHelper
|
|
34
|
+
def self.parse_for_signed_jwks: (String entity_statement_path) -> Hash[Symbol, untyped]?
|
|
35
|
+
def self.parse_for_signed_jwks_from_content: (String entity_statement_content) -> Hash[Symbol, untyped]?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class EntityStatementParser
|
|
39
|
+
def self.parse: (
|
|
40
|
+
String jwt_string,
|
|
41
|
+
?validate_signature: bool,
|
|
42
|
+
?validate_full: bool,
|
|
43
|
+
?issuer_entity_configuration: untyped
|
|
44
|
+
) -> Hash[Symbol, untyped]
|
|
45
|
+
|
|
46
|
+
def initialize: (
|
|
47
|
+
String jwt_string,
|
|
48
|
+
?validate_signature: bool,
|
|
49
|
+
?validate_full: bool,
|
|
50
|
+
?issuer_entity_configuration: untyped
|
|
51
|
+
) -> void
|
|
52
|
+
|
|
53
|
+
def parse: () -> Hash[Symbol, untyped]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class EntityStatementValidator
|
|
57
|
+
def initialize: (
|
|
58
|
+
jwt_string: String,
|
|
59
|
+
?issuer_entity_configuration: untyped,
|
|
60
|
+
?clock_skew_tolerance: Integer?
|
|
61
|
+
) -> void
|
|
62
|
+
|
|
63
|
+
def validate!: () -> void
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class EntityStatementBuilder
|
|
67
|
+
def initialize: (
|
|
68
|
+
issuer: String,
|
|
69
|
+
subject: String,
|
|
70
|
+
private_key: untyped,
|
|
71
|
+
jwks: Hash[String, untyped],
|
|
72
|
+
metadata: Hash[String, untyped],
|
|
73
|
+
?expiration_seconds: Integer,
|
|
74
|
+
?kid: String?,
|
|
75
|
+
?authority_hints: Array[String]?,
|
|
76
|
+
?trust_marks: Array[Hash[String, untyped]]?,
|
|
77
|
+
?trust_mark_issuers: Hash[String, untyped]?,
|
|
78
|
+
?trust_mark_owners: Hash[String, untyped]?,
|
|
79
|
+
?metadata_policy: Hash[String, untyped]?,
|
|
80
|
+
?metadata_policy_crit: Array[String]?,
|
|
81
|
+
?constraints: Hash[String, untyped]?,
|
|
82
|
+
?source_endpoint: String?,
|
|
83
|
+
?crit: Array[String]?
|
|
84
|
+
) -> void
|
|
85
|
+
|
|
86
|
+
def build: () -> String
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class SignedJWKS
|
|
90
|
+
def self.fetch!: (
|
|
91
|
+
String signed_jwks_uri,
|
|
92
|
+
untyped entity_jwks,
|
|
93
|
+
?cache_key: String?,
|
|
94
|
+
?cache_ttl: Integer?,
|
|
95
|
+
?force_refresh: bool
|
|
96
|
+
) -> Hash[String, untyped]
|
|
97
|
+
|
|
98
|
+
def initialize: (String signed_jwks_uri, untyped entity_jwks) -> void
|
|
99
|
+
def fetch_and_validate: () -> Hash[String, untyped]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
class TrustChainResolver
|
|
103
|
+
def initialize: (
|
|
104
|
+
leaf_entity_id: String,
|
|
105
|
+
trust_anchors: Array[Hash[Symbol, untyped]],
|
|
106
|
+
?max_chain_length: Integer,
|
|
107
|
+
?timeout: Integer
|
|
108
|
+
) -> void
|
|
109
|
+
|
|
110
|
+
def resolve!: () -> Array[Hash[Symbol, untyped]]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
class MetadataPolicyMerger
|
|
114
|
+
def initialize: (trust_chain: Array[Hash[Symbol, untyped]]) -> void
|
|
115
|
+
def merge_policies: () -> Hash[String, untyped]
|
|
116
|
+
def apply_policies: (Hash[String, untyped] entity_metadata) -> Hash[String, untyped]
|
|
117
|
+
def merge_and_apply: (Hash[String, untyped] entity_metadata) -> Hash[String, untyped]
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class FederationEndpoint
|
|
122
|
+
def self.configure: () { (FederationEndpoint::Configuration) -> void } -> FederationEndpoint::Configuration
|
|
123
|
+
def self.auto_configure: (
|
|
124
|
+
issuer: String,
|
|
125
|
+
?signing_key: untyped,
|
|
126
|
+
?encryption_key: untyped,
|
|
127
|
+
?private_key: untyped,
|
|
128
|
+
?jwks: Hash[String, untyped]?,
|
|
129
|
+
?subject: String?,
|
|
130
|
+
?entity_statement_path: String?,
|
|
131
|
+
?entity_statement_url: String?,
|
|
132
|
+
?metadata: Hash[String, untyped]?,
|
|
133
|
+
?expiration_seconds: Integer?,
|
|
134
|
+
?jwks_cache_ttl: Integer?,
|
|
135
|
+
?auto_provision_keys: bool,
|
|
136
|
+
?key_rotation_period: Integer?
|
|
137
|
+
) -> FederationEndpoint::Configuration
|
|
138
|
+
|
|
139
|
+
def self.provision_jwks: (
|
|
140
|
+
?signing_key: untyped,
|
|
141
|
+
?encryption_key: untyped,
|
|
142
|
+
?private_key: untyped,
|
|
143
|
+
?entity_statement_path: String?,
|
|
144
|
+
?issuer: String?,
|
|
145
|
+
?subject: String?,
|
|
146
|
+
?metadata: Hash[String, untyped]?,
|
|
147
|
+
?entity_statement_path_provided: bool
|
|
148
|
+
) -> Hash[String, untyped]?
|
|
149
|
+
|
|
150
|
+
def self.configuration: () -> FederationEndpoint::Configuration
|
|
151
|
+
def self.generate_entity_statement: () -> String
|
|
152
|
+
def self.generate_signed_jwks: () -> String
|
|
153
|
+
def self.current_jwks: () -> Hash[String, untyped]
|
|
154
|
+
def self.rack_app: () -> RackEndpoint
|
|
155
|
+
def self.mount_routes: (
|
|
156
|
+
untyped router,
|
|
157
|
+
?entity_statement_path: String,
|
|
158
|
+
?fetch_path: String,
|
|
159
|
+
?jwks_path: String,
|
|
160
|
+
?signed_jwks_path: String,
|
|
161
|
+
?as: Symbol
|
|
162
|
+
) -> void
|
|
163
|
+
|
|
164
|
+
def self.generate_fresh_keys: (
|
|
165
|
+
entity_statement_path: String,
|
|
166
|
+
?issuer: String?,
|
|
167
|
+
?subject: String?,
|
|
168
|
+
?metadata: Hash[String, untyped]?,
|
|
169
|
+
?keys_output_dir: String?
|
|
170
|
+
) -> Hash[String, untyped]?
|
|
171
|
+
|
|
172
|
+
def self.rotate_keys_if_needed: (FederationEndpoint::Configuration config) -> void
|
|
173
|
+
def self.ensure_jwks_endpoints: (
|
|
174
|
+
Hash[String, untyped] metadata,
|
|
175
|
+
String issuer,
|
|
176
|
+
Symbol? entity_type
|
|
177
|
+
) -> Hash[String, untyped]
|
|
178
|
+
|
|
179
|
+
def self.generate_subordinate_statement: (
|
|
180
|
+
subject_entity_id: String,
|
|
181
|
+
?subject_metadata: Hash[String, untyped]?,
|
|
182
|
+
?metadata_policy: Hash[String, untyped]?,
|
|
183
|
+
?constraints: Hash[String, untyped]?,
|
|
184
|
+
?source_endpoint: String?
|
|
185
|
+
) -> String
|
|
186
|
+
|
|
187
|
+
def self.get_subordinate_statement: (String subject_entity_id) -> String?
|
|
188
|
+
|
|
189
|
+
class Configuration
|
|
190
|
+
attr_accessor issuer: String?
|
|
191
|
+
attr_accessor subject: String?
|
|
192
|
+
attr_accessor private_key: untyped
|
|
193
|
+
attr_accessor jwks: Hash[String, untyped]?
|
|
194
|
+
attr_accessor metadata: Hash[String, untyped]?
|
|
195
|
+
attr_accessor expiration_seconds: Integer
|
|
196
|
+
attr_accessor kid: String?
|
|
197
|
+
attr_accessor entity_type: Symbol
|
|
198
|
+
attr_accessor signing_key: untyped
|
|
199
|
+
attr_accessor encryption_key: untyped
|
|
200
|
+
attr_accessor auto_provision_keys: bool
|
|
201
|
+
attr_accessor entity_statement_path: String?
|
|
202
|
+
attr_accessor key_rotation_period: Integer?
|
|
203
|
+
attr_accessor current_jwks: Hash[String, untyped]?
|
|
204
|
+
attr_accessor current_jwks_proc: Proc?
|
|
205
|
+
attr_accessor signed_jwks_payload: Hash[String, untyped]?
|
|
206
|
+
attr_accessor signed_jwks_payload_proc: Proc?
|
|
207
|
+
attr_accessor signed_jwks_expiration_seconds: Integer
|
|
208
|
+
attr_accessor signed_jwks_signing_kid: String?
|
|
209
|
+
attr_accessor jwks_cache_ttl: Integer
|
|
210
|
+
attr_accessor subordinate_statements: Hash[String, Hash[Symbol, untyped]]?
|
|
211
|
+
attr_accessor subordinate_statements_proc: Proc?
|
|
212
|
+
attr_accessor authority_hints: Array[String]?
|
|
213
|
+
|
|
214
|
+
def initialize: () -> void
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
data/sig/jwks.rbs
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module OmniauthOpenidFederation
|
|
2
|
+
module Jwks
|
|
3
|
+
module Fetch
|
|
4
|
+
def self.run: (
|
|
5
|
+
String jwks_uri,
|
|
6
|
+
?entity_statement_keys: untyped,
|
|
7
|
+
?cache_ttl: Integer?,
|
|
8
|
+
?force_refresh: bool
|
|
9
|
+
) -> Hash[String, untyped]
|
|
10
|
+
|
|
11
|
+
def self.fetch_jwks: (
|
|
12
|
+
String jwks_uri,
|
|
13
|
+
?entity_statement_keys: untyped
|
|
14
|
+
) -> Hash[String, untyped]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class Normalizer
|
|
18
|
+
def self.to_jwks_hash: (untyped jwks) -> Hash[String, Array[Hash[String, untyped]]]
|
|
19
|
+
def self.normalize_keys_array: (untyped keys) -> Hash[String, Array[Hash[String, untyped]]]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
module Decode
|
|
23
|
+
def self.run: (
|
|
24
|
+
String encoded_jwt,
|
|
25
|
+
String jwks_uri,
|
|
26
|
+
?retried: bool,
|
|
27
|
+
?entity_statement_keys: untyped,
|
|
28
|
+
&Proc[Hash[String, untyped], untyped]
|
|
29
|
+
) -> untyped
|
|
30
|
+
|
|
31
|
+
def self.jwt: (
|
|
32
|
+
String encoded_jwt,
|
|
33
|
+
String jwks_uri,
|
|
34
|
+
?retried: bool,
|
|
35
|
+
?entity_statement_keys: untyped
|
|
36
|
+
) -> Array[Hash[String, untyped]]
|
|
37
|
+
|
|
38
|
+
def self.json_jwt: (
|
|
39
|
+
String encoded_jwt,
|
|
40
|
+
String jwks_uri,
|
|
41
|
+
?retried: bool,
|
|
42
|
+
?entity_statement_keys: untyped
|
|
43
|
+
) -> untyped
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class Selector
|
|
47
|
+
def self.current_keys: (untyped jwks) -> Hash[String, Array[Hash[String, untyped]]]
|
|
48
|
+
def self.all_keys: (untyped jwks) -> Hash[String, Array[Hash[String, untyped]]]
|
|
49
|
+
def self.signing_keys: (untyped jwks) -> Array[Hash[String, untyped]]
|
|
50
|
+
def self.encryption_keys: (untyped jwks) -> Array[Hash[String, untyped]]
|
|
51
|
+
def self.key_by_kid: (untyped jwks, String kid) -> Hash[String, untyped]?
|
|
52
|
+
def self.extract_keys_array: (untyped jwks) -> Array[Hash[String, untyped]]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class Rotate
|
|
56
|
+
def self.run: (
|
|
57
|
+
String jwks_uri,
|
|
58
|
+
?entity_statement_path: String?
|
|
59
|
+
) -> Hash[String, untyped]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
module OmniauthOpenidFederation
|
|
2
|
+
VERSION: String
|
|
3
|
+
|
|
4
|
+
def self.configure: () { (Configuration) -> void } -> Configuration
|
|
5
|
+
def self.config: () -> Configuration
|
|
6
|
+
def self.rotate_jwks: (String jwks_uri, ?entity_statement_path: String?) -> Hash[String, untyped]
|
|
7
|
+
|
|
8
|
+
class Configuration
|
|
9
|
+
attr_accessor verify_ssl: bool
|
|
10
|
+
attr_accessor cache_ttl: Integer?
|
|
11
|
+
attr_accessor rotate_on_errors: bool
|
|
12
|
+
attr_accessor http_timeout: Integer
|
|
13
|
+
attr_accessor max_retries: Integer
|
|
14
|
+
attr_accessor retry_delay: Integer
|
|
15
|
+
attr_accessor http_options: Hash[Symbol, untyped] | Proc | nil
|
|
16
|
+
attr_accessor cache_adapter: untyped
|
|
17
|
+
attr_accessor root_path: String?
|
|
18
|
+
attr_accessor clock_skew_tolerance: Integer
|
|
19
|
+
attr_accessor instrumentation: Proc | untyped | nil
|
|
20
|
+
|
|
21
|
+
def self.config: () -> Configuration
|
|
22
|
+
def self.reset!: () -> void
|
|
23
|
+
def self.configure: () { (Configuration) -> void } -> Configuration
|
|
24
|
+
def initialize: () -> void
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Error < StandardError; end
|
|
28
|
+
class ConfigurationError < Error; end
|
|
29
|
+
class SecurityError < Error; end
|
|
30
|
+
class NetworkError < Error; end
|
|
31
|
+
class ValidationError < Error; end
|
|
32
|
+
class DecryptionError < SecurityError; end
|
|
33
|
+
class EncryptionError < SecurityError; end
|
|
34
|
+
class SignatureError < SecurityError; end
|
|
35
|
+
class FetchError < NetworkError; end
|
|
36
|
+
class KeyRelatedError < FetchError
|
|
37
|
+
def key_related_error?: () -> bool
|
|
38
|
+
end
|
|
39
|
+
class KeyRelatedValidationError < ValidationError
|
|
40
|
+
def key_related_error?: () -> bool
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
module Cache
|
|
44
|
+
def self.key_for_jwks: (String jwks_uri) -> String
|
|
45
|
+
def self.key_for_signed_jwks: (String signed_jwks_uri) -> String
|
|
46
|
+
def self.delete_jwks: (String jwks_uri) -> void
|
|
47
|
+
def self.delete_signed_jwks: (String signed_jwks_uri) -> void
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
module Constants
|
|
51
|
+
KEY_ROTATION_HTTP_CODES: Array[Integer]
|
|
52
|
+
REQUEST_OBJECT_EXPIRATION_SECONDS: Integer
|
|
53
|
+
MAX_RETRY_DELAY_SECONDS: Integer
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
module Utils
|
|
57
|
+
def self.to_indifferent_hash: (untyped hash) -> Hash[String, untyped] | ActiveSupport::HashWithIndifferentAccess
|
|
58
|
+
def self.sanitize_path: (String? path) -> String
|
|
59
|
+
def self.sanitize_uri: (String? uri) -> String
|
|
60
|
+
def self.build_endpoint_url: (String | URI issuer_uri, String endpoint_path) -> String
|
|
61
|
+
def self.build_entity_statement_url: (String | URI issuer_uri, ?entity_statement_endpoint: String?) -> String
|
|
62
|
+
def self.validate_file_path!: (String path, ?allowed_dirs: Array[String]?) -> String
|
|
63
|
+
def self.valid_jwt_format?: (String? str) -> bool
|
|
64
|
+
def self.extract_jwks_from_entity_statement: (String entity_statement_content) -> Hash[String, untyped]?
|
|
65
|
+
def self.rsa_key_to_jwk: (untyped key, ?use: String?) -> Hash[String, untyped]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
module RateLimiter
|
|
69
|
+
def self.allow?: (String key, ?max_requests: Integer, ?window: Integer) -> bool
|
|
70
|
+
def self.reset!: (String key) -> void
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class HttpClient
|
|
74
|
+
def self.get: (String uri, ?timeout: Integer, ?max_retries: Integer, ?retry_delay: Integer) -> untyped
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class Logger
|
|
78
|
+
def self.logger: () -> untyped
|
|
79
|
+
def self.logger=: (untyped logger) -> void
|
|
80
|
+
def self.debug: (String message) -> void
|
|
81
|
+
def self.info: (String message) -> void
|
|
82
|
+
def self.warn: (String message) -> void
|
|
83
|
+
def self.error: (String message) -> void
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class Jws
|
|
87
|
+
attr_accessor private_key: untyped
|
|
88
|
+
attr_accessor state: String?
|
|
89
|
+
attr_accessor nonce: String?
|
|
90
|
+
attr_accessor ftn_spname: String?
|
|
91
|
+
|
|
92
|
+
def initialize: (
|
|
93
|
+
client_id: String,
|
|
94
|
+
redirect_uri: String,
|
|
95
|
+
?scope: String,
|
|
96
|
+
?issuer: String?,
|
|
97
|
+
?audience: String?,
|
|
98
|
+
?state: String?,
|
|
99
|
+
?nonce: String?,
|
|
100
|
+
?response_type: String,
|
|
101
|
+
?response_mode: String?,
|
|
102
|
+
?login_hint: String?,
|
|
103
|
+
?ui_locales: String?,
|
|
104
|
+
?claims_locales: String?,
|
|
105
|
+
?prompt: String?,
|
|
106
|
+
?hd: String?,
|
|
107
|
+
?acr_values: String?,
|
|
108
|
+
?extra_params: Hash[Symbol, untyped],
|
|
109
|
+
?private_key: untyped,
|
|
110
|
+
?entity_statement_path: String?
|
|
111
|
+
) -> void
|
|
112
|
+
|
|
113
|
+
def add_claim: (Symbol key, untyped value) -> void
|
|
114
|
+
def sign: (?provider_metadata: Hash[String, untyped]?, ?always_encrypt: bool) -> String
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
class EntityStatementReader
|
|
118
|
+
def self.fetch_keys: (?entity_statement_path: String?) -> Array[untyped]
|
|
119
|
+
def self.parse_metadata: (?entity_statement_path: String?) -> Hash[Symbol, untyped]?
|
|
120
|
+
def self.validate_fingerprint: (
|
|
121
|
+
String entity_statement_content,
|
|
122
|
+
String expected_fingerprint
|
|
123
|
+
) -> bool
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class EndpointResolver
|
|
127
|
+
def self.resolve: (
|
|
128
|
+
?entity_statement_path: String?,
|
|
129
|
+
?config: Hash[Symbol, String?]
|
|
130
|
+
) -> Hash[Symbol, String?]
|
|
131
|
+
|
|
132
|
+
def self.validate_and_build_audience: (
|
|
133
|
+
Hash[Symbol, String?] endpoints,
|
|
134
|
+
?issuer_uri: URI
|
|
135
|
+
) -> Hash[Symbol, String?]
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
class KeyExtractor
|
|
139
|
+
def self.extract_signing_key: (
|
|
140
|
+
?jwks: Hash[String, untyped] | Array[Hash[String, untyped]] | nil,
|
|
141
|
+
?metadata: Hash[String, untyped]?,
|
|
142
|
+
?private_key: untyped
|
|
143
|
+
) -> untyped
|
|
144
|
+
|
|
145
|
+
def self.extract_encryption_key: (
|
|
146
|
+
?jwks: Hash[String, untyped] | Array[Hash[String, untyped]] | nil,
|
|
147
|
+
?metadata: Hash[String, untyped]?,
|
|
148
|
+
?private_key: untyped
|
|
149
|
+
) -> untyped
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
class RackEndpoint
|
|
153
|
+
def call: (Hash[String, untyped] env) -> Array[Integer, Hash[String, String], Array[String]]
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
module TasksHelper
|
|
157
|
+
def self.resolve_path: (String file_path) -> String
|
|
158
|
+
def self.fetch_entity_statement: (
|
|
159
|
+
url: String,
|
|
160
|
+
output_file: String,
|
|
161
|
+
?fingerprint: String?
|
|
162
|
+
) -> Hash[Symbol, untyped]
|
|
163
|
+
|
|
164
|
+
def self.validate_entity_statement: (
|
|
165
|
+
file_path: String,
|
|
166
|
+
?fingerprint: String?
|
|
167
|
+
) -> Hash[Symbol, untyped]
|
|
168
|
+
|
|
169
|
+
def self.parse_entity_statement: (String file_path) -> Hash[String, untyped]
|
|
170
|
+
|
|
171
|
+
def self.fetch_jwks: (
|
|
172
|
+
jwks_uri: String,
|
|
173
|
+
output_file: String
|
|
174
|
+
) -> Hash[Symbol, untyped]
|
|
175
|
+
|
|
176
|
+
def self.prepare_client_keys: (
|
|
177
|
+
?key_type: String,
|
|
178
|
+
?output_dir: String
|
|
179
|
+
) -> Hash[Symbol, untyped]
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
module StringHelpers
|
|
183
|
+
def self.present?: (untyped value) -> bool
|
|
184
|
+
def self.blank?: (untyped value) -> bool
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
module Validators
|
|
188
|
+
def self.validate_private_key!: (untyped private_key) -> void
|
|
189
|
+
def self.normalize_hash: (untyped hash) -> Hash[Symbol, untyped]
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
module Instrumentation
|
|
193
|
+
EVENT_CSRF_DETECTED: String
|
|
194
|
+
EVENT_SIGNATURE_VERIFICATION_FAILED: String
|
|
195
|
+
EVENT_DECRYPTION_FAILED: String
|
|
196
|
+
EVENT_TOKEN_VALIDATION_FAILED: String
|
|
197
|
+
EVENT_KEY_ROTATION_DETECTED: String
|
|
198
|
+
EVENT_KID_NOT_FOUND: String
|
|
199
|
+
EVENT_ENTITY_STATEMENT_VALIDATION_FAILED: String
|
|
200
|
+
EVENT_FINGERPRINT_MISMATCH: String
|
|
201
|
+
EVENT_TRUST_CHAIN_VALIDATION_FAILED: String
|
|
202
|
+
EVENT_ENDPOINT_MISMATCH: String
|
|
203
|
+
EVENT_UNEXPECTED_AUTHENTICATION_BREAK: String
|
|
204
|
+
EVENT_STATE_MISMATCH: String
|
|
205
|
+
EVENT_MISSING_REQUIRED_CLAIMS: String
|
|
206
|
+
EVENT_AUDIENCE_MISMATCH: String
|
|
207
|
+
EVENT_ISSUER_MISMATCH: String
|
|
208
|
+
EVENT_EXPIRED_TOKEN: String
|
|
209
|
+
EVENT_INVALID_NONCE: String
|
|
210
|
+
|
|
211
|
+
def self.notify: (
|
|
212
|
+
String event,
|
|
213
|
+
?data: Hash[Symbol, untyped],
|
|
214
|
+
?severity: Symbol
|
|
215
|
+
) -> void
|
|
216
|
+
|
|
217
|
+
def self.notify_csrf_detected: (?Hash[Symbol, untyped] data) -> void
|
|
218
|
+
def self.notify_signature_verification_failed: (?Hash[Symbol, untyped] data) -> void
|
|
219
|
+
def self.notify_decryption_failed: (?Hash[Symbol, untyped] data) -> void
|
|
220
|
+
def self.notify_token_validation_failed: (?Hash[Symbol, untyped] data) -> void
|
|
221
|
+
def self.notify_key_rotation_detected: (?Hash[Symbol, untyped] data) -> void
|
|
222
|
+
def self.notify_kid_not_found: (?Hash[Symbol, untyped] data) -> void
|
|
223
|
+
def self.notify_entity_statement_validation_failed: (?Hash[Symbol, untyped] data) -> void
|
|
224
|
+
def self.notify_fingerprint_mismatch: (?Hash[Symbol, untyped] data) -> void
|
|
225
|
+
def self.notify_trust_chain_validation_failed: (?Hash[Symbol, untyped] data) -> void
|
|
226
|
+
def self.notify_endpoint_mismatch: (?Hash[Symbol, untyped] data) -> void
|
|
227
|
+
def self.notify_unexpected_authentication_break: (?Hash[Symbol, untyped] data) -> void
|
|
228
|
+
def self.notify_state_mismatch: (?Hash[Symbol, untyped] data) -> void
|
|
229
|
+
def self.notify_missing_required_claims: (?Hash[Symbol, untyped] data) -> void
|
|
230
|
+
def self.notify_audience_mismatch: (?Hash[Symbol, untyped] data) -> void
|
|
231
|
+
def self.notify_issuer_mismatch: (?Hash[Symbol, untyped] data) -> void
|
|
232
|
+
def self.notify_expired_token: (?Hash[Symbol, untyped] data) -> void
|
|
233
|
+
def self.notify_invalid_nonce: (?Hash[Symbol, untyped] data) -> void
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
class CacheAdapter
|
|
237
|
+
def self.available?: () -> bool
|
|
238
|
+
def self.get: (String key) -> untyped
|
|
239
|
+
def self.set: (String key, untyped value, ?ttl: Integer) -> void
|
|
240
|
+
def self.delete: (String key) -> void
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
module Jwks
|
|
244
|
+
class Cache
|
|
245
|
+
attr_reader jwks_source: untyped
|
|
246
|
+
attr_reader timeout_sec: Integer
|
|
247
|
+
attr_reader cache_last_update: Integer
|
|
248
|
+
|
|
249
|
+
def initialize: (untyped jwks_source, ?timeout_sec: Integer) -> void
|
|
250
|
+
def call: (?Hash[Symbol, untyped] options) -> Array[Hash[String, untyped]]
|
|
251
|
+
def clear!: () -> void
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
data/sig/strategy.rbs
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module OmniAuth
|
|
2
|
+
module Strategies
|
|
3
|
+
class OpenIDFederation < OmniAuth::Strategies::OAuth2
|
|
4
|
+
def client: () -> untyped
|
|
5
|
+
def oidc_client: () -> untyped
|
|
6
|
+
def request_phase: () -> untyped
|
|
7
|
+
def callback_phase: () -> untyped
|
|
8
|
+
def auth_hash: () -> OmniAuth::AuthHash
|
|
9
|
+
def authorize_uri: () -> String
|
|
10
|
+
def raw_info: () -> Hash[String, untyped]
|
|
11
|
+
def client_jwk_signing_key: () -> untyped
|
|
12
|
+
def options: () -> untyped
|
|
13
|
+
def exchange_authorization_code: (String authorization_code) -> untyped
|
|
14
|
+
def new_state: () -> String
|
|
15
|
+
def new_nonce: () -> String
|
|
16
|
+
def resolve_endpoints_from_metadata: (Hash[Symbol, untyped] client_options_hash) -> Hash[Symbol, String?]
|
|
17
|
+
def resolve_issuer_from_metadata: () -> String?
|
|
18
|
+
def resolve_audience: (Hash[Symbol, untyped] client_options_hash, String? resolved_issuer) -> String
|
|
19
|
+
def resolve_jwks_for_validation: (Hash[Symbol, untyped] normalized_options) -> Hash[String, untyped]
|
|
20
|
+
def resolve_jwks_for_validation_with_kid: (Hash[Symbol, untyped] normalized_options, String kid) -> Hash[String, untyped]
|
|
21
|
+
def resolve_jwks_uri: (Hash[Symbol, untyped] normalized_options) -> String?
|
|
22
|
+
def build_base_url: (Hash[Symbol, untyped] client_options_hash) -> String
|
|
23
|
+
def build_endpoint: (String base_url, String path) -> String
|
|
24
|
+
def decode_id_token: (String id_token) -> Hash[String, untyped]
|
|
25
|
+
def encrypted_token?: (String token) -> bool
|
|
26
|
+
def decode_userinfo: (untyped userinfo) -> Hash[String, untyped]
|
|
27
|
+
def load_provider_entity_statement: () -> Hash[Symbol, untyped]?
|
|
28
|
+
def fetch_and_cache_entity_statement: (String url, ?fingerprint: String?) -> Hash[Symbol, untyped]?
|
|
29
|
+
def resolve_endpoints_from_trust_chain: (String issuer_entity_id, Hash[Symbol, untyped] client_options_hash) -> Hash[Symbol, String?]
|
|
30
|
+
def extract_metadata_from_parsed: (Hash[Symbol, untyped] parsed) -> Hash[Symbol, untyped]?
|
|
31
|
+
def normalize_trust_anchors: (untyped trust_anchors) -> Array[Hash[Symbol, untyped]]
|
|
32
|
+
def is_entity_id?: (String str) -> bool
|
|
33
|
+
def resolve_entity_statement_path: (String path) -> String
|
|
34
|
+
def load_metadata_for_key_extraction: () -> Hash[Symbol, untyped]?
|
|
35
|
+
def load_client_entity_statement: (?entity_statement_path: String?, ?entity_statement_url: String?) -> Hash[Symbol, untyped]?
|
|
36
|
+
def load_client_entity_statement_from_file: (String entity_statement_path) -> Hash[Symbol, untyped]?
|
|
37
|
+
def load_client_entity_statement_from_url: (String entity_statement_url) -> Hash[Symbol, untyped]?
|
|
38
|
+
def extract_client_jwk_signing_key: () -> untyped
|
|
39
|
+
def extract_entity_identifier_from_statement: (Hash[Symbol, untyped] entity_statement, String? configured_identifier) -> String?
|
|
40
|
+
def load_provider_metadata_for_encryption: () -> Hash[String, untyped]?
|
|
41
|
+
def combine_acr_values: (?configured_acr: String?, ?request_acr: String?) -> String?
|
|
42
|
+
def normalize_acr_values: (untyped acr_values) -> String?
|
|
43
|
+
def fetch_jwks: (String jwks_uri) -> Hash[String, untyped]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
OpenidFederation: singleton(OpenIDFederation)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
module OpenIDConnect
|
|
51
|
+
class AccessToken
|
|
52
|
+
def resource_request: () { () -> untyped } -> untyped
|
|
53
|
+
def get_strategy_options: () -> Hash[Symbol, untyped]
|
|
54
|
+
def extract_encryption_key_for_decryption: () -> untyped
|
|
55
|
+
def fetch_signed_jwks: (Hash[Symbol, untyped] strategy_options) -> Hash[String, untyped]?
|
|
56
|
+
def load_entity_statement_keys_for_jwks_validation: (Hash[Symbol, untyped] strategy_options) -> Array[untyped]
|
|
57
|
+
def resolve_jwks_uri_from_entity_statement: (Hash[Symbol, untyped] strategy_options) -> String?
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|