standard_id 0.1.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.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/stylesheets/standard_id/application.css +15 -0
  6. data/app/controllers/concerns/standard_id/api_authentication.rb +29 -0
  7. data/app/controllers/concerns/standard_id/web_authentication.rb +51 -0
  8. data/app/controllers/standard_id/api/authorization_controller.rb +73 -0
  9. data/app/controllers/standard_id/api/base_controller.rb +61 -0
  10. data/app/controllers/standard_id/api/oauth/base_controller.rb +22 -0
  11. data/app/controllers/standard_id/api/oauth/tokens_controller.rb +44 -0
  12. data/app/controllers/standard_id/api/oidc/logout_controller.rb +50 -0
  13. data/app/controllers/standard_id/api/passwordless_controller.rb +38 -0
  14. data/app/controllers/standard_id/api/providers_controller.rb +175 -0
  15. data/app/controllers/standard_id/api/userinfo_controller.rb +36 -0
  16. data/app/controllers/standard_id/web/account_controller.rb +32 -0
  17. data/app/controllers/standard_id/web/auth/callback/providers_controller.rb +126 -0
  18. data/app/controllers/standard_id/web/base_controller.rb +14 -0
  19. data/app/controllers/standard_id/web/login_controller.rb +69 -0
  20. data/app/controllers/standard_id/web/logout_controller.rb +20 -0
  21. data/app/controllers/standard_id/web/reset_password/confirm_controller.rb +46 -0
  22. data/app/controllers/standard_id/web/reset_password/start_controller.rb +27 -0
  23. data/app/controllers/standard_id/web/sessions_controller.rb +26 -0
  24. data/app/controllers/standard_id/web/signup_controller.rb +83 -0
  25. data/app/forms/standard_id/web/reset_password_confirm_form.rb +37 -0
  26. data/app/forms/standard_id/web/reset_password_start_form.rb +38 -0
  27. data/app/forms/standard_id/web/signup_form.rb +65 -0
  28. data/app/helpers/standard_id/application_helper.rb +4 -0
  29. data/app/jobs/standard_id/application_job.rb +4 -0
  30. data/app/mailers/standard_id/application_mailer.rb +6 -0
  31. data/app/models/concerns/standard_id/account_associations.rb +14 -0
  32. data/app/models/concerns/standard_id/credentiable.rb +12 -0
  33. data/app/models/standard_id/application_record.rb +5 -0
  34. data/app/models/standard_id/authorization_code.rb +86 -0
  35. data/app/models/standard_id/browser_session.rb +27 -0
  36. data/app/models/standard_id/client_application.rb +143 -0
  37. data/app/models/standard_id/client_secret_credential.rb +63 -0
  38. data/app/models/standard_id/credential.rb +16 -0
  39. data/app/models/standard_id/device_session.rb +38 -0
  40. data/app/models/standard_id/email_identifier.rb +5 -0
  41. data/app/models/standard_id/identifier.rb +25 -0
  42. data/app/models/standard_id/password_credential.rb +24 -0
  43. data/app/models/standard_id/passwordless_challenge.rb +30 -0
  44. data/app/models/standard_id/phone_number_identifier.rb +5 -0
  45. data/app/models/standard_id/service_session.rb +44 -0
  46. data/app/models/standard_id/session.rb +54 -0
  47. data/app/models/standard_id/username_identifier.rb +5 -0
  48. data/app/views/standard_id/web/account/edit.html.erb +26 -0
  49. data/app/views/standard_id/web/account/show.html.erb +31 -0
  50. data/app/views/standard_id/web/login/show.html.erb +108 -0
  51. data/app/views/standard_id/web/reset_password/confirm/show.html.erb +27 -0
  52. data/app/views/standard_id/web/reset_password/start/show.html.erb +20 -0
  53. data/app/views/standard_id/web/sessions/index.html.erb +112 -0
  54. data/app/views/standard_id/web/signup/show.html.erb +96 -0
  55. data/config/initializers/generators.rb +9 -0
  56. data/config/initializers/migration_helpers.rb +32 -0
  57. data/config/routes/api.rb +24 -0
  58. data/config/routes/web.rb +26 -0
  59. data/db/migrate/20250830000000_create_standard_id_client_applications.rb +56 -0
  60. data/db/migrate/20250830171553_create_standard_id_password_credentials.rb +10 -0
  61. data/db/migrate/20250830232800_create_standard_id_identifiers.rb +17 -0
  62. data/db/migrate/20250831075703_create_standard_id_credentials.rb +10 -0
  63. data/db/migrate/20250831154635_create_standard_id_sessions.rb +43 -0
  64. data/db/migrate/20250901134520_create_standard_id_client_secret_credentials.rb +20 -0
  65. data/db/migrate/20250903063000_create_standard_id_authorization_codes.rb +46 -0
  66. data/db/migrate/20250903135906_create_standard_id_passwordless_challenges.rb +22 -0
  67. data/lib/generators/standard_id/install/install_generator.rb +14 -0
  68. data/lib/generators/standard_id/install/templates/standard_id.rb +11 -0
  69. data/lib/standard_id/api/authentication_guard.rb +20 -0
  70. data/lib/standard_id/api/session_manager.rb +39 -0
  71. data/lib/standard_id/api/token_manager.rb +50 -0
  72. data/lib/standard_id/api_engine.rb +7 -0
  73. data/lib/standard_id/config.rb +69 -0
  74. data/lib/standard_id/engine.rb +5 -0
  75. data/lib/standard_id/errors.rb +55 -0
  76. data/lib/standard_id/jwt_service.rb +50 -0
  77. data/lib/standard_id/oauth/authorization_code_authorization_flow.rb +47 -0
  78. data/lib/standard_id/oauth/authorization_code_flow.rb +53 -0
  79. data/lib/standard_id/oauth/authorization_flow.rb +91 -0
  80. data/lib/standard_id/oauth/base_request_flow.rb +43 -0
  81. data/lib/standard_id/oauth/client_credentials_flow.rb +38 -0
  82. data/lib/standard_id/oauth/implicit_authorization_flow.rb +79 -0
  83. data/lib/standard_id/oauth/password_flow.rb +70 -0
  84. data/lib/standard_id/oauth/passwordless_otp_flow.rb +87 -0
  85. data/lib/standard_id/oauth/refresh_token_flow.rb +61 -0
  86. data/lib/standard_id/oauth/subflows/base.rb +19 -0
  87. data/lib/standard_id/oauth/subflows/social_login_grant.rb +66 -0
  88. data/lib/standard_id/oauth/subflows/traditional_code_grant.rb +52 -0
  89. data/lib/standard_id/oauth/token_grant_flow.rb +107 -0
  90. data/lib/standard_id/passwordless/base_strategy.rb +67 -0
  91. data/lib/standard_id/passwordless/email_strategy.rb +27 -0
  92. data/lib/standard_id/passwordless/sms_strategy.rb +29 -0
  93. data/lib/standard_id/version.rb +3 -0
  94. data/lib/standard_id/web/authentication_guard.rb +23 -0
  95. data/lib/standard_id/web/session_manager.rb +71 -0
  96. data/lib/standard_id/web/token_manager.rb +30 -0
  97. data/lib/standard_id/web_engine.rb +7 -0
  98. data/lib/standard_id.rb +49 -0
  99. data/lib/tasks/standard_id_tasks.rake +4 -0
  100. metadata +186 -0
@@ -0,0 +1,71 @@
1
+ module StandardId
2
+ module Web
3
+ class SessionManager
4
+ attr_reader :token_manager, :request, :session, :cookies
5
+
6
+ def initialize(token_manager, request:, session:, cookies:)
7
+ @token_manager = token_manager
8
+ @request = request
9
+ @session = session
10
+ @cookies = cookies
11
+ end
12
+
13
+ def current_session
14
+ Current.session ||= load_current_session
15
+ end
16
+
17
+ def current_account
18
+ Current.account ||= current_session&.account
19
+ end
20
+
21
+ def sign_in_account(account)
22
+ token_manager.create_browser_session(account).tap do |browser_session|
23
+ session[:session_token] = browser_session.token
24
+ Current.session = browser_session
25
+ end
26
+ end
27
+
28
+ def revoke_current_session!
29
+ current_session&.revoke!
30
+ clear_session!
31
+ end
32
+
33
+ def set_remember_cookie(password_credential)
34
+ cookies[:remember_token] = token_manager.create_remember_token(password_credential)
35
+ end
36
+
37
+ def clear_session!
38
+ # TODO: make token key names configurable
39
+ session.delete(:session_token)
40
+ cookies.delete(:remember_token)
41
+
42
+ Current.session = nil
43
+ end
44
+
45
+ private
46
+
47
+ def load_current_session
48
+ Current.session ||= load_session_from_session_token
49
+ Current.session ||= load_session_from_remember_token
50
+
51
+ clear_session! if Current.session.blank? || Current.session.expired? || Current.session.revoked?
52
+
53
+ Current.session
54
+ end
55
+
56
+ def load_session_from_session_token
57
+ StandardId::BrowserSession.eager_load(:account).by_token(session[:session_token]).first
58
+ end
59
+
60
+ def load_session_from_remember_token
61
+ password_credential = StandardId::PasswordCredential.find_by_token_for(:remember_me, cookies[:remember_token])
62
+ return if password_credential.blank?
63
+
64
+ token_manager.create_browser_session(password_credential.account, remember_me: true).tap do |browser_session|
65
+ session[:session_token] = browser_session.token
66
+ cookies[:remember_token] = token_manager.create_remember_token(password_credential)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,30 @@
1
+ module StandardId
2
+ module Web
3
+ class TokenManager
4
+ attr_reader :request
5
+
6
+ def initialize(request)
7
+ @request = request
8
+ end
9
+
10
+ def create_browser_session(account)
11
+ StandardId::BrowserSession.create!(
12
+ account: account,
13
+ ip_address: request.remote_ip,
14
+ user_agent: request.user_agent,
15
+ expires_at: 24.hours.from_now # TODO: make configurable
16
+ )
17
+ end
18
+
19
+ def create_remember_token(password_credential)
20
+ {
21
+ value: password_credential.generate_token_for(:remember_me),
22
+ expires: 30.days.from_now, # TODO: make configurable
23
+ httponly: true,
24
+ secure: request.ssl?,
25
+ same_site: :lax
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ module StandardId
2
+ class WebEngine < ::Rails::Engine
3
+ isolate_namespace StandardId
4
+
5
+ paths["config/routes.rb"] = "config/routes/web.rb"
6
+ end
7
+ end
@@ -0,0 +1,49 @@
1
+ require "standard_id/version"
2
+ require "standard_id/engine"
3
+ require "standard_id/web_engine"
4
+ require "standard_id/api_engine"
5
+ require "standard_id/config"
6
+ require "standard_id/errors"
7
+ require "standard_id/jwt_service"
8
+ require "standard_id/web/session_manager"
9
+ require "standard_id/web/token_manager"
10
+ require "standard_id/web/authentication_guard"
11
+ require "standard_id/api/session_manager"
12
+ require "standard_id/api/token_manager"
13
+ require "standard_id/api/authentication_guard"
14
+ require "standard_id/oauth/base_request_flow"
15
+ require "standard_id/oauth/token_grant_flow"
16
+ require "standard_id/oauth/client_credentials_flow"
17
+ require "standard_id/oauth/authorization_code_flow"
18
+ require "standard_id/oauth/password_flow"
19
+ require "standard_id/oauth/refresh_token_flow"
20
+ require "standard_id/oauth/authorization_flow"
21
+ require "standard_id/oauth/authorization_code_authorization_flow"
22
+ require "standard_id/oauth/implicit_authorization_flow"
23
+ require "standard_id/oauth/subflows/base"
24
+ require "standard_id/oauth/subflows/traditional_code_grant"
25
+ require "standard_id/oauth/subflows/social_login_grant"
26
+ require "standard_id/oauth/passwordless_otp_flow"
27
+ require "standard_id/passwordless/base_strategy"
28
+ require "standard_id/passwordless/email_strategy"
29
+ require "standard_id/passwordless/sms_strategy"
30
+
31
+ module StandardId
32
+ class << self
33
+ def configure
34
+ yield config
35
+ end
36
+
37
+ def config
38
+ @config ||= StandardId::Config.new
39
+ end
40
+
41
+ def cache_store
42
+ @cache_store ||= config.cache_store || Rails.cache
43
+ end
44
+
45
+ def logger
46
+ @logger ||= config.logger || Rails.logger
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :standard_id do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,186 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: standard_id
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jaryl Sim
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rails
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '8.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '8.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: bcrypt
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.1'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.1'
40
+ - !ruby/object:Gem::Dependency
41
+ name: jwt
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.7'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.7'
54
+ description: StandardId is an authentication engine that provides a complete, secure-by-default
55
+ solution for identity management, reducing boilerplate and eliminating common security
56
+ pitfalls.
57
+ email:
58
+ - code@jaryl.dev
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - MIT-LICENSE
64
+ - README.md
65
+ - Rakefile
66
+ - app/assets/stylesheets/standard_id/application.css
67
+ - app/controllers/concerns/standard_id/api_authentication.rb
68
+ - app/controllers/concerns/standard_id/web_authentication.rb
69
+ - app/controllers/standard_id/api/authorization_controller.rb
70
+ - app/controllers/standard_id/api/base_controller.rb
71
+ - app/controllers/standard_id/api/oauth/base_controller.rb
72
+ - app/controllers/standard_id/api/oauth/tokens_controller.rb
73
+ - app/controllers/standard_id/api/oidc/logout_controller.rb
74
+ - app/controllers/standard_id/api/passwordless_controller.rb
75
+ - app/controllers/standard_id/api/providers_controller.rb
76
+ - app/controllers/standard_id/api/userinfo_controller.rb
77
+ - app/controllers/standard_id/web/account_controller.rb
78
+ - app/controllers/standard_id/web/auth/callback/providers_controller.rb
79
+ - app/controllers/standard_id/web/base_controller.rb
80
+ - app/controllers/standard_id/web/login_controller.rb
81
+ - app/controllers/standard_id/web/logout_controller.rb
82
+ - app/controllers/standard_id/web/reset_password/confirm_controller.rb
83
+ - app/controllers/standard_id/web/reset_password/start_controller.rb
84
+ - app/controllers/standard_id/web/sessions_controller.rb
85
+ - app/controllers/standard_id/web/signup_controller.rb
86
+ - app/forms/standard_id/web/reset_password_confirm_form.rb
87
+ - app/forms/standard_id/web/reset_password_start_form.rb
88
+ - app/forms/standard_id/web/signup_form.rb
89
+ - app/helpers/standard_id/application_helper.rb
90
+ - app/jobs/standard_id/application_job.rb
91
+ - app/mailers/standard_id/application_mailer.rb
92
+ - app/models/concerns/standard_id/account_associations.rb
93
+ - app/models/concerns/standard_id/credentiable.rb
94
+ - app/models/standard_id/application_record.rb
95
+ - app/models/standard_id/authorization_code.rb
96
+ - app/models/standard_id/browser_session.rb
97
+ - app/models/standard_id/client_application.rb
98
+ - app/models/standard_id/client_secret_credential.rb
99
+ - app/models/standard_id/credential.rb
100
+ - app/models/standard_id/device_session.rb
101
+ - app/models/standard_id/email_identifier.rb
102
+ - app/models/standard_id/identifier.rb
103
+ - app/models/standard_id/password_credential.rb
104
+ - app/models/standard_id/passwordless_challenge.rb
105
+ - app/models/standard_id/phone_number_identifier.rb
106
+ - app/models/standard_id/service_session.rb
107
+ - app/models/standard_id/session.rb
108
+ - app/models/standard_id/username_identifier.rb
109
+ - app/views/standard_id/web/account/edit.html.erb
110
+ - app/views/standard_id/web/account/show.html.erb
111
+ - app/views/standard_id/web/login/show.html.erb
112
+ - app/views/standard_id/web/reset_password/confirm/show.html.erb
113
+ - app/views/standard_id/web/reset_password/start/show.html.erb
114
+ - app/views/standard_id/web/sessions/index.html.erb
115
+ - app/views/standard_id/web/signup/show.html.erb
116
+ - config/initializers/generators.rb
117
+ - config/initializers/migration_helpers.rb
118
+ - config/routes/api.rb
119
+ - config/routes/web.rb
120
+ - db/migrate/20250830000000_create_standard_id_client_applications.rb
121
+ - db/migrate/20250830171553_create_standard_id_password_credentials.rb
122
+ - db/migrate/20250830232800_create_standard_id_identifiers.rb
123
+ - db/migrate/20250831075703_create_standard_id_credentials.rb
124
+ - db/migrate/20250831154635_create_standard_id_sessions.rb
125
+ - db/migrate/20250901134520_create_standard_id_client_secret_credentials.rb
126
+ - db/migrate/20250903063000_create_standard_id_authorization_codes.rb
127
+ - db/migrate/20250903135906_create_standard_id_passwordless_challenges.rb
128
+ - lib/generators/standard_id/install/install_generator.rb
129
+ - lib/generators/standard_id/install/templates/standard_id.rb
130
+ - lib/standard_id.rb
131
+ - lib/standard_id/api/authentication_guard.rb
132
+ - lib/standard_id/api/session_manager.rb
133
+ - lib/standard_id/api/token_manager.rb
134
+ - lib/standard_id/api_engine.rb
135
+ - lib/standard_id/config.rb
136
+ - lib/standard_id/engine.rb
137
+ - lib/standard_id/errors.rb
138
+ - lib/standard_id/jwt_service.rb
139
+ - lib/standard_id/oauth/authorization_code_authorization_flow.rb
140
+ - lib/standard_id/oauth/authorization_code_flow.rb
141
+ - lib/standard_id/oauth/authorization_flow.rb
142
+ - lib/standard_id/oauth/base_request_flow.rb
143
+ - lib/standard_id/oauth/client_credentials_flow.rb
144
+ - lib/standard_id/oauth/implicit_authorization_flow.rb
145
+ - lib/standard_id/oauth/password_flow.rb
146
+ - lib/standard_id/oauth/passwordless_otp_flow.rb
147
+ - lib/standard_id/oauth/refresh_token_flow.rb
148
+ - lib/standard_id/oauth/subflows/base.rb
149
+ - lib/standard_id/oauth/subflows/social_login_grant.rb
150
+ - lib/standard_id/oauth/subflows/traditional_code_grant.rb
151
+ - lib/standard_id/oauth/token_grant_flow.rb
152
+ - lib/standard_id/passwordless/base_strategy.rb
153
+ - lib/standard_id/passwordless/email_strategy.rb
154
+ - lib/standard_id/passwordless/sms_strategy.rb
155
+ - lib/standard_id/version.rb
156
+ - lib/standard_id/web/authentication_guard.rb
157
+ - lib/standard_id/web/session_manager.rb
158
+ - lib/standard_id/web/token_manager.rb
159
+ - lib/standard_id/web_engine.rb
160
+ - lib/tasks/standard_id_tasks.rake
161
+ homepage: https://github.com/rarebit-one/standard_id
162
+ licenses:
163
+ - MIT
164
+ metadata:
165
+ homepage_uri: https://github.com/rarebit-one/standard_id
166
+ source_code_uri: https://github.com/rarebit-one/standard_id
167
+ changelog_uri: https://github.com/rarebit-one/standard_id/blob/main/CHANGELOG.md
168
+ rdoc_options: []
169
+ require_paths:
170
+ - lib
171
+ required_ruby_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '3.0'
176
+ required_rubygems_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ requirements: []
182
+ rubygems_version: 3.6.7
183
+ specification_version: 4
184
+ summary: A comprehensive authentication engine for Rails, built on the security primitives
185
+ introduced in Rails 7/8.
186
+ test_files: []