AuthTrail
Track Devise login activity
:tangerine: Battle-tested at Instacart
Installation
Add this line to your application’s Gemfile:
gem 'authtrail'
And run:
rails generate authtrail:install
rails db:migrate
How It Works
A LoginActivity record is created every time a user tries to login. You can then use this information to detect suspicious behavior. Data includes:
scope- Devise scopestrategy- Devise strategyidentity- email addresssuccess- whether the login succeededfailure_reason- if the login faileduser- the user if the login succeededcontext- controller and actionip- IP addressuser_agentandreferrer- from browsercity,region,country,latitude, andlongitude- from IPcreated_at- time of event
Features
Exclude certain attempts from tracking - useful if you run acceptance tests
AuthTrail.exclude_method = lambda do |info|
info[:identity] == "[email protected]"
end
Write data somewhere other than the login_activities table
AuthTrail.track_method = lambda do |info|
# code
end
Use a custom identity method
AuthTrail.identity_method = lambda do |request, opts, user|
if user
user.email
else
request.params.dig(opts[:scope], :email)
end
end
Associate login activity with your user model
class User < ApplicationRecord
has_many :login_activities, as: :user # use :user no matter what your model name
end
The LoginActivity model uses a polymorphic association so it can be associated with different user models.
Geocoding
IP geocoding is performed in a background job so it doesn’t slow down web requests. You can disable it entirely with:
AuthTrail.geocode = false
Set job queue for geocoding
AuthTrail.job_queue = :low_priority
Geocoding Performance
To avoid calls to a remote API, download the GeoLite2 City database and configure Geocoder to use it.
Add this line to your application’s Gemfile:
gem 'maxminddb'
And create an initializer at config/initializers/geocoder.rb with:
Geocoder.configure(
ip_lookup: :geoip2,
geoip2: {
file: Rails.root.join("lib", "GeoLite2-City.mmdb")
}
)
Data Protection
Protect the privacy of your users by encrypting fields that contain personal data, such as identity and ip. Lockbox is great for this. Use Blind Index so you can still query the fields.
class LoginActivity < ApplicationRecord
encrypts :identity, :ip
blind_index :identity, :ip
end
Other Notes
We recommend using this in addition to Devise’s Lockable module and Rack::Attack.
Check out Hardening Devise and Secure Rails for more best practices.
Upgrading
0.2.0
To store latitude and longitude, create a migration with:
add_column :login_activities, :latitude, :float
add_column :login_activities, :longitude, :float
History
View the changelog
Contributing
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- Report bugs
- Fix bugs and submit pull requests
- Write, clarify, or fix documentation
- Suggest or add new features
To get started with development and testing:
git clone https://github.com/ankane/authtrail.git
cd authtrail
bundle install
bundle exec rake test