standard_id 0.48.0 → 0.49.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 +4 -4
- data/CHANGELOG.md +23 -0
- data/README.md +178 -1
- data/app/controllers/concerns/standard_id/resource_server.rb +138 -0
- data/app/controllers/standard_id/api/authorization_controller.rb +1 -0
- data/app/controllers/standard_id/api/oauth/callback/providers_controller.rb +23 -0
- data/app/controllers/standard_id/api/oauth/registrations_controller.rb +99 -22
- data/app/controllers/standard_id/api/well_known/oauth_protected_resource_controller.rb +46 -0
- data/app/jobs/standard_id/cleanup_all_job.rb +4 -3
- data/app/jobs/standard_id/purge_stale_dynamic_clients_job.rb +73 -0
- data/app/models/standard_id/client_application.rb +38 -0
- data/config/routes/api.rb +9 -0
- data/db/migrate/20261020120000_add_registration_access_token_digest_to_standard_id_client_applications.rb +14 -0
- data/lib/generators/standard_id/install/install_generator.rb +2 -1
- data/lib/standard_id/config/callable_validator.rb +20 -0
- data/lib/standard_id/config/schema.rb +87 -0
- data/lib/standard_id/errors.rb +22 -0
- data/lib/standard_id/oauth/audience_resolver.rb +88 -0
- data/lib/standard_id/oauth/authorization_code_authorization_flow.rb +1 -1
- data/lib/standard_id/oauth/authorization_code_flow.rb +3 -1
- data/lib/standard_id/oauth/authorization_flow.rb +21 -1
- data/lib/standard_id/oauth/client_registration.rb +151 -23
- data/lib/standard_id/oauth/direct_mint_flow.rb +128 -0
- data/lib/standard_id/oauth/implicit_authorization_flow.rb +1 -1
- data/lib/standard_id/oauth/protected_resource_document.rb +171 -0
- data/lib/standard_id/oauth/refresh_token_flow.rb +1 -1
- data/lib/standard_id/otp.rb +9 -1
- data/lib/standard_id/passwordless/base_strategy.rb +4 -2
- data/lib/standard_id/routing.rb +21 -0
- data/lib/standard_id/token_minter.rb +74 -0
- data/lib/standard_id/version.rb +1 -1
- data/lib/standard_id.rb +4 -0
- data/lib/tasks/standard_id_tasks.rake +8 -1
- metadata +9 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module StandardId
|
|
2
|
+
# Mint an access token (and optionally a refresh token) for an account the
|
|
3
|
+
# host has already authenticated, through the same pipeline /oauth/token
|
|
4
|
+
# uses — so the claims, the audience → profile binding, the account-status
|
|
5
|
+
# guards and the OAUTH_TOKEN_ISSUING / OAUTH_TOKEN_ISSUED events are the ones
|
|
6
|
+
# every other token gets, instead of a hand-rolled JwtService.encode that
|
|
7
|
+
# re-derives the initializer's claim resolvers by hand.
|
|
8
|
+
#
|
|
9
|
+
# result = StandardId::TokenMinter.mint(
|
|
10
|
+
# account: account,
|
|
11
|
+
# audience: "harness",
|
|
12
|
+
# scopes: "profile permissions",
|
|
13
|
+
# grant_type: "harness.mint", # free-form; lands in the JWT and the audit event
|
|
14
|
+
# claims: { permissions: scopes }, # host extras; reserved keys are dropped
|
|
15
|
+
# expires_in: 60.minutes
|
|
16
|
+
# )
|
|
17
|
+
# result.access_token # the JWT
|
|
18
|
+
# result.jti # what OAUTH_TOKEN_ISSUED carried
|
|
19
|
+
#
|
|
20
|
+
# What runs, in order: audience validation (oauth.allowed_audiences),
|
|
21
|
+
# audience → profile binding (oauth.audience_profile_types, fail-closed),
|
|
22
|
+
# OAUTH_TOKEN_ISSUING (AccountStatus / AccountLocking refuse here),
|
|
23
|
+
# scope_claims + claim_resolvers and custom_claims, then the host's own
|
|
24
|
+
# +claims+, then OAUTH_TOKEN_ISSUED. A refresh token is persisted only when
|
|
25
|
+
# +refresh_token: true+, bound to +client_id+'s ClientApplication when that
|
|
26
|
+
# names one. Pass +request:+ to let config.session.session_type_resolver
|
|
27
|
+
# materialise a session; without it the mint is sessionless.
|
|
28
|
+
#
|
|
29
|
+
# Raises the same errors the token endpoint would (InvalidGrantError,
|
|
30
|
+
# InvalidRequestError, NoBoundProfileError, AccountDeactivatedError, …).
|
|
31
|
+
module TokenMinter
|
|
32
|
+
Result = Data.define(:access_token, :refresh_token, :token_type, :expires_in, :scope, :jti)
|
|
33
|
+
|
|
34
|
+
module_function
|
|
35
|
+
|
|
36
|
+
# @param account [ActiveRecord::Base] a persisted account
|
|
37
|
+
# @param audience [String, Array<String>] the `aud` claim
|
|
38
|
+
# @param grant_type [String] recorded in the JWT and the audit events
|
|
39
|
+
# @param scopes [String, Array<String>, nil] the `scope` claim and the key
|
|
40
|
+
# into oauth.scope_claims
|
|
41
|
+
# @param client_id [String, nil] the `client_id` claim; a registered
|
|
42
|
+
# ClientApplication's id binds the refresh token to it
|
|
43
|
+
# @param claims [Hash] extra claims merged last (reserved keys dropped)
|
|
44
|
+
# @param expires_in [Integer, ActiveSupport::Duration, nil] access-token
|
|
45
|
+
# lifetime; default is oauth.token_lifetimes[grant_type] or
|
|
46
|
+
# oauth.default_token_lifetime
|
|
47
|
+
# @param refresh_token [Boolean] also persist and return a refresh token;
|
|
48
|
+
# requires +client_id+, which the refresh grant matches on redemption
|
|
49
|
+
# @param request [ActionDispatch::Request, nil] lets session_type_resolver
|
|
50
|
+
# persist a session; resolvers see `request: nil` without it
|
|
51
|
+
# @param auth_method [Symbol, String, nil] how the host authenticated the
|
|
52
|
+
# account, recorded on the refresh token for login_method_policy; nil is
|
|
53
|
+
# judged as :unspecified on refresh, which a restrictive policy refuses
|
|
54
|
+
# @param auth_provider [String, nil]
|
|
55
|
+
# @return [Result]
|
|
56
|
+
def mint(account:, audience:, grant_type:, scopes: nil, client_id: nil, claims: {}, expires_in: nil,
|
|
57
|
+
refresh_token: false, request: nil, auth_method: nil, auth_provider: nil)
|
|
58
|
+
flow = StandardId::Oauth::DirectMintFlow.new(
|
|
59
|
+
account: account, audience: audience, grant_type: grant_type, scopes: scopes, client_id: client_id,
|
|
60
|
+
claims: claims, expires_in: expires_in, refresh_token: refresh_token, request: request,
|
|
61
|
+
auth_method: auth_method, auth_provider: auth_provider
|
|
62
|
+
)
|
|
63
|
+
response = flow.execute
|
|
64
|
+
Result.new(
|
|
65
|
+
access_token: response[:access_token],
|
|
66
|
+
refresh_token: response[:refresh_token],
|
|
67
|
+
token_type: response[:token_type],
|
|
68
|
+
expires_in: response[:expires_in],
|
|
69
|
+
scope: response[:scope],
|
|
70
|
+
jti: flow.issued_jti
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
data/lib/standard_id/version.rb
CHANGED
data/lib/standard_id.rb
CHANGED
|
@@ -38,6 +38,7 @@ require "standard_id/auth_lineage"
|
|
|
38
38
|
require "standard_id/account_cleanup"
|
|
39
39
|
require "standard_id/oauth/audience_profile_resolver"
|
|
40
40
|
require "standard_id/oauth/audience_scope_resolver"
|
|
41
|
+
require "standard_id/oauth/audience_resolver"
|
|
41
42
|
require "standard_id/oauth/base_request_flow"
|
|
42
43
|
require "standard_id/oauth/token_lifetime_resolver"
|
|
43
44
|
require "standard_id/oauth/oauth_session_persistence"
|
|
@@ -47,6 +48,8 @@ require "standard_id/oauth/authorization_code_flow"
|
|
|
47
48
|
require "standard_id/oauth/password_flow"
|
|
48
49
|
require "standard_id/oauth/refresh_token_flow"
|
|
49
50
|
require "standard_id/oauth/social_flow"
|
|
51
|
+
require "standard_id/oauth/direct_mint_flow"
|
|
52
|
+
require "standard_id/token_minter"
|
|
50
53
|
require "standard_id/oauth/authorization_flow"
|
|
51
54
|
require "standard_id/oauth/authorization_code_authorization_flow"
|
|
52
55
|
require "standard_id/oauth/implicit_authorization_flow"
|
|
@@ -57,6 +60,7 @@ require "standard_id/oauth/passwordless_otp_flow"
|
|
|
57
60
|
require "standard_id/oauth/discovery_resolver"
|
|
58
61
|
require "standard_id/oauth/grant_types"
|
|
59
62
|
require "standard_id/oauth/discovery_document"
|
|
63
|
+
require "standard_id/oauth/protected_resource_document"
|
|
60
64
|
require "standard_id/routing"
|
|
61
65
|
require "standard_id/oauth/consent_payload"
|
|
62
66
|
require "standard_id/oauth/client_registration"
|
|
@@ -39,8 +39,15 @@ namespace :standard_id do
|
|
|
39
39
|
)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
desc "Delete dynamically registered clients that were deregistered, or never authorized, more than GRACE_DAYS ago (default 7)"
|
|
43
|
+
task dynamic_clients: :environment do
|
|
44
|
+
StandardId::PurgeStaleDynamicClientsJob.perform_now(
|
|
45
|
+
stale_after_seconds: StandardId::RakeHelpers.grace_period_seconds
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
42
49
|
desc "Run all StandardId cleanup jobs with GRACE_DAYS (default 7)"
|
|
43
|
-
task all: [:sessions, :refresh_tokens, :authorization_codes, :code_challenges]
|
|
50
|
+
task all: [:sessions, :refresh_tokens, :authorization_codes, :code_challenges, :dynamic_clients]
|
|
44
51
|
end
|
|
45
52
|
end
|
|
46
53
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: standard_id
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.49.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jaryl Sim
|
|
@@ -123,6 +123,7 @@ files:
|
|
|
123
123
|
- app/controllers/concerns/standard_id/passwordless_flow.rb
|
|
124
124
|
- app/controllers/concerns/standard_id/passwordless_strategy.rb
|
|
125
125
|
- app/controllers/concerns/standard_id/rate_limit_handling.rb
|
|
126
|
+
- app/controllers/concerns/standard_id/resource_server.rb
|
|
126
127
|
- app/controllers/concerns/standard_id/sentry_context.rb
|
|
127
128
|
- app/controllers/concerns/standard_id/set_current_request_details.rb
|
|
128
129
|
- app/controllers/concerns/standard_id/social_authentication.rb
|
|
@@ -143,6 +144,7 @@ files:
|
|
|
143
144
|
- app/controllers/standard_id/api/userinfo_controller.rb
|
|
144
145
|
- app/controllers/standard_id/api/well_known/jwks_controller.rb
|
|
145
146
|
- app/controllers/standard_id/api/well_known/oauth_authorization_server_controller.rb
|
|
147
|
+
- app/controllers/standard_id/api/well_known/oauth_protected_resource_controller.rb
|
|
146
148
|
- app/controllers/standard_id/api/well_known/openid_configuration_controller.rb
|
|
147
149
|
- app/controllers/standard_id/web/account_controller.rb
|
|
148
150
|
- app/controllers/standard_id/web/auth/callback/providers_controller.rb
|
|
@@ -172,6 +174,7 @@ files:
|
|
|
172
174
|
- app/jobs/standard_id/cleanup_expired_refresh_tokens_job.rb
|
|
173
175
|
- app/jobs/standard_id/cleanup_expired_sessions_job.rb
|
|
174
176
|
- app/jobs/standard_id/password_reset_delivery_job.rb
|
|
177
|
+
- app/jobs/standard_id/purge_stale_dynamic_clients_job.rb
|
|
175
178
|
- app/jobs/standard_id/secure_mail_delivery_job.rb
|
|
176
179
|
- app/mailers/standard_id/application_mailer.rb
|
|
177
180
|
- app/mailers/standard_id/password_reset_mailer.rb
|
|
@@ -239,6 +242,7 @@ files:
|
|
|
239
242
|
- db/migrate/20261002000000_create_standard_id_social_identities.rb
|
|
240
243
|
- db/migrate/20261004000000_add_auth_method_to_standard_id_refresh_tokens.rb
|
|
241
244
|
- db/migrate/20261020000000_add_client_application_id_to_standard_id_refresh_tokens.rb
|
|
245
|
+
- db/migrate/20261020120000_add_registration_access_token_digest_to_standard_id_client_applications.rb
|
|
242
246
|
- lib/generators/standard_id/install/install_generator.rb
|
|
243
247
|
- lib/generators/standard_id/install/templates/standard_id.rb
|
|
244
248
|
- lib/standard_id.rb
|
|
@@ -278,6 +282,7 @@ files:
|
|
|
278
282
|
- lib/standard_id/migration_check.rb
|
|
279
283
|
- lib/standard_id/migration_helpers.rb
|
|
280
284
|
- lib/standard_id/oauth/audience_profile_resolver.rb
|
|
285
|
+
- lib/standard_id/oauth/audience_resolver.rb
|
|
281
286
|
- lib/standard_id/oauth/audience_scope_resolver.rb
|
|
282
287
|
- lib/standard_id/oauth/authorization_code_authorization_flow.rb
|
|
283
288
|
- lib/standard_id/oauth/authorization_code_flow.rb
|
|
@@ -286,6 +291,7 @@ files:
|
|
|
286
291
|
- lib/standard_id/oauth/client_credentials_flow.rb
|
|
287
292
|
- lib/standard_id/oauth/client_registration.rb
|
|
288
293
|
- lib/standard_id/oauth/consent_payload.rb
|
|
294
|
+
- lib/standard_id/oauth/direct_mint_flow.rb
|
|
289
295
|
- lib/standard_id/oauth/discovery_document.rb
|
|
290
296
|
- lib/standard_id/oauth/discovery_resolver.rb
|
|
291
297
|
- lib/standard_id/oauth/grant_types.rb
|
|
@@ -293,6 +299,7 @@ files:
|
|
|
293
299
|
- lib/standard_id/oauth/oauth_session_persistence.rb
|
|
294
300
|
- lib/standard_id/oauth/password_flow.rb
|
|
295
301
|
- lib/standard_id/oauth/passwordless_otp_flow.rb
|
|
302
|
+
- lib/standard_id/oauth/protected_resource_document.rb
|
|
296
303
|
- lib/standard_id/oauth/refresh_token_flow.rb
|
|
297
304
|
- lib/standard_id/oauth/social_flow.rb
|
|
298
305
|
- lib/standard_id/oauth/subflows/base.rb
|
|
@@ -324,6 +331,7 @@ files:
|
|
|
324
331
|
- lib/standard_id/testing/factory_bot.rb
|
|
325
332
|
- lib/standard_id/testing/provider_examples.rb
|
|
326
333
|
- lib/standard_id/testing/request_helpers.rb
|
|
334
|
+
- lib/standard_id/token_minter.rb
|
|
327
335
|
- lib/standard_id/utils/callable_parameter_filter.rb
|
|
328
336
|
- lib/standard_id/utils/ip_normalizer.rb
|
|
329
337
|
- lib/standard_id/version.rb
|