standard_id 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +347 -7
- data/app/controllers/standard_id/api/providers_controller.rb +15 -16
- data/app/controllers/standard_id/web/verify_email/base_controller.rb +9 -0
- data/app/controllers/standard_id/web/verify_email/confirm_controller.rb +41 -0
- data/app/controllers/standard_id/web/verify_email/start_controller.rb +39 -0
- data/app/controllers/standard_id/web/verify_phone/base_controller.rb +9 -0
- data/app/controllers/standard_id/web/verify_phone/confirm_controller.rb +41 -0
- data/app/controllers/standard_id/web/verify_phone/start_controller.rb +39 -0
- data/app/forms/standard_id/web/signup_form.rb +3 -14
- data/app/models/standard_id/client_application.rb +2 -1
- data/app/models/standard_id/{passwordless_challenge.rb → code_challenge.rb} +9 -5
- data/app/models/standard_id/email_identifier.rb +2 -0
- data/app/models/standard_id/identifier.rb +17 -0
- data/app/models/standard_id/phone_number_identifier.rb +2 -0
- data/app/models/standard_id/username_identifier.rb +2 -0
- data/config/routes/web.rb +12 -0
- data/db/migrate/20250830000000_create_standard_id_client_applications.rb +3 -3
- data/db/migrate/20250830232800_create_standard_id_identifiers.rb +1 -1
- data/db/migrate/20250831075703_create_standard_id_credentials.rb +2 -2
- data/db/migrate/20250831154635_create_standard_id_sessions.rb +2 -2
- data/db/migrate/20250901134520_create_standard_id_client_secret_credentials.rb +2 -2
- data/db/migrate/20250907090000_create_standard_id_code_challenges.rb +29 -0
- data/lib/generators/standard_id/install/templates/standard_id.rb +36 -3
- data/lib/{standard_id → standard_config}/config.rb +1 -1
- data/lib/standard_config/config_provider.rb +82 -0
- data/lib/standard_config/manager.rb +86 -0
- data/lib/standard_config/schema.rb +137 -0
- data/lib/standard_config.rb +38 -0
- data/lib/standard_id/api/session_manager.rb +1 -1
- data/lib/standard_id/config/schema.rb +49 -0
- data/lib/standard_id/oauth/client_credentials_flow.rb +1 -5
- data/lib/standard_id/oauth/implicit_authorization_flow.rb +1 -1
- data/lib/standard_id/oauth/password_flow.rb +0 -4
- data/lib/standard_id/oauth/passwordless_otp_flow.rb +7 -10
- data/lib/standard_id/oauth/token_grant_flow.rb +6 -2
- data/lib/standard_id/oauth/token_lifetime_resolver.rb +50 -0
- data/lib/standard_id/passwordless/base_strategy.rb +8 -4
- data/lib/standard_id/version.rb +1 -1
- data/lib/standard_id.rb +13 -4
- metadata +16 -4
- data/db/migrate/20250903135906_create_standard_id_passwordless_challenges.rb +0 -22
|
@@ -7,12 +7,12 @@ module StandardId
|
|
|
7
7
|
def authenticate!
|
|
8
8
|
validate_client_secret!(params[:client_id], params[:client_secret]) if params[:client_secret].present?
|
|
9
9
|
|
|
10
|
-
raise StandardId::InvalidGrantError, "Invalid or expired verification code" if
|
|
10
|
+
raise StandardId::InvalidGrantError, "Invalid or expired verification code" if code_challenge.blank?
|
|
11
11
|
raise StandardId::InvalidGrantError, "Unable to authenticate user" if account.blank?
|
|
12
12
|
|
|
13
13
|
validate_requested_scope!
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
code_challenge.use!
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
private
|
|
@@ -41,14 +41,11 @@ module StandardId
|
|
|
41
41
|
true
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
@passwordless_challenge ||= StandardId::PasswordlessChallenge.active.find_by(
|
|
50
|
-
connection_type: params[:connection],
|
|
51
|
-
username: params[:username],
|
|
44
|
+
def code_challenge
|
|
45
|
+
@code_challenge ||= StandardId::CodeChallenge.active.find_by(
|
|
46
|
+
realm: "authentication",
|
|
47
|
+
channel: params[:connection],
|
|
48
|
+
target: params[:username],
|
|
52
49
|
code: params[:otp]
|
|
53
50
|
)
|
|
54
51
|
end
|
|
@@ -62,7 +62,7 @@ module StandardId
|
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def token_expiry
|
|
65
|
-
|
|
65
|
+
TokenLifetimeResolver.access_token_for(token_lifetime_key)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def supports_refresh_token?
|
|
@@ -80,7 +80,11 @@ module StandardId
|
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
def refresh_token_expiry
|
|
83
|
-
|
|
83
|
+
TokenLifetimeResolver.refresh_token_lifetime
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def token_lifetime_key
|
|
87
|
+
grant_type&.to_sym
|
|
84
88
|
end
|
|
85
89
|
|
|
86
90
|
def subject_id
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module StandardId
|
|
2
|
+
module Oauth
|
|
3
|
+
class TokenLifetimeResolver
|
|
4
|
+
class << self
|
|
5
|
+
DEFAULT_ACCESS_TOKEN_LIFETIME = 1.hour.to_i
|
|
6
|
+
DEFAULT_REFRESH_TOKEN_LIFETIME = 30.days.to_i
|
|
7
|
+
|
|
8
|
+
def access_token_for(flow_key)
|
|
9
|
+
configured = lookup_token_lifetime(flow_key)
|
|
10
|
+
positive_seconds(configured, default_access_token_lifetime)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def refresh_token_lifetime
|
|
14
|
+
positive_seconds(oauth_config.refresh_token_lifetime, DEFAULT_REFRESH_TOKEN_LIFETIME)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def default_access_token_lifetime
|
|
20
|
+
positive_seconds(oauth_config.default_token_lifetime, DEFAULT_ACCESS_TOKEN_LIFETIME)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def lookup_token_lifetime(flow_key)
|
|
24
|
+
config = oauth_config
|
|
25
|
+
return nil unless config.respond_to?(:token_lifetimes)
|
|
26
|
+
|
|
27
|
+
lifetimes = config.token_lifetimes || {}
|
|
28
|
+
lifetimes[flow_key.to_sym] || lifetimes[flow_key.to_s] if flow_key
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def positive_seconds(value, fallback_value)
|
|
32
|
+
normalized_value = case value
|
|
33
|
+
when ActiveSupport::Duration
|
|
34
|
+
value.to_i
|
|
35
|
+
when Numeric, String
|
|
36
|
+
value.to_i
|
|
37
|
+
else
|
|
38
|
+
0
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
(normalized_value.positive? ? normalized_value : fallback_value).seconds
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def oauth_config
|
|
45
|
+
StandardId.config.oauth
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -24,14 +24,18 @@ module StandardId
|
|
|
24
24
|
protected
|
|
25
25
|
|
|
26
26
|
def create_challenge!(username)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
code = generate_otp_code
|
|
28
|
+
|
|
29
|
+
cc = StandardId::CodeChallenge.create!(
|
|
30
|
+
realm: "authentication",
|
|
31
|
+
channel: connection_type,
|
|
32
|
+
target: username,
|
|
33
|
+
code: code,
|
|
31
34
|
expires_at: 10.minutes.from_now,
|
|
32
35
|
ip_address: request.remote_ip,
|
|
33
36
|
user_agent: request.user_agent
|
|
34
37
|
)
|
|
38
|
+
cc
|
|
35
39
|
end
|
|
36
40
|
|
|
37
41
|
def generate_otp_code
|
data/lib/standard_id/version.rb
CHANGED
data/lib/standard_id.rb
CHANGED
|
@@ -2,7 +2,7 @@ require "standard_id/version"
|
|
|
2
2
|
require "standard_id/engine"
|
|
3
3
|
require "standard_id/web_engine"
|
|
4
4
|
require "standard_id/api_engine"
|
|
5
|
-
require "standard_id/config"
|
|
5
|
+
require "standard_id/config/schema"
|
|
6
6
|
require "standard_id/errors"
|
|
7
7
|
require "standard_id/jwt_service"
|
|
8
8
|
require "standard_id/web/session_manager"
|
|
@@ -12,6 +12,7 @@ require "standard_id/api/session_manager"
|
|
|
12
12
|
require "standard_id/api/token_manager"
|
|
13
13
|
require "standard_id/api/authentication_guard"
|
|
14
14
|
require "standard_id/oauth/base_request_flow"
|
|
15
|
+
require "standard_id/oauth/token_lifetime_resolver"
|
|
15
16
|
require "standard_id/oauth/token_grant_flow"
|
|
16
17
|
require "standard_id/oauth/client_credentials_flow"
|
|
17
18
|
require "standard_id/oauth/authorization_code_flow"
|
|
@@ -30,12 +31,16 @@ require "standard_id/passwordless/sms_strategy"
|
|
|
30
31
|
|
|
31
32
|
module StandardId
|
|
32
33
|
class << self
|
|
33
|
-
def configure
|
|
34
|
-
|
|
34
|
+
def configure(&block)
|
|
35
|
+
StandardConfig.configure(&block)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def register(scope_name, resolver_proc)
|
|
39
|
+
StandardConfig.config.register(scope_name, resolver_proc)
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
def config
|
|
38
|
-
|
|
43
|
+
StandardConfig.config
|
|
39
44
|
end
|
|
40
45
|
|
|
41
46
|
def cache_store
|
|
@@ -45,5 +50,9 @@ module StandardId
|
|
|
45
50
|
def logger
|
|
46
51
|
@logger ||= config.logger || Rails.logger
|
|
47
52
|
end
|
|
53
|
+
|
|
54
|
+
def account_class
|
|
55
|
+
config.account_class_name.constantize
|
|
56
|
+
end
|
|
48
57
|
end
|
|
49
58
|
end
|
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.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jaryl Sim
|
|
@@ -83,6 +83,12 @@ files:
|
|
|
83
83
|
- app/controllers/standard_id/web/reset_password/start_controller.rb
|
|
84
84
|
- app/controllers/standard_id/web/sessions_controller.rb
|
|
85
85
|
- app/controllers/standard_id/web/signup_controller.rb
|
|
86
|
+
- app/controllers/standard_id/web/verify_email/base_controller.rb
|
|
87
|
+
- app/controllers/standard_id/web/verify_email/confirm_controller.rb
|
|
88
|
+
- app/controllers/standard_id/web/verify_email/start_controller.rb
|
|
89
|
+
- app/controllers/standard_id/web/verify_phone/base_controller.rb
|
|
90
|
+
- app/controllers/standard_id/web/verify_phone/confirm_controller.rb
|
|
91
|
+
- app/controllers/standard_id/web/verify_phone/start_controller.rb
|
|
86
92
|
- app/forms/standard_id/web/reset_password_confirm_form.rb
|
|
87
93
|
- app/forms/standard_id/web/reset_password_start_form.rb
|
|
88
94
|
- app/forms/standard_id/web/signup_form.rb
|
|
@@ -96,12 +102,12 @@ files:
|
|
|
96
102
|
- app/models/standard_id/browser_session.rb
|
|
97
103
|
- app/models/standard_id/client_application.rb
|
|
98
104
|
- app/models/standard_id/client_secret_credential.rb
|
|
105
|
+
- app/models/standard_id/code_challenge.rb
|
|
99
106
|
- app/models/standard_id/credential.rb
|
|
100
107
|
- app/models/standard_id/device_session.rb
|
|
101
108
|
- app/models/standard_id/email_identifier.rb
|
|
102
109
|
- app/models/standard_id/identifier.rb
|
|
103
110
|
- app/models/standard_id/password_credential.rb
|
|
104
|
-
- app/models/standard_id/passwordless_challenge.rb
|
|
105
111
|
- app/models/standard_id/phone_number_identifier.rb
|
|
106
112
|
- app/models/standard_id/service_session.rb
|
|
107
113
|
- app/models/standard_id/session.rb
|
|
@@ -124,15 +130,20 @@ files:
|
|
|
124
130
|
- db/migrate/20250831154635_create_standard_id_sessions.rb
|
|
125
131
|
- db/migrate/20250901134520_create_standard_id_client_secret_credentials.rb
|
|
126
132
|
- db/migrate/20250903063000_create_standard_id_authorization_codes.rb
|
|
127
|
-
- db/migrate/
|
|
133
|
+
- db/migrate/20250907090000_create_standard_id_code_challenges.rb
|
|
128
134
|
- lib/generators/standard_id/install/install_generator.rb
|
|
129
135
|
- lib/generators/standard_id/install/templates/standard_id.rb
|
|
136
|
+
- lib/standard_config.rb
|
|
137
|
+
- lib/standard_config/config.rb
|
|
138
|
+
- lib/standard_config/config_provider.rb
|
|
139
|
+
- lib/standard_config/manager.rb
|
|
140
|
+
- lib/standard_config/schema.rb
|
|
130
141
|
- lib/standard_id.rb
|
|
131
142
|
- lib/standard_id/api/authentication_guard.rb
|
|
132
143
|
- lib/standard_id/api/session_manager.rb
|
|
133
144
|
- lib/standard_id/api/token_manager.rb
|
|
134
145
|
- lib/standard_id/api_engine.rb
|
|
135
|
-
- lib/standard_id/config.rb
|
|
146
|
+
- lib/standard_id/config/schema.rb
|
|
136
147
|
- lib/standard_id/engine.rb
|
|
137
148
|
- lib/standard_id/errors.rb
|
|
138
149
|
- lib/standard_id/jwt_service.rb
|
|
@@ -149,6 +160,7 @@ files:
|
|
|
149
160
|
- lib/standard_id/oauth/subflows/social_login_grant.rb
|
|
150
161
|
- lib/standard_id/oauth/subflows/traditional_code_grant.rb
|
|
151
162
|
- lib/standard_id/oauth/token_grant_flow.rb
|
|
163
|
+
- lib/standard_id/oauth/token_lifetime_resolver.rb
|
|
152
164
|
- lib/standard_id/passwordless/base_strategy.rb
|
|
153
165
|
- lib/standard_id/passwordless/email_strategy.rb
|
|
154
166
|
- lib/standard_id/passwordless/sms_strategy.rb
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
class CreateStandardIdPasswordlessChallenges < ActiveRecord::Migration[8.0]
|
|
2
|
-
def change
|
|
3
|
-
create_table :standard_id_passwordless_challenges do |t|
|
|
4
|
-
t.string :connection_type, null: false
|
|
5
|
-
|
|
6
|
-
t.string :username, null: false
|
|
7
|
-
t.string :code, null: false
|
|
8
|
-
|
|
9
|
-
t.datetime :expires_at, null: false
|
|
10
|
-
t.datetime :used_at
|
|
11
|
-
|
|
12
|
-
t.string :ip_address
|
|
13
|
-
t.text :user_agent
|
|
14
|
-
|
|
15
|
-
t.timestamps
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
add_index :standard_id_passwordless_challenges, [:connection_type, :username, :code], name: "index_passwordless_challenges_on_lookup"
|
|
19
|
-
add_index :standard_id_passwordless_challenges, :expires_at
|
|
20
|
-
add_index :standard_id_passwordless_challenges, :used_at
|
|
21
|
-
end
|
|
22
|
-
end
|