authtrail 0.3.0 → 0.4.2

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: e54d90f6f3527e7f9f37276deda00150f33b472069b97bd66b0d27f0a3a44c6f
4
- data.tar.gz: aa1cd0b4fc8e01590efbd51cd872a57a3ef6e984c844166f261ebd01230a771a
3
+ metadata.gz: ff58207c013a0181500aea1886029896cae2af4fe0cf8dbf65bd1545e0637f4a
4
+ data.tar.gz: f2b530b002daaa2ca52f2dbf471199e9fcfc13c04c9c821df139b9e6e909eecc
5
5
  SHA512:
6
- metadata.gz: b640a2f9705502d2405fc15d1bf4bf6082cac388addef26b3592514af117508db8b5f35306f5bd93555472f25e58a86b42d1ade276083bf4b4c4db6dea284ec8
7
- data.tar.gz: 80475eaba75303cffdf3313706a3a58e73718804414002559780a55a1041616de61da596f9b67f79b57e71998e9c27a8c590faefdb0febaaa9834fd74b897a55
6
+ metadata.gz: 94ec2b6986bef058156630c1dccf900c366f1b9c2aaf84703c5372370dbf305af698c554c9e1b5f0ca64d144cd934c065499ac745c711a98d8dfe33c3138ed5b
7
+ data.tar.gz: ae73465fd479199a31cabed9a87a6afdf6acca838de32c8b329f2da061709229046812584dfce1a9a8fdb4650834a5b2a4f2928ac7ea0d6e0cbf50da98e2c4c2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ ## 0.4.2 (2021-12-13)
2
+
3
+ - Added experimental support for Active Record encryption
4
+ - Fixed error with Rails 7 rc1
5
+
6
+ ## 0.4.1 (2021-08-14)
7
+
8
+ - Improved error message when `geocoder` gem not installed
9
+
10
+ ## 0.4.0 (2021-08-13)
11
+
12
+ - Disabled geocoding by default (this was already the case for new installations with 0.3.0+)
13
+ - Made the `geocoder` gem an optional dependency
14
+ - Added `country_code` to geocoding
15
+
16
+ ## 0.3.1 (2021-03-03)
17
+
18
+ - Added `--lockbox` option to install generator
19
+
1
20
  ## 0.3.0 (2021-03-01)
2
21
 
3
22
  - Disabled geocoding by default for new installations
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Track Devise login activity
4
4
 
5
+ **AuthTrail 0.4.0 was recently released** - see [how to upgrade](#upgrading)
6
+
5
7
  :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
6
8
 
7
9
  [![Build Status](https://github.com/ankane/authtrail/workflows/build/badge.svg?branch=master)](https://github.com/ankane/authtrail/actions)
@@ -14,13 +16,29 @@ Add this line to your application’s Gemfile:
14
16
  gem 'authtrail'
15
17
  ```
16
18
 
17
- And run:
19
+ To encrypt email and IP addresses with Lockbox, install [Lockbox](https://github.com/ankane/lockbox) and [Blind Index](https://github.com/ankane/blind_index) and run:
18
20
 
19
21
  ```sh
20
- rails generate authtrail:install
22
+ rails generate authtrail:install --encryption=lockbox
21
23
  rails db:migrate
22
24
  ```
23
25
 
26
+ To use Active Record encryption (Rails 7+, experimental, unreleased), run:
27
+
28
+ ```sh
29
+ rails generate authtrail:install --encryption=activerecord
30
+ rails db:migrate
31
+ ```
32
+
33
+ If you prefer not to encrypt data, run:
34
+
35
+ ```sh
36
+ rails generate authtrail:install --encryption=none
37
+ rails db:migrate
38
+ ```
39
+
40
+ To enable geocoding, see the [Geocoding section](#geocoding).
41
+
24
42
  ## How It Works
25
43
 
26
44
  A `LoginActivity` record is created every time a user tries to login. You can then use this information to detect suspicious behavior. Data includes:
@@ -95,9 +113,15 @@ The `LoginActivity` model uses a [polymorphic association](https://guides.rubyon
95
113
 
96
114
  ## Geocoding
97
115
 
98
- AuthTrail uses [Geocoder](https://github.com/alexreisner/geocoder) for geocoding. We recommend configuring [local geocoding](#local-geocoding) so IP addresses are not sent to a 3rd party service. If you do use a 3rd party service and adhere to GDPR, be sure to add it to your subprocessor list.
116
+ AuthTrail uses [Geocoder](https://github.com/alexreisner/geocoder) for geocoding. We recommend configuring [local geocoding](#local-geocoding) or [load balancer geocoding](#load-balancer-geocoding) so IP addresses are not sent to a 3rd party service. If you do use a 3rd party service and adhere to GDPR, be sure to add it to your subprocessor list.
117
+
118
+ To enable geocoding, add this line to your application’s Gemfile:
99
119
 
100
- To enable geocoding, update `config/initializers/authtrail.rb`:
120
+ ```ruby
121
+ gem 'geocoder'
122
+ ```
123
+
124
+ And update `config/initializers/authtrail.rb`:
101
125
 
102
126
  ```ruby
103
127
  AuthTrail.geocode = true
@@ -146,17 +170,40 @@ Geocoder.configure(
146
170
  )
147
171
  ```
148
172
 
149
- ## Data Protection
173
+ ### Load Balancer Geocoding
174
+
175
+ Some load balancers can add geocoding information to request headers.
150
176
 
151
- Protect the privacy of your users by encrypting fields that contain personal data, such as `identity` and `ip`. [Lockbox](https://github.com/ankane/lockbox) is great for this. Use [Blind Index](https://github.com/ankane/blind_index) so you can still query the fields.
177
+ - [nginx](https://nginx.org/en/docs/http/ngx_http_geoip_module.html)
178
+ - [Google Cloud](https://cloud.google.com/load-balancing/docs/custom-headers)
179
+ - [Cloudflare](https://support.cloudflare.com/hc/en-us/articles/200168236-Configuring-Cloudflare-IP-Geolocation)
152
180
 
153
181
  ```ruby
154
- class LoginActivity < ApplicationRecord
155
- encrypts :identity, :ip
156
- blind_index :identity, :ip
182
+ AuthTrail.geocode = false
183
+
184
+ AuthTrail.transform_method = lambda do |data, request|
185
+ data[:country] = request.headers["<country-header>"]
186
+ data[:region] = request.headers["<region-header>"]
187
+ data[:city] = request.headers["<city-header>"]
157
188
  end
158
189
  ```
159
190
 
191
+ Check out [this example](https://github.com/ankane/authtrail/issues/40)
192
+
193
+ ## Data Retention
194
+
195
+ Delete older data with:
196
+
197
+ ```ruby
198
+ LoginActivity.where("created_at < ?", 2.years.ago).in_batches.delete_all
199
+ ```
200
+
201
+ Delete data for a specific user with:
202
+
203
+ ```ruby
204
+ LoginActivity.where(user_id: 1, user_type: "User").in_batches.delete_all
205
+ ```
206
+
160
207
  ## Other Notes
161
208
 
162
209
  We recommend using this in addition to Devise’s `Lockable` module and [Rack::Attack](https://github.com/kickstarter/rack-attack).
@@ -165,6 +212,18 @@ Check out [Hardening Devise](https://ankane.org/hardening-devise) and [Secure Ra
165
212
 
166
213
  ## Upgrading
167
214
 
215
+ ### 0.4.0
216
+
217
+ There are two notable changes to geocoding:
218
+
219
+ 1. Geocoding is now disabled by default (this was already the case for new installations with 0.3.0+). Check out the instructions for [how to enable it](#geocoding) (you may need to create `config/initializers/authtrail.rb`).
220
+
221
+ 2. The `geocoder` gem is now an optional dependency. To use geocoding, add it to your Gemfile:
222
+
223
+ ```ruby
224
+ gem 'geocoder'
225
+ ```
226
+
168
227
  ### 0.2.0
169
228
 
170
229
  To store latitude and longitude, create a migration with:
@@ -8,6 +8,8 @@ module AuthTrail
8
8
  result =
9
9
  begin
10
10
  Geocoder.search(login_activity.ip).first
11
+ rescue NameError
12
+ raise "Add the geocoder gem to your Gemfile to use geocoding"
11
13
  rescue => e
12
14
  Rails.logger.info "Geocode failed: #{e.message}"
13
15
  nil
@@ -18,6 +20,7 @@ module AuthTrail
18
20
  city: result.try(:city),
19
21
  region: result.try(:state),
20
22
  country: result.try(:country),
23
+ country_code: result.try(:country_code),
21
24
  latitude: result.try(:latitude),
22
25
  longitude: result.try(:longitude)
23
26
  }
@@ -1,3 +1,4 @@
1
+ require "active_support"
1
2
  require "rails/engine"
2
3
 
3
4
  module AuthTrail
@@ -1,3 +1,3 @@
1
1
  module AuthTrail
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.2"
3
3
  end
data/lib/authtrail.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  # dependencies
2
- require "geocoder"
3
2
  require "warden"
4
3
 
5
4
  # modules
@@ -11,7 +10,7 @@ module AuthTrail
11
10
  class << self
12
11
  attr_accessor :exclude_method, :geocode, :track_method, :identity_method, :job_queue, :transform_method
13
12
  end
14
- self.geocode = true
13
+ self.geocode = false
15
14
  self.identity_method = lambda do |request, opts, user|
16
15
  if user
17
16
  user.try(:email)
@@ -6,7 +6,12 @@ module Authtrail
6
6
  include ActiveRecord::Generators::Migration
7
7
  source_root File.join(__dir__, "templates")
8
8
 
9
+ class_option :encryption, type: :string
10
+ # deprecated
11
+ class_option :lockbox, type: :boolean
12
+
9
13
  def copy_migration
14
+ encryption # ensure valid
10
15
  migration_template "login_activities_migration.rb", "db/migrate/create_login_activities.rb", migration_version: migration_version
11
16
  end
12
17
 
@@ -15,12 +20,56 @@ module Authtrail
15
20
  end
16
21
 
17
22
  def generate_model
18
- template "login_activity_model.rb", "app/models/login_activity.rb"
23
+ case encryption
24
+ when "lockbox"
25
+ template "model_lockbox.rb", "app/models/login_activity.rb"
26
+ when "activerecord"
27
+ template "model_activerecord.rb", "app/models/login_activity.rb"
28
+ else
29
+ template "model_none.rb", "app/models/login_activity.rb"
30
+ end
19
31
  end
20
32
 
21
33
  def migration_version
22
34
  "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
23
35
  end
36
+
37
+ def identity_column
38
+ case encryption
39
+ when "lockbox"
40
+ "t.text :identity_ciphertext\n t.string :identity_bidx, index: true"
41
+ else
42
+ # TODO add limit: 510 for Active Record encryption + MySQL?
43
+ "t.string :identity, index: true"
44
+ end
45
+ end
46
+
47
+ def ip_column
48
+ case encryption
49
+ when "lockbox"
50
+ "t.text :ip_ciphertext\n t.string :ip_bidx, index: true"
51
+ else
52
+ # TODO add limit: 510 for Active Record encryption + MySQL?
53
+ "t.string :ip, index: true"
54
+ end
55
+ end
56
+
57
+ # TODO remove default
58
+ def encryption
59
+ case options[:encryption]
60
+ when "lockbox", "activerecord", "none"
61
+ options[:encryption]
62
+ when nil
63
+ if options[:lockbox]
64
+ # TODO deprecation warning
65
+ "lockbox"
66
+ else
67
+ "none"
68
+ end
69
+ else
70
+ abort "Error: encryption must be lockbox, activerecord, or none"
71
+ end
72
+ end
24
73
  end
25
74
  end
26
75
  end
@@ -1,5 +1,5 @@
1
- # set to true for geocoding
2
- # we recommend configuring local geocoding first
1
+ # set to true for geocoding (and add the geocoder gem to your Gemfile)
2
+ # we recommend configuring local geocoding as well
3
3
  # see https://github.com/ankane/authtrail#geocoding
4
4
  AuthTrail.geocode = false
5
5
 
@@ -3,12 +3,12 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version
3
3
  create_table :login_activities do |t|
4
4
  t.string :scope
5
5
  t.string :strategy
6
- t.string :identity
6
+ <%= identity_column %>
7
7
  t.boolean :success
8
8
  t.string :failure_reason
9
9
  t.references :user, polymorphic: true
10
10
  t.string :context
11
- t.string :ip
11
+ <%= ip_column %>
12
12
  t.text :user_agent
13
13
  t.text :referrer
14
14
  t.string :city
@@ -18,8 +18,5 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version
18
18
  t.float :longitude
19
19
  t.datetime :created_at
20
20
  end
21
-
22
- add_index :login_activities, :identity
23
- add_index :login_activities, :ip
24
21
  end
25
22
  end
@@ -0,0 +1,14 @@
1
+ class LoginActivity < ApplicationRecord
2
+ belongs_to :user, polymorphic: true, optional: true
3
+
4
+ encrypts :identity, deterministic: true
5
+ encrypts :ip, deterministic: true
6
+
7
+ before_save :reduce_precision
8
+
9
+ # reduce precision to city level to protect IP
10
+ def reduce_precision
11
+ self.latitude = latitude&.round(1) if try(:latitude_changed?)
12
+ self.longitude = longitude&.round(1) if try(:longitude_changed?)
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ class LoginActivity < ApplicationRecord
2
+ belongs_to :user, polymorphic: true, optional: true
3
+
4
+ encrypts :identity, :ip
5
+ blind_index :identity, :ip
6
+
7
+ before_save :reduce_precision
8
+
9
+ # reduce precision to city level to protect IP
10
+ def reduce_precision
11
+ self.latitude = latitude&.round(1) if try(:latitude_changed?)
12
+ self.longitude = longitude&.round(1) if try(:longitude_changed?)
13
+ end
14
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authtrail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-02 00:00:00.000000000 Z
11
+ date: 2021-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: geocoder
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
55
  description:
70
56
  email: andrew@ankane.org
71
57
  executables: []
@@ -83,7 +69,9 @@ files:
83
69
  - lib/generators/authtrail/install_generator.rb
84
70
  - lib/generators/authtrail/templates/initializer.rb.tt
85
71
  - lib/generators/authtrail/templates/login_activities_migration.rb.tt
86
- - lib/generators/authtrail/templates/login_activity_model.rb.tt
72
+ - lib/generators/authtrail/templates/model_activerecord.rb.tt
73
+ - lib/generators/authtrail/templates/model_lockbox.rb.tt
74
+ - lib/generators/authtrail/templates/model_none.rb.tt
87
75
  homepage: https://github.com/ankane/authtrail
88
76
  licenses:
89
77
  - MIT
@@ -103,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
91
  - !ruby/object:Gem::Version
104
92
  version: '0'
105
93
  requirements: []
106
- rubygems_version: 3.2.3
94
+ rubygems_version: 3.2.32
107
95
  signing_key:
108
96
  specification_version: 4
109
97
  summary: Track Devise login activity