standard_id 0.43.2 → 0.45.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 +72 -0
- data/README.md +148 -3
- data/app/controllers/concerns/standard_id/lifecycle_hooks.rb +3 -18
- data/app/controllers/concerns/standard_id/social_authentication.rb +316 -8
- data/app/controllers/concerns/standard_id/web_authentication.rb +6 -1
- data/app/controllers/standard_id/api/authorization_controller.rb +11 -4
- data/app/controllers/standard_id/api/base_controller.rb +16 -0
- data/app/controllers/standard_id/api/oauth/callback/providers_controller.rb +61 -15
- data/app/controllers/standard_id/web/auth/callback/providers_controller.rb +51 -3
- data/app/controllers/standard_id/web/consent_controller.rb +5 -1
- data/app/controllers/standard_id/web/login_verify_controller.rb +6 -1
- data/app/controllers/standard_id/web/signup_controller.rb +6 -1
- data/app/models/standard_id/social_identity.rb +30 -0
- data/db/migrate/20261002000000_create_standard_id_social_identities.rb +44 -0
- data/db/migrate/20261004000000_add_auth_method_to_standard_id_refresh_tokens.rb +17 -0
- data/lib/generators/standard_id/install/templates/standard_id.rb +21 -4
- data/lib/standard_id/account_cleanup.rb +62 -0
- data/lib/standard_id/api/token_manager.rb +18 -2
- data/lib/standard_id/auth_lineage.rb +75 -0
- data/lib/standard_id/config/callable_validator.rb +5 -0
- data/lib/standard_id/config/schema.rb +18 -0
- data/lib/standard_id/errors.rb +68 -2
- data/lib/standard_id/events/definitions.rb +6 -1
- data/lib/standard_id/events/subscribers/logging_subscriber.rb +1 -0
- data/lib/standard_id/login_method_policy.rb +108 -0
- data/lib/standard_id/oauth/authorization_code_authorization_flow.rb +2 -1
- data/lib/standard_id/oauth/authorization_code_flow.rb +6 -0
- data/lib/standard_id/oauth/authorization_flow.rb +6 -2
- data/lib/standard_id/oauth/password_flow.rb +13 -2
- data/lib/standard_id/oauth/passwordless_otp_flow.rb +4 -0
- data/lib/standard_id/oauth/refresh_token_flow.rb +32 -0
- data/lib/standard_id/oauth/social_flow.rb +4 -0
- data/lib/standard_id/oauth/subflows/traditional_code_grant.rb +6 -1
- data/lib/standard_id/oauth/token_grant_flow.rb +54 -2
- data/lib/standard_id/providers/base.rb +34 -0
- data/lib/standard_id/version.rb +1 -1
- data/lib/standard_id/web/session_manager.rb +50 -3
- data/lib/standard_id/web/token_manager.rb +8 -3
- data/lib/standard_id.rb +3 -0
- metadata +7 -1
|
@@ -55,6 +55,10 @@ module StandardId
|
|
|
55
55
|
@account.id
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
+
def login_method_policy_context
|
|
59
|
+
{ auth_method: :password, flow: :oauth_password_grant }
|
|
60
|
+
end
|
|
61
|
+
|
|
58
62
|
def client_id
|
|
59
63
|
params[:client_id]
|
|
60
64
|
end
|
|
@@ -76,15 +80,22 @@ module StandardId
|
|
|
76
80
|
end
|
|
77
81
|
|
|
78
82
|
def authenticate_account(username, password)
|
|
83
|
+
# Credential reaches the account through its identifier (`delegate
|
|
84
|
+
# :account, to: :identifier`); there is no `account` association to
|
|
85
|
+
# preload, and asking for one raised AssociationNotFoundError for every
|
|
86
|
+
# login that found a credential.
|
|
79
87
|
@credential = StandardId::PasswordCredential
|
|
80
|
-
.includes(credential: :account)
|
|
88
|
+
.includes(credential: { identifier: :account })
|
|
81
89
|
.find_by(login: username)
|
|
82
90
|
|
|
83
91
|
# Perform a dummy bcrypt comparison when the credential doesn't exist
|
|
84
92
|
# to prevent user enumeration via response timing differences.
|
|
85
93
|
BCrypt::Password.new(dummy_password_digest).is_password?(password) unless @credential
|
|
86
94
|
|
|
87
|
-
|
|
95
|
+
# has_secure_password's authenticate returns false (not nil) on a wrong
|
|
96
|
+
# password, so `&.account` would call false.account → NoMethodError (500).
|
|
97
|
+
authenticated = @credential&.authenticate(password)
|
|
98
|
+
authenticated ? authenticated.account : nil
|
|
88
99
|
end
|
|
89
100
|
|
|
90
101
|
def validate_requested_scope!
|
|
@@ -15,6 +15,7 @@ module StandardId
|
|
|
15
15
|
# in a transaction for atomicity.
|
|
16
16
|
def execute
|
|
17
17
|
instrumented_authenticate!
|
|
18
|
+
enforce_refresh_login_method_policy!
|
|
18
19
|
response = nil
|
|
19
20
|
StandardId::RefreshToken.transaction do
|
|
20
21
|
rotate_current_refresh_token!
|
|
@@ -45,6 +46,37 @@ module StandardId
|
|
|
45
46
|
|
|
46
47
|
private
|
|
47
48
|
|
|
49
|
+
# The refresh_token grant re-checks config.login_method_policy with the
|
|
50
|
+
# method the ORIGINAL authentication used (recorded on the token, copied
|
|
51
|
+
# down each rotation). A token minted before 0.45 / before migration
|
|
52
|
+
# 20261004000000 has none and is checked as :unspecified, so a
|
|
53
|
+
# restrictive policy refuses it and the client must sign in again.
|
|
54
|
+
def login_method_policy_context
|
|
55
|
+
StandardId::AuthLineage.policy_arguments(refresh_token_auth_lineage).merge(flow: :oauth_refresh_token)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Successor tokens inherit the presented token's lineage.
|
|
59
|
+
def refresh_token_auth_lineage
|
|
60
|
+
StandardId::AuthLineage.from_refresh_token(@current_refresh_token_record)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Runs after authenticate! proved the token, before rotation. Outside the
|
|
64
|
+
# rotation transaction so the family revocation persists. The answer is
|
|
65
|
+
# the same `invalid_grant` as any other dead refresh token: whoever
|
|
66
|
+
# presents a refresh token may not be its legitimate holder, so the
|
|
67
|
+
# response must not reveal why (RFC 6749 §5.2; see
|
|
68
|
+
# Api::Oauth::BaseController#handle_account_unusable). The reason is in
|
|
69
|
+
# the AUTHENTICATION_METHOD_DENIED event, server-side.
|
|
70
|
+
def enforce_refresh_login_method_policy!
|
|
71
|
+
account = token_account
|
|
72
|
+
return if account.nil?
|
|
73
|
+
|
|
74
|
+
StandardId::LoginMethodPolicy.enforce!(account: account, request: request, **login_method_policy_context)
|
|
75
|
+
rescue StandardId::LoginMethodDenied
|
|
76
|
+
@current_refresh_token_record&.revoke_family!
|
|
77
|
+
raise StandardId::InvalidGrantError, "Refresh token is no longer valid"
|
|
78
|
+
end
|
|
79
|
+
|
|
48
80
|
def validate_refresh_token_record!
|
|
49
81
|
jti = @refresh_payload[:jti]
|
|
50
82
|
# Legacy tokens minted before jti tracking was added cannot be looked
|
|
@@ -21,6 +21,11 @@ module StandardId
|
|
|
21
21
|
@authorization_code ||= SecureRandom.urlsafe_base64(32)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def lineage_metadata
|
|
25
|
+
lineage = params[:auth_lineage]
|
|
26
|
+
lineage ? StandardId::AuthLineage.to_metadata(lineage) : {}
|
|
27
|
+
end
|
|
28
|
+
|
|
24
29
|
def store_authorization_code
|
|
25
30
|
StandardId::AuthorizationCode.issue!(
|
|
26
31
|
plaintext_code: authorization_code,
|
|
@@ -32,7 +37,7 @@ module StandardId
|
|
|
32
37
|
code_challenge: params[:code_challenge],
|
|
33
38
|
code_challenge_method: params[:code_challenge_method],
|
|
34
39
|
nonce: params[:nonce],
|
|
35
|
-
metadata: { state: params[:state] }.compact
|
|
40
|
+
metadata: { state: params[:state] }.compact.merge(lineage_metadata)
|
|
36
41
|
)
|
|
37
42
|
end
|
|
38
43
|
|
|
@@ -3,6 +3,13 @@ module StandardId
|
|
|
3
3
|
class TokenGrantFlow < BaseRequestFlow
|
|
4
4
|
attr_reader :params, :request
|
|
5
5
|
|
|
6
|
+
# The refresh token row this grant persisted, once it got that far (nil
|
|
7
|
+
# before). A caller that rejects the grant after it ran (the API social
|
|
8
|
+
# callback) revokes it, and its session, from here: when the grant
|
|
9
|
+
# itself raised after the write, no token response came back to read
|
|
10
|
+
# it from.
|
|
11
|
+
attr_reader :issued_refresh_token
|
|
12
|
+
|
|
6
13
|
def initialize(params, request, current_account: nil)
|
|
7
14
|
@params = params
|
|
8
15
|
@request = request
|
|
@@ -17,11 +24,42 @@ module StandardId
|
|
|
17
24
|
|
|
18
25
|
def execute
|
|
19
26
|
instrumented_authenticate!
|
|
27
|
+
enforce_login_method_policy!
|
|
20
28
|
generate_token_response
|
|
21
29
|
end
|
|
22
30
|
|
|
23
31
|
private
|
|
24
32
|
|
|
33
|
+
# The login-method policy context for this grant, or nil when the grant
|
|
34
|
+
# does not establish a new authentication (authorization_code,
|
|
35
|
+
# refresh_token, client_credentials derive from one that already
|
|
36
|
+
# happened, or have no account). Grants that authenticate an account
|
|
37
|
+
# themselves override this. See StandardId::LoginMethodPolicy.
|
|
38
|
+
#
|
|
39
|
+
# @return [Hash, nil] `{ auth_method:, flow:, provider: }`
|
|
40
|
+
def login_method_policy_context
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Runs after authenticate! has proven the credential and before any
|
|
45
|
+
# token, refresh token or session row is created. On refusal an account
|
|
46
|
+
# created by this very request (passwordless or social registration) is
|
|
47
|
+
# removed again, mirroring the WebEngine's handle_authentication_denied.
|
|
48
|
+
def enforce_login_method_policy!
|
|
49
|
+
policy_context = login_method_policy_context
|
|
50
|
+
return if policy_context.nil?
|
|
51
|
+
|
|
52
|
+
account = token_account
|
|
53
|
+
return if account.nil?
|
|
54
|
+
|
|
55
|
+
StandardId::LoginMethodPolicy.enforce!(account: account, request: request, **policy_context)
|
|
56
|
+
rescue StandardId::LoginMethodDenied
|
|
57
|
+
if account.respond_to?(:previously_new_record?) && account.previously_new_record?
|
|
58
|
+
StandardId::AccountCleanup.destroy_newly_created!(account)
|
|
59
|
+
end
|
|
60
|
+
raise
|
|
61
|
+
end
|
|
62
|
+
|
|
25
63
|
# authenticate!, wrapped in the Instrumentation::AUTHENTICATE event.
|
|
26
64
|
def instrumented_authenticate!
|
|
27
65
|
StandardId::Instrumentation.instrument(StandardId::Instrumentation::AUTHENTICATE, instrumentation_payload) do
|
|
@@ -186,15 +224,29 @@ module StandardId
|
|
|
186
224
|
end
|
|
187
225
|
|
|
188
226
|
def persist_refresh_token!(jti:, expires_at:)
|
|
189
|
-
StandardId::RefreshToken.create!(
|
|
227
|
+
@issued_refresh_token = StandardId::RefreshToken.create!(
|
|
190
228
|
account_id: subject_id,
|
|
191
229
|
session_id: refresh_token_session_id,
|
|
192
230
|
token_digest: StandardId::RefreshToken.digest_for(jti),
|
|
193
231
|
expires_at: expires_at,
|
|
194
|
-
previous_token: previous_refresh_token_record
|
|
232
|
+
previous_token: previous_refresh_token_record,
|
|
233
|
+
**StandardId::AuthLineage.refresh_token_attributes(refresh_token_auth_lineage)
|
|
195
234
|
)
|
|
196
235
|
end
|
|
197
236
|
|
|
237
|
+
# How the authentication behind this grant was established, recorded on
|
|
238
|
+
# the refresh token so the refresh_token grant can re-check the
|
|
239
|
+
# login-method policy against it. Grants that authenticate an account
|
|
240
|
+
# themselves derive it from their policy context; the authorization_code
|
|
241
|
+
# and refresh_token grants override it (from the code / the presented
|
|
242
|
+
# token). See StandardId::AuthLineage.
|
|
243
|
+
def refresh_token_auth_lineage
|
|
244
|
+
context = login_method_policy_context
|
|
245
|
+
return StandardId::AuthLineage.empty if context.nil?
|
|
246
|
+
|
|
247
|
+
StandardId::AuthLineage.build(context[:auth_method], context[:provider])
|
|
248
|
+
end
|
|
249
|
+
|
|
198
250
|
# The parent session for the refresh token issued by THIS grant, when the
|
|
199
251
|
# host materialised one via `config.session.session_type_resolver`.
|
|
200
252
|
#
|
|
@@ -212,6 +212,40 @@ module StandardId
|
|
|
212
212
|
false
|
|
213
213
|
end
|
|
214
214
|
|
|
215
|
+
# Whether the `:strict` link_strategy may link this provider's login to
|
|
216
|
+
# an existing account that was created through ANOTHER provider (for
|
|
217
|
+
# example, a Google-created account) when the email addresses match.
|
|
218
|
+
#
|
|
219
|
+
# Default: false. Every provider, including Google and Apple, keeps
|
|
220
|
+
# the 0.44 behaviour: `:strict` refuses that link with
|
|
221
|
+
# SocialLinkError (reason `:link_required`).
|
|
222
|
+
#
|
|
223
|
+
# Return true ONLY for the organisation's own identity provider whose
|
|
224
|
+
# email claims the organisation itself verifies — e.g. a broker-local
|
|
225
|
+
# directory such as moneta (standard_id-void_which_binds), where an
|
|
226
|
+
# address is provisioned by the org and cannot be self-asserted. A
|
|
227
|
+
# public IdP that lets anyone register an address (Google, Apple,
|
|
228
|
+
# GitHub, ...) must never return true: trusting it would let whoever
|
|
229
|
+
# controls an address *at that IdP* take over the account holding the
|
|
230
|
+
# same address here.
|
|
231
|
+
#
|
|
232
|
+
# Returning true relaxes ONLY the `:strict` cross-provider check. All
|
|
233
|
+
# of these still apply, unchanged:
|
|
234
|
+
# - the provider must report `email_verified` as true (or "true"),
|
|
235
|
+
# otherwise the link is refused with reason `:email_unverified`;
|
|
236
|
+
# - the existing email identifier must itself be verified (an
|
|
237
|
+
# unverified address on the existing account proves nothing about
|
|
238
|
+
# who created it — see the pre-account-hijacking note in the
|
|
239
|
+
# README);
|
|
240
|
+
# - the identifier must not already be linked to a different `sub`
|
|
241
|
+
# from this provider (`:subject_mismatch`);
|
|
242
|
+
# - a stored (provider, sub) match still wins over any email match.
|
|
243
|
+
#
|
|
244
|
+
# @return [Boolean]
|
|
245
|
+
def trusted_for_linking?
|
|
246
|
+
false
|
|
247
|
+
end
|
|
248
|
+
|
|
215
249
|
# Returns list of supported authorization parameters for this provider.
|
|
216
250
|
#
|
|
217
251
|
# Include :nonce in this list for OIDC providers to enable nonce validation.
|
data/lib/standard_id/version.rb
CHANGED
|
@@ -3,6 +3,11 @@ module StandardId
|
|
|
3
3
|
class SessionManager
|
|
4
4
|
attr_reader :token_manager, :request, :session, :cookies
|
|
5
5
|
|
|
6
|
+
# The session sign_in_account created in this request, set as soon as the
|
|
7
|
+
# row exists — so a caller can revoke it even when sign_in_account then
|
|
8
|
+
# raises (e.g. a SESSION_CREATED subscriber fails).
|
|
9
|
+
attr_reader :created_session
|
|
10
|
+
|
|
6
11
|
def initialize(token_manager, request:, session:, cookies:, reset_session: nil)
|
|
7
12
|
@token_manager = token_manager
|
|
8
13
|
@request = request
|
|
@@ -32,7 +37,26 @@ module StandardId
|
|
|
32
37
|
Current.account = load_current_account
|
|
33
38
|
end
|
|
34
39
|
|
|
35
|
-
|
|
40
|
+
# Creates a browser session for an account whose credential the caller
|
|
41
|
+
# has already verified.
|
|
42
|
+
#
|
|
43
|
+
# `config.login_method_policy` is consulted first, before anything is
|
|
44
|
+
# written; a refusal raises StandardId::LoginMethodDenied (an
|
|
45
|
+
# AuthenticationDenied) and no session, cookie or Rails-session change
|
|
46
|
+
# happens. The engine's own controllers pass `auth_method:` /
|
|
47
|
+
# `provider:` / `flow:`. Host code that signs accounts in itself should
|
|
48
|
+
# pass at least `auth_method:` (e.g. `:password`, `:social`); without it
|
|
49
|
+
# the policy sees `:unspecified` under flow `:web_session`, which a
|
|
50
|
+
# restrictive policy will (correctly) refuse.
|
|
51
|
+
def sign_in_account(account, scope_name: nil, auth_method: nil, provider: nil, flow: :web_session)
|
|
52
|
+
StandardId::LoginMethodPolicy.enforce!(
|
|
53
|
+
account: account,
|
|
54
|
+
auth_method: auth_method,
|
|
55
|
+
provider: provider,
|
|
56
|
+
request: request,
|
|
57
|
+
flow: flow
|
|
58
|
+
)
|
|
59
|
+
|
|
36
60
|
emit_session_creating(account, "browser")
|
|
37
61
|
|
|
38
62
|
# Prevent session fixation by resetting the Rails session before
|
|
@@ -44,7 +68,9 @@ module StandardId
|
|
|
44
68
|
session[:return_to_after_authenticating] = return_to if return_to
|
|
45
69
|
session[:standard_id_scopes] = existing_scopes if existing_scopes
|
|
46
70
|
|
|
47
|
-
|
|
71
|
+
lineage = StandardId::AuthLineage.build(auth_method || :unspecified, provider)
|
|
72
|
+
token_manager.create_browser_session(account, auth_lineage: lineage).tap do |browser_session|
|
|
73
|
+
@created_session = browser_session
|
|
48
74
|
# Store in both session and encrypted cookie for backward compatibility
|
|
49
75
|
# Action Cable will use the encrypted cookie
|
|
50
76
|
session[:session_token] = browser_session.token
|
|
@@ -202,13 +228,34 @@ module StandardId
|
|
|
202
228
|
password_credential = StandardId::PasswordCredential.find_by_token_for(:remember_me, cookies[:remember_token])
|
|
203
229
|
return if password_credential.blank?
|
|
204
230
|
|
|
231
|
+
# Remember-me is a re-authentication (it mints a new session), so the
|
|
232
|
+
# login-method policy applies. A refusal must not raise here — this
|
|
233
|
+
# runs on any request that asks for current_session — so it signs the
|
|
234
|
+
# visitor out instead (clearing the remember cookie, so the refused
|
|
235
|
+
# cookie is not replayed on every request). The refusal itself is
|
|
236
|
+
# published as AUTHENTICATION_METHOD_DENIED by the policy.
|
|
237
|
+
begin
|
|
238
|
+
StandardId::LoginMethodPolicy.enforce!(
|
|
239
|
+
account: password_credential.account,
|
|
240
|
+
auth_method: :remember_me,
|
|
241
|
+
request: request,
|
|
242
|
+
flow: :web_remember_me
|
|
243
|
+
)
|
|
244
|
+
rescue StandardId::LoginMethodDenied
|
|
245
|
+
clear_session!
|
|
246
|
+
return
|
|
247
|
+
end
|
|
248
|
+
|
|
205
249
|
# Prevent session fixation on returning-user remember-me flow.
|
|
206
250
|
# Note: standard_id_scopes are intentionally NOT preserved here —
|
|
207
251
|
# remember-me re-auth is a fresh session context where scopes
|
|
208
252
|
# must be re-acquired through explicit scoped sign-in.
|
|
209
253
|
@reset_session&.call
|
|
210
254
|
|
|
211
|
-
|
|
255
|
+
# Recorded as :remember_me, the method the policy approved above, so
|
|
256
|
+
# tokens later derived from this session are re-checked as such.
|
|
257
|
+
lineage = StandardId::AuthLineage.build(:remember_me)
|
|
258
|
+
token_manager.create_browser_session(password_credential.account, auth_lineage: lineage).tap do |browser_session|
|
|
212
259
|
# Store in both session and encrypted cookie for backward compatibility
|
|
213
260
|
session[:session_token] = browser_session.token
|
|
214
261
|
write_session_cookie(browser_session)
|
|
@@ -7,14 +7,17 @@ module StandardId
|
|
|
7
7
|
@request = request
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
# `auth_lineage` (StandardId::AuthLineage) records how the sign-in was
|
|
11
|
+
# made in the session's metadata, so codes and tokens derived from this
|
|
12
|
+
# session can be re-checked against config.login_method_policy.
|
|
13
|
+
def create_browser_session(account, auth_lineage: nil)
|
|
11
14
|
session_class = StandardId::SessionTypeResolver.resolve!(
|
|
12
15
|
request: request,
|
|
13
16
|
account: account,
|
|
14
17
|
flow: :web_sign_in
|
|
15
18
|
)
|
|
16
19
|
|
|
17
|
-
create_session_for(session_class, account: account)
|
|
20
|
+
create_session_for(session_class, account: account, auth_lineage: auth_lineage)
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
def create_remember_token(password_credential)
|
|
@@ -29,10 +32,12 @@ module StandardId
|
|
|
29
32
|
|
|
30
33
|
private
|
|
31
34
|
|
|
32
|
-
def create_session_for(session_class, account:)
|
|
35
|
+
def create_session_for(session_class, account:, auth_lineage: nil)
|
|
33
36
|
attrs = base_attributes(account: account).merge(
|
|
34
37
|
session_specific_attributes(session_class)
|
|
35
38
|
)
|
|
39
|
+
lineage_metadata = auth_lineage ? StandardId::AuthLineage.to_metadata(auth_lineage) : {}
|
|
40
|
+
attrs[:metadata] = lineage_metadata if lineage_metadata.present?
|
|
36
41
|
session_class.create!(**attrs)
|
|
37
42
|
end
|
|
38
43
|
|
data/lib/standard_id.rb
CHANGED
|
@@ -33,6 +33,9 @@ require "standard_id/api/session_manager"
|
|
|
33
33
|
require "standard_id/api/token_manager"
|
|
34
34
|
require "standard_id/api/authentication_guard"
|
|
35
35
|
require "standard_id/utils/callable_parameter_filter"
|
|
36
|
+
require "standard_id/login_method_policy"
|
|
37
|
+
require "standard_id/auth_lineage"
|
|
38
|
+
require "standard_id/account_cleanup"
|
|
36
39
|
require "standard_id/oauth/audience_profile_resolver"
|
|
37
40
|
require "standard_id/oauth/audience_scope_resolver"
|
|
38
41
|
require "standard_id/oauth/base_request_flow"
|
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.45.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jaryl Sim
|
|
@@ -195,6 +195,7 @@ files:
|
|
|
195
195
|
- app/models/standard_id/refresh_token.rb
|
|
196
196
|
- app/models/standard_id/service_session.rb
|
|
197
197
|
- app/models/standard_id/session.rb
|
|
198
|
+
- app/models/standard_id/social_identity.rb
|
|
198
199
|
- app/models/standard_id/username_identifier.rb
|
|
199
200
|
- app/views/standard_id/password_reset_mailer/reset_email.html.erb
|
|
200
201
|
- app/views/standard_id/password_reset_mailer/reset_email.text.erb
|
|
@@ -235,9 +236,12 @@ files:
|
|
|
235
236
|
- db/migrate/20260611000000_create_standard_id_client_grants.rb
|
|
236
237
|
- db/migrate/20260915000000_remove_refresh_token_lifetime_from_standard_id_client_applications.rb
|
|
237
238
|
- db/migrate/20260924000000_add_unique_active_device_index_to_standard_id_sessions.rb
|
|
239
|
+
- db/migrate/20261002000000_create_standard_id_social_identities.rb
|
|
240
|
+
- db/migrate/20261004000000_add_auth_method_to_standard_id_refresh_tokens.rb
|
|
238
241
|
- lib/generators/standard_id/install/install_generator.rb
|
|
239
242
|
- lib/generators/standard_id/install/templates/standard_id.rb
|
|
240
243
|
- lib/standard_id.rb
|
|
244
|
+
- lib/standard_id/account_cleanup.rb
|
|
241
245
|
- lib/standard_id/account_locking.rb
|
|
242
246
|
- lib/standard_id/account_status.rb
|
|
243
247
|
- lib/standard_id/api/authentication_guard.rb
|
|
@@ -245,6 +249,7 @@ files:
|
|
|
245
249
|
- lib/standard_id/api/token_manager.rb
|
|
246
250
|
- lib/standard_id/api_engine.rb
|
|
247
251
|
- lib/standard_id/association_strict_loading.rb
|
|
252
|
+
- lib/standard_id/auth_lineage.rb
|
|
248
253
|
- lib/standard_id/authorization_bypass.rb
|
|
249
254
|
- lib/standard_id/bearer_token_extraction.rb
|
|
250
255
|
- lib/standard_id/checks/migrations.rb
|
|
@@ -268,6 +273,7 @@ files:
|
|
|
268
273
|
- lib/standard_id/http_client.rb
|
|
269
274
|
- lib/standard_id/instrumentation.rb
|
|
270
275
|
- lib/standard_id/jwt_service.rb
|
|
276
|
+
- lib/standard_id/login_method_policy.rb
|
|
271
277
|
- lib/standard_id/migration_check.rb
|
|
272
278
|
- lib/standard_id/migration_helpers.rb
|
|
273
279
|
- lib/standard_id/oauth/audience_profile_resolver.rb
|