add_auth 0.2.1 → 0.3.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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -0
  3. data/README.md +57 -18
  4. data/ROADMAP.md +260 -242
  5. data/SECURITY.md +6 -0
  6. data/app/controllers/add_auth/accounts_controller.rb +138 -0
  7. data/app/controllers/add_auth/assets_controller.rb +2 -1
  8. data/app/controllers/add_auth/external_identities_controller.rb +56 -0
  9. data/app/controllers/add_auth/mobile_sessions_controller.rb +120 -0
  10. data/app/controllers/add_auth/provider_sign_ins_controller.rb +248 -0
  11. data/app/helpers/add_auth/sign_ins_helper.rb +2 -1
  12. data/app/jobs/add_auth/account_delivery_job.rb +14 -0
  13. data/app/jobs/add_auth/account_request_job.rb +17 -0
  14. data/app/mailers/add_auth/account_mailer.rb +12 -0
  15. data/app/views/add_auth/account_mailer/link.text.erb +7 -0
  16. data/app/views/add_auth/accounts/_check_email.html.erb +5 -0
  17. data/app/views/add_auth/accounts/_delete.html.erb +6 -0
  18. data/app/views/add_auth/accounts/_email.html.erb +12 -0
  19. data/app/views/add_auth/accounts/_invalid_proof.html.erb +5 -0
  20. data/app/views/add_auth/accounts/_password.html.erb +12 -0
  21. data/app/views/add_auth/accounts/_proof.html.erb +16 -0
  22. data/app/views/add_auth/accounts/_register.html.erb +17 -0
  23. data/app/views/add_auth/accounts/_request.html.erb +14 -0
  24. data/app/views/add_auth/accounts/_unavailable.html.erb +3 -0
  25. data/app/views/add_auth/external_identities/_index.html.erb +22 -0
  26. data/app/views/add_auth/external_identities/_unavailable.html.erb +3 -0
  27. data/app/views/add_auth/passkeys/_controls.html.erb +3 -1
  28. data/app/views/add_auth/provider_sign_ins/_enrollment.html.erb +12 -0
  29. data/app/views/add_auth/provider_sign_ins/_failure.html.erb +3 -0
  30. data/app/views/add_auth/provider_sign_ins/_prepare.html.erb +7 -0
  31. data/app/views/add_auth/reauthentications/_form.html.erb +9 -0
  32. data/app/views/add_auth/sessions/_list.html.erb +1 -1
  33. data/app/views/add_auth/sessions/index.html.erb +7 -0
  34. data/app/views/add_auth/sign_ins/_confirmation.html.erb +1 -0
  35. data/app/views/add_auth/sign_ins/_form.html.erb +17 -0
  36. data/app/views/add_auth/sign_ins/_remember.html.erb +6 -0
  37. data/app/views/layouts/add_auth/authentication.html.erb +4 -3
  38. data/exe/add_auth-preflight +26 -0
  39. data/lib/add_auth/configuration.rb +78 -4
  40. data/lib/add_auth/core/access_policy.rb +11 -1
  41. data/lib/add_auth/core/account_lifecycle.rb +251 -0
  42. data/lib/add_auth/core/account_policy.rb +50 -0
  43. data/lib/add_auth/core/external_identities/evidence.rb +98 -0
  44. data/lib/add_auth/core/external_identities.rb +278 -0
  45. data/lib/add_auth/core/intake.rb +6 -1
  46. data/lib/add_auth/core/maintenance.rb +5 -3
  47. data/lib/add_auth/core/migration/account_adoption.rb +79 -0
  48. data/lib/add_auth/core/migration/readiness.rb +41 -0
  49. data/lib/add_auth/core/mobile_authentication.rb +35 -0
  50. data/lib/add_auth/core/mobile_handoffs.rb +83 -0
  51. data/lib/add_auth/core/mobile_profile.rb +46 -0
  52. data/lib/add_auth/core/mobile_response.rb +12 -0
  53. data/lib/add_auth/core/native_authentication.rb +77 -0
  54. data/lib/add_auth/core/passwords/bcrypt_support.rb +28 -0
  55. data/lib/add_auth/core/passwords/credential.rb +49 -0
  56. data/lib/add_auth/core/passwords/legacy_bcrypt.rb +43 -0
  57. data/lib/add_auth/core/passwords/lifecycle.rb +60 -0
  58. data/lib/add_auth/core/remaining_factors.rb +24 -0
  59. data/lib/add_auth/core/sessions.rb +102 -17
  60. data/lib/add_auth/core/step_up.rb +13 -1
  61. data/lib/add_auth/migration/static_inventory.rb +116 -0
  62. data/lib/add_auth/rails/account_password_entry.rb +24 -0
  63. data/lib/add_auth/rails/authentication.rb +1 -1
  64. data/lib/add_auth/rails/authentication_pages.rb +5 -0
  65. data/lib/add_auth/rails/doctor.rb +73 -3
  66. data/lib/add_auth/rails/ejection.rb +1 -1
  67. data/lib/add_auth/rails/engine.rb +6 -1
  68. data/lib/add_auth/rails/migration/account_store.rb +41 -0
  69. data/lib/add_auth/rails/migration/effective_inventory.rb +162 -0
  70. data/lib/add_auth/rails/migration/key_type.rb +23 -0
  71. data/lib/add_auth/rails/migration/source_bridge.rb +53 -0
  72. data/lib/add_auth/rails/password_adoption.rb +37 -0
  73. data/lib/add_auth/rails/provider_enrollment.rb +61 -0
  74. data/lib/add_auth/rails/provider_libraries/apple_form_post_correlation.rb +127 -0
  75. data/lib/add_auth/rails/provider_libraries/apple_jwks.rb +68 -0
  76. data/lib/add_auth/rails/provider_libraries/apple_native.rb +55 -0
  77. data/lib/add_auth/rails/provider_libraries/callback_route.rb +16 -0
  78. data/lib/add_auth/rails/provider_libraries/omniauth.rb +136 -0
  79. data/lib/add_auth/rails/provider_libraries/omniauth_correlation.rb +107 -0
  80. data/lib/add_auth/rails/provider_libraries/openid_connect.rb +62 -0
  81. data/lib/add_auth/rails/provider_libraries/request_protection.rb +43 -0
  82. data/lib/add_auth/rails/rate_limit_cache.rb +17 -0
  83. data/lib/add_auth/rails/runtime.rb +173 -9
  84. data/lib/add_auth/rails/stores/account_credentials.rb +44 -0
  85. data/lib/add_auth/rails/stores/account_lock.rb +16 -7
  86. data/lib/add_auth/rails/stores/account_tokens.rb +96 -0
  87. data/lib/add_auth/rails/stores/authority.rb +28 -0
  88. data/lib/add_auth/rails/stores/commit_dispatch.rb +32 -0
  89. data/lib/add_auth/rails/stores/external_identities.rb +91 -0
  90. data/lib/add_auth/rails/stores/maintenance.rb +1 -1
  91. data/lib/add_auth/rails/stores/mobile_handoffs.rb +53 -0
  92. data/lib/add_auth/rails/stores/security_events.rb +3 -6
  93. data/lib/add_auth/rails/user_lifecycle.rb +8 -10
  94. data/lib/add_auth/result.rb +1 -0
  95. data/lib/add_auth/version.rb +1 -1
  96. data/lib/add_auth.rb +4 -0
  97. data/lib/generators/add_auth/accounts/accounts_generator.rb +52 -0
  98. data/lib/generators/add_auth/accounts/templates/add_add_auth_accounts.rb.tt +49 -0
  99. data/lib/generators/add_auth/accounts/templates/add_auth_account_token.rb +6 -0
  100. data/lib/generators/add_auth/accounts/templates/add_auth_address_claim.rb +6 -0
  101. data/lib/generators/add_auth/devise_accounts/devise_accounts_generator.rb +23 -0
  102. data/lib/generators/add_auth/devise_accounts/templates/prepare_add_auth_devise_accounts.rb.tt +17 -0
  103. data/lib/generators/add_auth/email_link/templates/add_auth_challenge.js +1 -0
  104. data/lib/generators/add_auth/email_tokens/templates/create_add_auth_sign_in_tokens.rb.tt +3 -1
  105. data/lib/generators/add_auth/external_identities/external_identities_generator.rb +52 -0
  106. data/lib/generators/add_auth/external_identities/templates/add_add_auth_external_enrollment.rb.tt +5 -0
  107. data/lib/generators/add_auth/external_identities/templates/add_add_auth_external_identity_validity.rb.tt +5 -0
  108. data/lib/generators/add_auth/external_identities/templates/add_auth_external_identity.rb +4 -0
  109. data/lib/generators/add_auth/external_identities/templates/add_auth_external_transaction.rb +6 -0
  110. data/lib/generators/add_auth/external_identities/templates/create_add_auth_external_identities.rb.tt +50 -0
  111. data/lib/generators/add_auth/external_identities/templates/providers.rb +51 -0
  112. data/lib/generators/add_auth/install/templates/initializer.rb +7 -1
  113. data/lib/generators/add_auth/javascript/templates/passkey.js +8 -5
  114. data/lib/generators/add_auth/mobile_sessions/mobile_sessions_generator.rb +48 -0
  115. data/lib/generators/add_auth/mobile_sessions/templates/add_add_auth_mobile_sessions.rb.tt +9 -0
  116. data/lib/generators/add_auth/mobile_sessions/templates/add_auth_mobile_handoff.rb +5 -0
  117. data/lib/generators/add_auth/mobile_sessions/templates/create_add_auth_mobile_handoffs.rb.tt +27 -0
  118. data/lib/generators/add_auth/mobile_sessions/templates/mobile.rb +8 -0
  119. data/lib/generators/add_auth/notifications/templates/create_add_auth_security_events.rb.tt +3 -1
  120. data/lib/generators/add_auth/passkeys/templates/add_add_auth_passkeys.rb.tt +7 -3
  121. data/lib/generators/add_auth/step_up/templates/add_add_auth_reauthentication.rb.tt +3 -1
  122. data/lib/tasks/add_auth.rake +18 -1
  123. metadata +86 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33de30a9b51e6aff4236af059703155e8eeed6692497df9657c2958d37d21536
4
- data.tar.gz: a3dd63d2b854c69f4f17af73d067f7dc5b9c5fd3105ce9b45cd2d1aec8eb943f
3
+ metadata.gz: 5856e424011a6e4b49dabd271324aadd29862aad6e0dc5a8b5e06c6e1ea27186
4
+ data.tar.gz: 5169c854a4428c4daee558abb68208eae29a1f5ae98b91478c9e803ccb3383d4
5
5
  SHA512:
6
- metadata.gz: ac89ed45158b07a68a94fba2c832781b1f5a38f732217f29992865dc0b0f532ae6e0e70f79c746b1a962f07cad4f7ec0cadff71485d79d1c569af07ef2c3887c
7
- data.tar.gz: 99459566fa90408261c16d2cd3453c168e3800a913cdbe48b44ebc4b64dd13a2cddda3661097b01d12f39cc89415b395158fb0c50b6fa335412fa5544a91f022
6
+ metadata.gz: ee5a6a0df85d2719372eba860f0afb1030c3c1ccaf5644fd0ece45395e0f648bd689e0cb8b8b48a04ffa3fb5d066aab5aa8d4925ba502d0db26e8922c48302a9
7
+ data.tar.gz: 5b9bcc71dd3f72271dd140eb9b335cc93feb6222ec4a95e012afc2eaaa6f96945cd3ff7193e2fbfd816dc4e66bcaea293f9075ae9948931892952a4ba9b25b74
data/CHANGELOG.md CHANGED
@@ -1,5 +1,41 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 — 2026-09-09
4
+
5
+ Optional account lifecycle, bounded Devise migration and native authentication.
6
+ The standard Rails-generator installation remains supported; enable only the
7
+ additional capabilities your host needs. The latest-0.x support policy continues.
8
+
9
+ - Add read-only Devise inventory, additive account preparation, explicit legacy
10
+ password adoption and retired-source write fences. Preserve account IDs and
11
+ reject ambiguous identifier/credential conversions.
12
+ - Add optional registration, confirmation/reconfirmation, reset, lock/unlock,
13
+ account changes and remembered sessions with shared Core policy and delivery.
14
+ - Integrate maintained provider libraries without owning their registrations,
15
+ protocol exchange, unrelated routes or provider API credentials. Preserve
16
+ identity ownership and require independent enrollment confirmation.
17
+ - Add opt-in finite native sessions, account-scoped revocation, S256-bound
18
+ single-use browser handoffs and optional nonce-bound Apple token verification.
19
+ Mobile duration settings are separate from browser settings; refresh-token
20
+ families are not part of this finite profile.
21
+ - Verify generated/ejected pages with Turbo, ordinary JavaScript without Turbo
22
+ and permitted no-JS. Add populated migration, checkpoint, compatibility
23
+ rollback, provider and native integration fixtures.
24
+
25
+ ## 0.2.2 — 2026-09-08
26
+
27
+ - Reject Solid Cache as an authentication rate-limit store: simultaneous first
28
+ increments can be lost. Runtime fails closed and doctor explains how to
29
+ configure a separate atomic store. Solid Queue and ordinary application
30
+ caching remain independent choices. No schema, cookie or job-format change.
31
+ - Add checksum-pinned upgrades from the published 0.2.1 package to the candidate
32
+ and back, including persisted authority, pending delivery and customized
33
+ ejections; run this acceptance on every supported Ruby/Rails CI combination.
34
+ - Verify Solid Queue with a separate queue database, demonstrate Solid Cache
35
+ counter unsuitability on PostgreSQL, and measure bounded maintenance.
36
+ - Refresh immutable checkout action pins to 7.0.1 and add upgrade/compatibility
37
+ guidance. See the upgrade guide before changing a deployed bundle.
38
+
3
39
  ## 0.2.1 — 2026-09-07
4
40
 
5
41
  - Install release dependencies into RubyGems' normal gem path so the attestation
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # AddAuth
2
2
 
3
- **0.2.1:** password, email-link and passkey sign-in extend
3
+ **0.3.0:** password, email-link and passkey sign-in extend
4
4
  Rails' generated authentication. AddAuth adds hardened sessions, verification
5
5
  for sensitive actions, passkey management and email recovery with an optional
6
6
  strict policy. Turnstile and reCAPTCHA integrations are available. See
@@ -9,6 +9,11 @@ strict policy. Turnstile and reCAPTCHA integrations are available. See
9
9
  AddAuth builds on top of Rails 8's built-in login system instead of
10
10
  replacing it -- it keeps using your existing `User` and `Session` models.
11
11
 
12
+ Version 0.3.0 adds optional account lifecycle, bounded Devise migration,
13
+ provider-library integration and finite Android/iOS sessions. See the
14
+ [migration guide](https://addauthgem.com/migrating-from-devise/) before changing
15
+ an existing Devise app; do not run the Rails generator over its custom files.
16
+
12
17
  Read the [documentation](https://addauthgem.com) for setup guides, configuration
13
18
  reference and troubleshooting.
14
19
 
@@ -18,18 +23,18 @@ Install the `add_auth` gem from RubyGems through your Rails app’s Gemfile,
18
23
  then enable password and email-link sign-in. Use Ruby 3.3+ and Rails 8.0+
19
24
  with Active Record, and run the commands below from your Rails app’s root.
20
25
 
21
- **Release availability:** these commands require the published `0.2.1` package.
26
+ **Release availability:** these commands require the published `0.3.0` package.
22
27
  If it is not yet listed on [RubyGems](https://rubygems.org/gems/add_auth/versions),
23
28
  wait for publication; see [release status](https://addauthgem.com/release-status/).
24
29
  Start in your app’s development environment; use the deployment settings
25
30
  below before enabling sign-in for users.
26
31
 
27
32
  1. Keep `source "https://rubygems.org"` in your app’s Gemfile and add the
28
- 0.2 release line:
33
+ 0.3 release line:
29
34
 
30
35
  ```ruby
31
36
  # Gemfile
32
- gem "add_auth", "~> 0.2.1"
37
+ gem "add_auth", "~> 0.3.0"
33
38
  ```
34
39
 
35
40
  Bundler downloads the package from RubyGems and records the resolved
@@ -39,8 +44,8 @@ below before enabling sign-in for users.
39
44
  bundle install
40
45
  ```
41
46
 
42
- 2. If your app doesn't already have Rails' built-in login system, add it
43
- first:
47
+ 2. For a fresh app without an existing authentication system, generate
48
+ Rails' built-in login system:
44
49
 
45
50
  ```sh
46
51
  bin/rails generate authentication
@@ -101,12 +106,18 @@ generators again later -- they won't overwrite changes you've already made.
101
106
  AddAuth.configure do |config|
102
107
  config.base_url = "https://accounts.example.com"
103
108
  config.mail_from = "Accounts <sign-in@example.com>"
104
- config.rate_limit_store = Rails.cache
109
+ config.rate_limit_store = ActiveSupport::Cache::RedisCacheStore.new(
110
+ url: ENV.fetch("AUTH_REDIS_URL"), namespace: "add_auth"
111
+ )
105
112
  # Only let certain accounts sign in, e.g. skip unconfirmed or banned users:
106
113
  # config.eligible = ->(user) { user.confirmed? && !user.disabled? }
107
114
  end
108
115
  ```
109
116
 
117
+ For this example, add `gem "redis", "~> 5.4"` to the host Gemfile, run
118
+ `bundle install`, and configure `AUTH_REDIS_URL` for every web/worker/scheduler
119
+ process. Keep their namespace identical.
120
+
110
121
  Before real users touch this, make sure of three things:
111
122
 
112
123
  - **Email actually sends.** Configure Action Mailer's SMTP settings for
@@ -115,9 +126,11 @@ Before real users touch this, make sure of three things:
115
126
  background job, so use a real Active Job backend like Sidekiq or Solid
116
127
  Queue -- not Rails' default in-memory one, which forgets everything on
117
128
  deploy.
118
- - **Your cache is shared across servers**, e.g. Redis, Memcached or Solid
119
- Cache -- not each server's own memory. Otherwise sign-in rate limits only
120
- apply per-server instead of across your whole app.
129
+ - **Abuse counters are shared and atomic**, including the first increment and
130
+ expiry under concurrent requests. RedisCacheStore has local acceptance. Solid
131
+ Cache is unsuitable: its absent-row increment can lose concurrent requests.
132
+ Keep application caching separate from `rate_limit_store`; local MemoryStore
133
+ is for a single-process trial. Other adapters require their own atomic/TTL proof.
121
134
 
122
135
  Then schedule this to run at least once a minute, however you run scheduled
123
136
  jobs (cron, `whenever`, your platform's scheduler):
@@ -478,6 +491,13 @@ Selenium in the host test bundle. AddAuth itself uses RSpec.
478
491
 
479
492
  ## Operations and rollback
480
493
 
494
+ See the [persisted-host upgrade guide](https://addauthgem.com/upgrading/) and
495
+ [integration boundaries](https://addauthgem.com/compatibility/) before changing
496
+ a deployed bundle. The published 0.2.1 doctor cannot detect Solid Cache's
497
+ concurrent-initialization race; 0.2.2 rejects that known
498
+ incompatible adapter at runtime and reports a separate-store remedy in doctor.
499
+
500
+
481
501
  Run doctor after migrations and template upgrades. Expand schemas before enabling
482
502
  features; generators preserve existing sessions and credentials. Keep the new
483
503
  reader during rollback while browser-bound proofs or strict accounts exist.
@@ -518,14 +538,33 @@ or recovery procedures work in production.
518
538
 
519
539
  ## Scope
520
540
 
521
- AddAuth 0.2 implements password/email/passkey sign-in, session
522
- adoption and management, purpose-bound verification, passkey recovery and
523
- strict account policy, durable security mail, and challenge adapters. Account
524
- provisioning, address confirmation and password reset remain host responsibilities.
525
- Release acceptance uses local real-database, generated-host, browser and
526
- SMTP/queue/cache tests. Hosts verify their own live providers and supported
527
- physical devices before deployment. Recovery codes and AddAuth-owned password
528
- policy remain deferred.
541
+ AddAuth 0.3 implements password/email/passkey sign-in, session adoption and
542
+ management, purpose-bound verification, passkey recovery and strict account
543
+ policy, durable security mail and challenge adapters. Optional account lifecycle
544
+ adds registration, confirmation/reconfirmation, password reset, lock/unlock and
545
+ account changes. Hosts retain account eligibility, resource authorization and
546
+ provider registrations.
547
+
548
+ ## Optional integrations in 0.3.0
549
+
550
+ Enable bounded [Devise migration](https://addauthgem.com/migrating-from-devise/),
551
+ [account lifecycle](https://addauthgem.com/account-lifecycle/),
552
+ [provider sign-in](https://addauthgem.com/omniauth/) and
553
+ [Android/iOS sessions](https://addauthgem.com/mobile-authentication/) independently.
554
+ Provider protocol handling stays with maintained libraries. Native sessions use
555
+ finite expiry; the verified profile is 30 days absolute and 14 days idle, with
556
+ fresh sign-in after expiry. Refresh-token families are not included.
557
+
558
+ Migration evidence covers the documented Devise 5.0.4 source profiles, including
559
+ integer and UUID accounts; it does not establish universal Devise-module parity.
560
+ Preserve current credentials and revocations during cutover and compatible
561
+ rollback. Follow the migration guide before removing Devise or retiring columns.
562
+
563
+ Release acceptance uses local real-database, generated-host, browser,
564
+ SMTP/queue/cache and native-consumer tests. Hosts verify their own live providers
565
+ and supported physical devices before deployment. Recovery codes and multiple
566
+ realms remain deferred. See [ROADMAP.md](ROADMAP.md) for scope and progress, and
567
+ [CONTRIBUTING.md](CONTRIBUTING.md) for synthetic acceptance commands.
529
568
 
530
569
  ## Roadmap
531
570