login-control 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 576dfb778fef6f08e892aee929fb44b15ac51de82b8bca41a6d5b7fa5291cf1e
4
+ data.tar.gz: 15f8547991b86ae2f90b212cfc639ad67e8fd2556acd5851b7fc2b9894d6a337
5
+ SHA512:
6
+ metadata.gz: 5668048e7774db39f276303cc32d9bf6e1538a3300c4118bea7c520eb32ee263203c9afb7b8a60a9ba48a76be4cdcf430029015ddd1ee334d587d1c52dcd7bd1
7
+ data.tar.gz: 480d115794fb3726822b090718eb5dd941aed63db411bb1931290944307cd8db0f6742db01c1ebac8a748d312372e05f474cbb2a29f19c08b0845d41d66b6f33
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ ## Description
2
+
3
+ The Attempt here is to give more flexibility on multiple signup barriers, like captacha or 2fa. Based on the requests it gives you a decisive criteria of the barriers a user have to take for sign in. It stores a permanent cookie and a table for tracking requests for specific routes you track within a controller method.
4
+
5
+ its built for systems on higher security requirements, for users which have sign-in multiple times on same login.
6
+
7
+ ## Features
8
+
9
+ The `RequestControlViewHelper.captcha_tag?` delivers true if captcha is necessary and showed on a login form.
10
+
11
+ This decision is based on the status of failed login attempts, which is stored in rails-session-cookie.
12
+
13
+ For a user that had never a successfully login, `captcha_tag?` is always true. After first successful login, `captcha_tag?` is true if `attempts` are less than configured (default: 10) and `last_attempt` is older than `config.x.login_control.retry_after_seconds`
14
+
15
+ On localhost captcha is never required.
16
+
17
+ ## Installation
18
+
19
+ `gem 'request-control'
20
+
21
+ run
22
+ ```
23
+ $ bundle
24
+ $ rails g model login_control session_id:string login_name:string scope:string sign_in_success:integer attempts:integer last_attempt:datetime validate_captcha:boolean
25
+ $ rails db:migrate
26
+ ```
27
+
28
+ Login Form
29
+
30
+ `include RequestControlViewHelper`
31
+
32
+ ```
33
+ - if captcha_tag?
34
+ = hcaptcha xxx
35
+ ```
36
+
37
+ Controller example for subclassed devise controller
38
+
39
+ ```
40
+ class SessionsController < Devise::SessionsController
41
+
42
+ include RequestControlModule
43
+
44
+ def create
45
+ notice_request_attempt
46
+ if (captcha_validation? ? verify_hcaptcha(secret_key: ...) : true) && credentials-matched
47
+ super
48
+ notice_successful_request
49
+ else
50
+ redirect_to login_path, alert: 'captcha failed'
51
+ end
52
+ end
53
+ end
54
+ ```
55
+
56
+ ## Configs
57
+
58
+ `config.x.login_control.attempts_allowed` integer, default: 10
59
+
60
+ `config.x.login_control.retry_after_seconds` integer, default: 30 (seconds) # => if, after a failed login, within status `:known`, within `attempts_allowed`, within `retry_after_seconds` `RequestControlViewHelper.captcha_tag?` returns true
61
+
62
+ `config.x.login_control.debug` boolean, default: false only for production
63
+
64
+
@@ -0,0 +1,56 @@
1
+ module LoginControlModule
2
+
3
+ # check if captcha is to validate (does not store a cookie)
4
+ def captcha_validation?(scope: :global, login_name: nil)
5
+ rec = rc_record(scope, login_name)
6
+ rec ? rec.validate_captcha : true
7
+ end
8
+
9
+ # stores cookie, count-up sign_in_success, set attempts count to 1
10
+
11
+ def notice_successful_request(scope: :global, login_name: nil)
12
+ rec = find_or_build_rc_record(scope, login_name)
13
+ rec.sign_in_success = rec.sign_in_success.to_i + 1
14
+ rec.attempts = 1
15
+ rec.save!
16
+ logger.info "REQUEST-CONTROL => #{rec.sign_in_success}. successful request noticed" if debug_request_control
17
+ end
18
+
19
+ # stores cookie, counts up attempts
20
+
21
+ def notice_request_attempt(scope: :global, login_name: nil)
22
+ rec = find_or_build_rc_record(scope, login_name)
23
+ rec.attempts = rec.attempts.to_i + 1
24
+ rec.save!
25
+ logger.info "REQUEST-CONTROL => #{rec.attempts}. failed request noticed" if debug_request_control
26
+ end
27
+
28
+ private
29
+
30
+ # read or store encrypted permanent cookie «login_control»
31
+
32
+ def find_or_build_rc_record(scope, login_name)
33
+ id = cookies.encrypted.permanent[:login_control]
34
+ if id.present?
35
+ rc_record(scope, login_name, id: id)
36
+ else
37
+ id = SecureRandom.hex(20)
38
+ cookies.encrypted.permanent[:login_control] = id
39
+ LoginControl.new(session_id: id, scope: scope, login_name: login_name)
40
+ end
41
+ end
42
+
43
+ # read cookie «login_control»
44
+ def rc_record(scope, login_name, id: cookies.encrypted.permanent[:login_control])
45
+ if id
46
+ LoginControl.find_by(session_id: id, scope: scope, login_name: login_name)
47
+ else
48
+ nil
49
+ end
50
+ end
51
+
52
+ def debug_request_control
53
+ Rails.configuration.x.login_control.debug || !Rails.env.production?
54
+ end
55
+
56
+ end
@@ -0,0 +1,45 @@
1
+ module LoginControlViewHelper
2
+
3
+ # true if captcha tag is showed on a login form
4
+ # the result is saved in rails-session-cookie and later picked up by LoginControlModule.captcha_validation?
5
+
6
+ def captcha_tag?(scope: :global, login_name: nil)
7
+ debug = (Rails.configuration.x.login_control.debug || !Rails.env.production?)
8
+ rc_id = cookies.encrypted.permanent[:login_control]
9
+ if request.host == 'localhost'
10
+ logger.info 'REQUEST-CONTROL => no captcha because of localhost' if debug
11
+ false
12
+ elsif !rc_id.present?
13
+ logger.info 'REQUEST-CONTROL => captcha because no cookie stored yet' if debug
14
+ true
15
+ else
16
+ logger.info 'REQUEST-CONTROL => cookie found ...' if debug
17
+ rec = LoginControl.find_by(session_id: rc_id, scope: scope, login_name: login_name)
18
+ if !rec
19
+ logger.info 'REQUEST-CONTROL => captcha required because no record found(!)' if debug
20
+ true
21
+ else
22
+ logger.info 'REQUEST-CONTROL => record found ...' if debug
23
+ captcha_requested = true
24
+
25
+ attempts_allowed = (Rails.configuration.x.login_control.attempts_allowed || 10)
26
+ retry_after_seconds = (Rails.configuration.x.login_control.retry_after_seconds || 30)
27
+ logger.info "REQUEST-CONTROL => #{rec.attempts.to_i}. attempt (config.x.attempts_allowed: #{attempts_allowed})" if debug
28
+
29
+ if rec.attempts.to_i <= attempts_allowed
30
+ secs = Time.now - rec.updated_at
31
+ captcha_requested = retry_after_seconds.to_f >= secs
32
+ logger.info "REQUEST-CONTROL => captcha #{captcha_requested ? '' : 'NOT '}requested: config.x.retry_after_seconds(#{retry_after_seconds}) >= secs(#{secs})" if debug
33
+ end
34
+
35
+ rec.update!(validate_captcha: captcha_requested)
36
+ captcha_requested
37
+ end
38
+ end
39
+ end
40
+
41
+ # Text for ask a user for storing a cookie
42
+
43
+ REQUEST_CONTROL_COOKIE_TXT = "On first login attempt this service stores a permanent cookie. It tracks login attempts. Only aim is securing and, on the other hand, simplifying access."
44
+
45
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: login-control
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Christian Sedlmair
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-07 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Based on Login Attempts check if captcha is necessary. It stores a permanent
14
+ cookie and uses a table for tracking login requests.
15
+ email: christian@sedlmair.ch
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - README.md
21
+ - lib/login_control_module.rb
22
+ - lib/login_control_view_helper.rb
23
+ homepage: https://rubygems.org/gems/request-control
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubygems_version: 3.3.17
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: Lib for simplifying and securing login.
46
+ test_files: []