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 +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +47 -28
- data/lib/veri/configuration.rb +1 -0
- data/lib/veri/inputs/hashing_algorithm.rb +1 -1
- data/lib/veri/models/session.rb +4 -12
- data/lib/veri/password/pbkdf2.rb +47 -0
- data/lib/veri/railtie.rb +11 -1
- data/lib/veri/version.rb +1 -1
- data/lib/veri.rb +1 -0
- data/veri.gemspec +6 -2
- metadata +16 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17672738e498e3328b8b4cf724e3b30e4ee3fb2f7c1d768344cd0c9d29ced1df
|
4
|
+
data.tar.gz: bb8031eb131fce46b349e6881d8b20a18d43c19bf4aba7b41ae1bc6474e5c3cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
1
|
+
# Veri: Minimal Authentication for Rails
|
2
2
|
|
3
3
|
[](http://badge.fury.io/rb/veri)
|
4
|
-
[](https://rubygems.org/gems/veri)
|
5
|
+
[](https://github.com/enjaku4/veri/actions/workflows/ci.yml)
|
6
|
+
[](LICENSE)
|
5
7
|
|
6
|
-
Veri is a cookie-based authentication library for Ruby on Rails
|
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
|
-
-
|
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
|
-
|
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: :
|
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
|
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
|
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
|
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
|
-
#
|
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
|
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
|
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
|
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
|
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/
|
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/
|
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/
|
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/
|
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/
|
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/
|
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).
|
data/lib/veri/configuration.rb
CHANGED
data/lib/veri/models/session.rb
CHANGED
@@ -100,23 +100,15 @@ module Veri
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def prune
|
103
|
-
|
103
|
+
expired.or(inactive).delete_all
|
104
104
|
|
105
|
-
|
106
|
-
|
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:
|
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
|
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
data/lib/veri.rb
CHANGED
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.
|
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.
|
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
|
+
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.
|
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.
|
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/
|
150
|
+
homepage: https://github.com/enjaku4/veri
|
145
151
|
licenses:
|
146
152
|
- MIT
|
147
153
|
metadata:
|
148
|
-
homepage_uri: https://github.com/
|
149
|
-
source_code_uri: https://github.com/
|
150
|
-
changelog_uri: https://github.com/
|
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.
|
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: []
|