veri 0.4.0 → 1.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85a6c779bd69de4d11430630c142f8e5e12e3574d7828f740abc19f0e51d291f
4
- data.tar.gz: 0def50b534c6d728230ec7543fe6a007a518f9abe47e9c0d93aac45e7eb2f59f
3
+ metadata.gz: 17672738e498e3328b8b4cf724e3b30e4ee3fb2f7c1d768344cd0c9d29ced1df
4
+ data.tar.gz: bb8031eb131fce46b349e6881d8b20a18d43c19bf4aba7b41ae1bc6474e5c3cd
5
5
  SHA512:
6
- metadata.gz: 714985726d7e5d04f55dbb1b94a73110a64ed1cb2853f565ddefda540cb13393969a1c4c3ec91e7de310822224dd844031d7d6b0cf57bd3b537c36da5bb6d55b
7
- data.tar.gz: 7f2070d1f1da0260a8061b8abcff5a625245e4388f593d14a6edbdc8c8b496a3b55b5525bfda7a9abaae6bd91ffb218cb0d707d888f14114981c536d99a85e90
6
+ metadata.gz: a6000202fed29f8e3e303d831727c7199cc073dcec3c592e412b3234b3a55c06b5761f4781f7325d7113a44af2c2f4786fff526b7d9bbd30eaebf599e62987e0
7
+ data.tar.gz: eaa49fd164b25daefeb97c505d73b11fb148f433f940594a6e6a349eae8a341f3ad8a716eccd5e47204968685602c895185ee255144cf39680eab610d66e83c1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## v1.0.1
2
+
3
+ ### Bugs
4
+
5
+ - Fixed tenant validation blocking Rails console and database commands when orphaned tenant classes exist
6
+
7
+ ## v1.0.0
8
+
9
+ ### Breaking
10
+
11
+ - Dropped support for Rails 7.1
12
+
13
+ ### Features
14
+
15
+ - Added support for pbkdf2 password hashing algorithm
16
+
17
+ ### Bugs
18
+
19
+ - Fixed error raised on Rails console commands when the database was not yet set up
20
+
1
21
  ## v0.4.0
2
22
 
3
23
  ### Breaking
data/README.md CHANGED
@@ -1,22 +1,21 @@
1
- # Veri: Minimal Authentication Framework for Rails
1
+ # Veri: Minimal Authentication for Rails
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/veri.svg)](http://badge.fury.io/rb/veri)
4
- [![Github Actions badge](https://github.com/brownboxdev/veri/actions/workflows/ci.yml/badge.svg)](https://github.com/brownboxdev/veri/actions/workflows/ci.yml)
4
+ [![Downloads](https://img.shields.io/gem/dt/veri.svg)](https://rubygems.org/gems/veri)
5
+ [![Github Actions badge](https://github.com/enjaku4/veri/actions/workflows/ci.yml/badge.svg)](https://github.com/enjaku4/veri/actions/workflows/ci.yml)
6
+ [![License](https://img.shields.io/github/license/enjaku4/veri.svg)](LICENSE)
5
7
 
6
- Veri is a cookie-based authentication library for Ruby on Rails that provides essential authentication building blocks without imposing business logic. Unlike full-featured solutions, Veri gives you complete control over your authentication flow while handling the complex underlying mechanics of secure password storage and session management.
8
+ Veri is a cookie-based authentication library for Ruby on Rails. Unlike other solutions, Veri doesn't impose business logic or generate controllers, views, and mailers for you. Instead, it provides essential authentication building blocks giving you complete control over your authentication flow while handling the complex underlying mechanics of secure password storage and session management.
7
9
 
8
10
  **Key Features:**
9
11
 
10
12
  - Cookie-based authentication with database-stored sessions
11
- - Multiple password hashing algorithms (argon2, bcrypt, scrypt)
13
+ - Multiple password hashing algorithms (argon2, bcrypt, pbkdf2, scrypt)
14
+ - Multi-tenancy support
12
15
  - Granular session management and control
13
- - Return path handling
14
16
  - User impersonation feature
15
17
  - Account lockout functionality
16
- - Multi-tenancy support
17
-
18
- > ⚠️ **Development Notice**<br>
19
- > Veri is functional but in early development. Breaking changes may occur in minor releases until v1.0!
18
+ - Return path handling
20
19
 
21
20
  ## Table of Contents
22
21
 
@@ -68,12 +67,12 @@ rails db:migrate
68
67
 
69
68
  ## Configuration
70
69
 
71
- If customization is required, configure Veri in an initializer:
70
+ Configure Veri in an initializer if customization is needed:
72
71
 
73
72
  ```rb
74
73
  # These are the default values; you can change them as needed
75
74
  Veri.configure do |config|
76
- config.hashing_algorithm = :argon2 # Password hashing algorithm (:argon2, :bcrypt, or :scrypt)
75
+ config.hashing_algorithm = :argon2 # Password hashing algorithm (:argon2, :bcrypt, :pbkdf2, or :scrypt)
77
76
  config.inactive_session_lifetime = nil # Session inactivity timeout (nil means sessions never expire due to inactivity)
78
77
  config.total_session_lifetime = 14.days # Maximum session duration regardless of activity
79
78
  config.user_model_name = "User" # Your user model name
@@ -115,6 +114,22 @@ end
115
114
  This is a simplified example of how to use Veri's authentication methods:
116
115
 
117
116
  ```rb
117
+ class RegistrationsController < ApplicationController
118
+ skip_authentication
119
+
120
+ def create
121
+ user = User.new(user_params)
122
+
123
+ if user.valid?
124
+ user.update_password(user_params[:password])
125
+ log_in(user)
126
+ redirect_to dashboard_path
127
+ else
128
+ render :new, status: :unprocessable_content
129
+ end
130
+ end
131
+ end
132
+
118
133
  class SessionsController < ApplicationController
119
134
  skip_authentication except: [:destroy]
120
135
 
@@ -126,7 +141,7 @@ class SessionsController < ApplicationController
126
141
  redirect_to return_path || dashboard_path
127
142
  else
128
143
  flash.now[:alert] = "Invalid credentials"
129
- render :new, status: :unprocessable_entity
144
+ render :new, status: :unprocessable_content
130
145
  end
131
146
  end
132
147
 
@@ -161,7 +176,7 @@ current_session
161
176
 
162
177
  ### User Impersonation (Shapeshifting)
163
178
 
164
- Veri provides user impersonation functionality that allows, for example, administrators to temporarily assume another user's identity:
179
+ Veri provides user impersonation functionality that allows administrators to temporarily assume another user's identity:
165
180
 
166
181
  ```rb
167
182
  module Admin
@@ -206,7 +221,7 @@ shapeshifter?
206
221
 
207
222
  ### When unauthenticated
208
223
 
209
- Override this private method to customize authentication behavior:
224
+ Override this private method to customize unauthenticated user behavior:
210
225
 
211
226
  ```rb
212
227
  class ApplicationController < ActionController::Base
@@ -218,10 +233,8 @@ class ApplicationController < ActionController::Base
218
233
 
219
234
  private
220
235
 
221
- # Customize unauthenticated user handling
222
236
  def when_unauthenticated
223
- # By default redirects back with a fallback to the root path if the request format is HTML,
224
- # otherwise responds with 401 Unauthorized
237
+ # By default, redirects back (HTML) or returns 401 (other formats)
225
238
  redirect_to login_path
226
239
  end
227
240
  end
@@ -288,13 +301,19 @@ session.terminate
288
301
  # Terminate all sessions
289
302
  Veri::Session.terminate_all
290
303
 
291
- # Clean up expired/inactive sessions
304
+ # Terminate all sessions for a specific user
305
+ user.sessions.terminate_all
306
+
307
+ # Clean up expired/inactive sessions, and sessions with deleted tenant
292
308
  Veri::Session.prune
309
+
310
+ # Clean up expired/inactive sessions for a specific user
311
+ user.sessions.prune
293
312
  ```
294
313
 
295
314
  ## Account Lockout
296
315
 
297
- Veri provides account lockout functionality to temporarily disable user accounts (for example, after too many failed login attempts or for security reasons).
316
+ Veri provides account lockout functionality to temporarily disable user accounts.
298
317
 
299
318
  ```rb
300
319
  # Lock a user account
@@ -313,11 +332,11 @@ User.locked
313
332
  User.unlocked
314
333
  ```
315
334
 
316
- When an account is locked, the user cannot log in. If the user is already logged in, their sessions will be terminated, and they will be treated as an unauthenticated user.
335
+ When an account is locked, the user cannot log in. If they're already logged in, their sessions are terminated and they're treated as unauthenticated.
317
336
 
318
337
  ## Multi-Tenancy
319
338
 
320
- Veri supports multi-tenancy, allowing you to isolate authentication sessions between different tenants (e.g., organizations, clients, or subdomains).
339
+ Veri supports multi-tenancy, allowing you to isolate authentication sessions between different tenants like organizations, clients, or subdomains.
321
340
 
322
341
  ### Setting Up Multi-Tenancy
323
342
 
@@ -381,7 +400,7 @@ Access authentication state in your views:
381
400
 
382
401
  ## Testing
383
402
 
384
- Veri doesn't provide test helpers, but you can easily create your own:
403
+ Veri doesn't include test helpers, but you can easily create your own:
385
404
 
386
405
  ### Request Specs (Recommended)
387
406
 
@@ -426,13 +445,13 @@ end
426
445
  ## Getting Help and Contributing
427
446
 
428
447
  ### Getting Help
429
- Have a question or need assistance? Open a discussion in our [discussions section](https://github.com/brownboxdev/veri/discussions) for:
448
+ Have a question or need assistance? Open a discussion in our [discussions section](https://github.com/enjaku4/veri/discussions) for:
430
449
  - Usage questions
431
450
  - Implementation guidance
432
451
  - Feature suggestions
433
452
 
434
453
  ### Reporting Issues
435
- Found a bug? Please [create an issue](https://github.com/brownboxdev/veri/issues) with:
454
+ Found a bug? Please [create an issue](https://github.com/enjaku4/veri/issues) with:
436
455
  - A clear description of the problem
437
456
  - Steps to reproduce the issue
438
457
  - Your environment details (Rails version, Ruby version, etc.)
@@ -441,14 +460,14 @@ Found a bug? Please [create an issue](https://github.com/brownboxdev/veri/issues
441
460
  Ready to contribute? You can:
442
461
  - Fix bugs by submitting pull requests
443
462
  - Improve documentation
444
- - Add new features (please discuss first in our [discussions section](https://github.com/brownboxdev/veri/discussions))
463
+ - Add new features (please discuss first in our [discussions section](https://github.com/enjaku4/veri/discussions))
445
464
 
446
- Before contributing, please read the [contributing guidelines](https://github.com/brownboxdev/veri/blob/main/CONTRIBUTING.md)
465
+ Before contributing, please read the [contributing guidelines](https://github.com/enjaku4/veri/blob/main/CONTRIBUTING.md)
447
466
 
448
467
  ## License
449
468
 
450
- The gem is available as open source under the terms of the [MIT License](https://github.com/brownboxdev/veri/blob/main/LICENSE.txt).
469
+ The gem is available as open source under the terms of the [MIT License](https://github.com/enjaku4/veri/blob/main/LICENSE.txt).
451
470
 
452
471
  ## Code of Conduct
453
472
 
454
- Everyone interacting in the Veri project is expected to follow the [code of conduct](https://github.com/brownboxdev/veri/blob/main/CODE_OF_CONDUCT.md).
473
+ Everyone interacting in the Veri project is expected to follow the [code of conduct](https://github.com/enjaku4/veri/blob/main/CODE_OF_CONDUCT.md).
@@ -52,6 +52,7 @@ module Veri
52
52
  HASHERS = {
53
53
  argon2: Veri::Password::Argon2,
54
54
  bcrypt: Veri::Password::BCrypt,
55
+ pbkdf2: Veri::Password::Pbkdf2,
55
56
  scrypt: Veri::Password::SCrypt
56
57
  }.freeze
57
58
 
@@ -3,7 +3,7 @@ module Veri
3
3
  class HashingAlgorithm < Veri::Inputs::Base
4
4
  private
5
5
 
6
- def type = -> { self.class::Strict::Symbol.enum(:argon2, :bcrypt, :scrypt) }
6
+ def type = -> { self.class::Strict::Symbol.enum(:argon2, :bcrypt, :pbkdf2, :scrypt) }
7
7
  end
8
8
  end
9
9
  end
@@ -100,23 +100,15 @@ module Veri
100
100
  end
101
101
 
102
102
  def prune
103
- expired_scope = where(expires_at: ...Time.current)
103
+ expired.or(inactive).delete_all
104
104
 
105
- if Veri::Configuration.inactive_session_lifetime
106
- inactive_cutoff = Time.current - Veri::Configuration.inactive_session_lifetime
107
- expired_scope = expired_scope.or(where(last_seen_at: ...inactive_cutoff))
108
- end
109
-
110
- expired_scope.delete_all
111
-
112
- ids = where.not(tenant_id: nil).includes(:tenant).filter_map do |session|
113
- session.tenant
114
- nil
105
+ orphaned_tenant_sessions = where.not(tenant_id: nil).includes(:tenant).filter_map do |session|
106
+ !session.tenant
115
107
  rescue ActiveRecord::RecordNotFound
116
108
  session.id
117
109
  end
118
110
 
119
- where(id: ids).delete_all if ids.any?
111
+ where(id: orphaned_tenant_sessions).delete_all if orphaned_tenant_sessions.any?
120
112
  end
121
113
 
122
114
  alias terminate_all delete_all
@@ -0,0 +1,47 @@
1
+ require "openssl"
2
+ require "base64"
3
+ require "securerandom"
4
+
5
+ module Veri
6
+ module Password
7
+ module Pbkdf2
8
+ module_function
9
+
10
+ ITERATIONS = 210_000
11
+ SALT_BYTES = 64
12
+ HASH_BYTES = 64
13
+ DIGEST = "sha512"
14
+
15
+ def create(password)
16
+ salt = SecureRandom.random_bytes(SALT_BYTES)
17
+ hash = OpenSSL::KDF.pbkdf2_hmac(
18
+ password,
19
+ salt:,
20
+ iterations: ITERATIONS,
21
+ length: HASH_BYTES,
22
+ hash: DIGEST
23
+ )
24
+
25
+ "#{DIGEST}$#{ITERATIONS}$#{HASH_BYTES}$#{Base64.strict_encode64(salt)}$#{Base64.strict_encode64(hash)}"
26
+ end
27
+
28
+ def verify(password, hashed_password)
29
+ parts = hashed_password.split("$")
30
+ digest, iterations, hash_bytes, encoded_salt, encoded_hash = parts[0], parts[1], parts[2], parts[3], parts[4]
31
+
32
+ salt = Base64.strict_decode64(encoded_salt)
33
+ hash = Base64.strict_decode64(encoded_hash)
34
+
35
+ recalculated_hash = OpenSSL::KDF.pbkdf2_hmac(
36
+ password,
37
+ salt:,
38
+ iterations: iterations.to_i,
39
+ length: hash_bytes.to_i,
40
+ hash: digest
41
+ )
42
+
43
+ OpenSSL.fixed_length_secure_compare(recalculated_hash, hash)
44
+ end
45
+ end
46
+ end
47
+ end
data/lib/veri/railtie.rb CHANGED
@@ -2,9 +2,19 @@ require "rails/railtie"
2
2
 
3
3
  module Veri
4
4
  class Railtie < Rails::Railtie
5
+ def self.server_running?
6
+ !!defined?(Rails::Server)
7
+ end
8
+
9
+ def self.table_exists?
10
+ ActiveRecord::Base.connection.data_source_exists?("veri_sessions")
11
+ rescue ActiveRecord::NoDatabaseError, ActiveRecord::ConnectionNotEstablished
12
+ false
13
+ end
14
+
5
15
  initializer "veri.to_prepare" do |app|
6
16
  app.config.to_prepare do
7
- if ActiveRecord::Base.connection.data_source_exists?("veri_sessions")
17
+ if Veri::Railtie.server_running? && Veri::Railtie.table_exists?
8
18
  Veri::Session.where.not(tenant_id: nil).distinct.pluck(:tenant_type).each do |tenant_class|
9
19
  tenant_class.constantize
10
20
  rescue NameError => e
data/lib/veri/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Veri
2
- VERSION = "0.4.0".freeze
2
+ VERSION = "1.0.1".freeze
3
3
  end
data/lib/veri.rb CHANGED
@@ -5,6 +5,7 @@ require "active_support"
5
5
 
6
6
  require_relative "veri/password/argon2"
7
7
  require_relative "veri/password/bcrypt"
8
+ require_relative "veri/password/pbkdf2"
8
9
  require_relative "veri/password/scrypt"
9
10
 
10
11
  require_relative "veri/inputs/base"
data/veri.gemspec CHANGED
@@ -4,12 +4,16 @@ Gem::Specification.new do |spec|
4
4
  spec.name = "veri"
5
5
  spec.version = Veri::VERSION
6
6
  spec.authors = ["enjaku4"]
7
- spec.homepage = "https://github.com/brownboxdev/veri"
7
+ spec.email = ["enjaku4@icloud.com"]
8
+ spec.homepage = "https://github.com/enjaku4/veri"
8
9
  spec.metadata["homepage_uri"] = spec.homepage
9
10
  spec.metadata["source_code_uri"] = spec.homepage
10
11
  spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
12
+ spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
13
+ spec.metadata["documentation_uri"] = "#{spec.homepage}/blob/main/README.md"
11
14
  spec.metadata["rubygems_mfa_required"] = "true"
12
15
  spec.summary = "Minimal cookie-based authentication library for Ruby on Rails"
16
+ spec.description = "Veri provides cookie-based authentication for Ruby on Rails applications with secure password storage, granular session management, multi-tenancy support, and user impersonation feature, without imposing business logic"
13
17
  spec.license = "MIT"
14
18
  spec.required_ruby_version = ">= 3.2", "< 3.5"
15
19
 
@@ -23,7 +27,7 @@ Gem::Specification.new do |spec|
23
27
  spec.add_dependency "bcrypt", "~> 3.0"
24
28
  spec.add_dependency "dry-configurable", "~> 1.1"
25
29
  spec.add_dependency "dry-types", "~> 1.7"
26
- spec.add_dependency "rails", ">= 7.1", "< 8.1"
30
+ spec.add_dependency "rails", ">= 7.2", "< 8.1"
27
31
  spec.add_dependency "scrypt", "~> 3.0"
28
32
  spec.add_dependency "user_agent_parser", "~> 2.0"
29
33
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: veri
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - enjaku4
@@ -71,7 +71,7 @@ dependencies:
71
71
  requirements:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
- version: '7.1'
74
+ version: '7.2'
75
75
  - - "<"
76
76
  - !ruby/object:Gem::Version
77
77
  version: '8.1'
@@ -81,7 +81,7 @@ dependencies:
81
81
  requirements:
82
82
  - - ">="
83
83
  - !ruby/object:Gem::Version
84
- version: '7.1'
84
+ version: '7.2'
85
85
  - - "<"
86
86
  - !ruby/object:Gem::Version
87
87
  version: '8.1'
@@ -113,6 +113,11 @@ dependencies:
113
113
  - - "~>"
114
114
  - !ruby/object:Gem::Version
115
115
  version: '2.0'
116
+ description: Veri provides cookie-based authentication for Ruby on Rails applications
117
+ with secure password storage, granular session management, multi-tenancy support,
118
+ and user impersonation feature, without imposing business logic
119
+ email:
120
+ - enjaku4@icloud.com
116
121
  executables: []
117
122
  extensions: []
118
123
  extra_rdoc_files: []
@@ -137,17 +142,20 @@ files:
137
142
  - lib/veri/models/session.rb
138
143
  - lib/veri/password/argon2.rb
139
144
  - lib/veri/password/bcrypt.rb
145
+ - lib/veri/password/pbkdf2.rb
140
146
  - lib/veri/password/scrypt.rb
141
147
  - lib/veri/railtie.rb
142
148
  - lib/veri/version.rb
143
149
  - veri.gemspec
144
- homepage: https://github.com/brownboxdev/veri
150
+ homepage: https://github.com/enjaku4/veri
145
151
  licenses:
146
152
  - MIT
147
153
  metadata:
148
- homepage_uri: https://github.com/brownboxdev/veri
149
- source_code_uri: https://github.com/brownboxdev/veri
150
- changelog_uri: https://github.com/brownboxdev/veri/blob/main/CHANGELOG.md
154
+ homepage_uri: https://github.com/enjaku4/veri
155
+ source_code_uri: https://github.com/enjaku4/veri
156
+ changelog_uri: https://github.com/enjaku4/veri/blob/main/CHANGELOG.md
157
+ bug_tracker_uri: https://github.com/enjaku4/veri/issues
158
+ documentation_uri: https://github.com/enjaku4/veri/blob/main/README.md
151
159
  rubygems_mfa_required: 'true'
152
160
  rdoc_options: []
153
161
  require_paths:
@@ -166,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
174
  - !ruby/object:Gem::Version
167
175
  version: '0'
168
176
  requirements: []
169
- rubygems_version: 3.6.7
177
+ rubygems_version: 3.7.2
170
178
  specification_version: 4
171
179
  summary: Minimal cookie-based authentication library for Ruby on Rails
172
180
  test_files: []