cookie_crypt 1.0.0

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
+ SHA1:
3
+ metadata.gz: 03a95f39e7dfef045da3c962fd52a2df5ace9e11
4
+ data.tar.gz: af04600f35989fb07666ec55558406210f16612f
5
+ SHA512:
6
+ metadata.gz: 645fa5fe1fe957cd9d4157a0ecf1978ddf0cba504a720029a332239aa9b70b454058f7a64693978d4b12a419e6e167631fb83cee8bdceb5f6ec6cc87c25626cc
7
+ data.tar.gz: 938a738da2b1f352aeb1309fb6b1bb0036814dd48aa93c8999a98743aee687ac897d8b6288ef0a88a82b4d5d757cfb8573848e6e1da6fbee520de827227eb699
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in devise_ip_filter.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2013 Louis Alridge
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ ## Cookie Crypt
2
+
3
+ ## Encrypted Cookie Two Factor Authentication for Devise
4
+
5
+ ## Features
6
+
7
+ * User customizable security questions and answers
8
+ * Configurable max login attempts
9
+ * Per user level of control (Allow certain ips to bypass two-factor)
10
+ * Customizable views
11
+
12
+ ## Configuration
13
+
14
+ ### Initial Setup
15
+
16
+ In a Rails environment, require the gem in your Gemfile:
17
+
18
+ gem 'cookie_crypt'
19
+
20
+ Once that's done, run:
21
+
22
+ bundle install
23
+
24
+
25
+ ### Automatic installation
26
+
27
+ In order to add encrypted cookie two factor authorization to a model, run the command:
28
+
29
+ bundle exec rails g cookie_crypt MODEL
30
+
31
+ Where MODEL is your model name (e.g. User or Admin). This generator will add `:cookie_cryptable` to your model
32
+ and create a migration in `db/migrate/`, which will add the required columns to your table.
33
+
34
+ NOTE: This will create a field called "username" on the table it is creating if that field does not already exist.
35
+ The fields are security_question_one, security_question_two, security_answer_one, security_answer_two,
36
+ agent_list, and cookie_crypt_attempts_count
37
+
38
+ Finally, run the migration with:
39
+
40
+ bundle exec rake db:migrate
41
+
42
+
43
+ ### Manual installation
44
+
45
+ To manually enable encrypted cookie two factor authentication for the User model, you should add cookie_crypt to your devise line, like:
46
+
47
+ ```ruby
48
+ devise :database_authenticatable, :registerable,
49
+ :recoverable, :rememberable, :trackable, :validatable, :cookie_cryptable
50
+ ```
51
+
52
+ Config setup
53
+
54
+ ```ruby
55
+ config.max_login_attempts = 3
56
+ config.cookie_deletion_time_frame = '30.days.from_now'
57
+ ```
58
+
59
+ ### Customisation
60
+
61
+ By default encrypted cookie two factor authentication is enabled for each user, you can change it with this method in your User model:
62
+
63
+ ```ruby
64
+ def need_two_factor_authentication?(request)
65
+ request.ip != '127.0.0.1'
66
+ end
67
+ ```
68
+
69
+ This will disable two factor authentication for local users and just puts the code in the logs.
70
+
71
+ ### Rationalle
72
+
73
+ Cookie Crypt uses a cookie stored on a user's machine to monitor their authentication status. The first time a user passes the initial login
74
+ they are passed to the cookie crypt controller which prevents further action. They are "logged in" in the devise sense, but have an additional hook
75
+ preventing them from performing any actions that arent in the cookie crypt controller until they bypass that auth. If this is first time they are going
76
+ through cookie_crypt, the user will be presented with several labeled text boxes asking them to input two security questions and two security answers.
77
+ After inputting this information they are authenticated and redirected to the root of the application but not given an auth cookie.
78
+
79
+ It is important to note that the security answers are not saved as plaintext in the database. They are encrypted and that output is matched against
80
+ whatever the user inputs for their answers in the future.
81
+
82
+ When the user attempts to login again, they will be displayed their two security questions and asked to answer them with their two security answers.
83
+ If successful, an auth cookie is generated on the user's machine based on the user's username and encrypted password. The cookie is username - application
84
+ specific. No two cookies should ever be the same if the username field is unique. After receiving their auth cookie, the user's user agent is logged and
85
+ they are sent to the root of the system as fully authenticated. If the user was unsuccessful in authenticating 3 (or more) times, they will be locked out
86
+ until their cookie_crypt_attempts_count is reset to 0.
87
+
88
+ ### Two factor Defense
89
+
90
+ So a user now has an auth cookie and the server knows it gave an auth cookie to this user that possessed this user agent, what now? If that same user with
91
+ that same agent tries to login again, they will authenticate through cookie crypt auth without any work on their part. The server simply matches the value
92
+ of their cookie with what it expects it should be. If they match AND the user agent the user is using is in the list of agents allocated to that user,
93
+ everything is square and they are authenticated. Using the UserAgent gem, incremental updates in a user's user agent will not be treated as differing agents.
94
+ The system will log the attempt as successful and update the user's agent_list with the updated agent value.
95
+
96
+ But what if they're logging in through a different machine / browser? Then they input their security answers and are given a cookie for that agent.
97
+
98
+ But what if an attacker knows the user's username and password? The attacker must also know the user's security question answers to auth as the user.
99
+
100
+ But what if an attacker knows the user's username and password AND has a copy of the user's cookie in their browser? Cookie crypt detects this case and
101
+ locks out the attacker by referencing the agent_list. A user that has a cookie but not a validated agent is obviously an attacker. This case also creates a
102
+ file in Rails.root / log to notify the admins of a hacking attempt. The agent_list field stores information given out by a browser's user agent and contains a
103
+ decent enough amount of data for fingerprinting. More could be done in this regard (testing to see what fonts/plugins a browser has) but is outside the scope
104
+ of this gem and would make it more difficult for the gem to be only a minor inconvienence to the users.
105
+
106
+ What cookie crypt doesnt prevent:
107
+ An attacker that knows a user's username and password thats logging in from the user's machine / browser
108
+ An attacker that knows a user's username and password thats also spoofing the user's agent and also has the user's same auth-cookie
109
+ An attacker that knows a user's username, password, security questions and answers to said questions
110
+
111
+ Afterword: Spoofing a user agent is not that difficult, any modern browser with dev tools can change its user agent rather easily. The catch is that the values
112
+ need to match with what the user already has which requires additional work on the attacker's part. Also, The system recognizes updates to both the user's OS AND
113
+ browser.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,142 @@
1
+ include ActionView::Helpers::SanitizeHelper
2
+ require "useragent"
3
+ require "logger"
4
+ class Devise::CookieCryptController < DeviseController
5
+ prepend_before_filter :authenticate_scope!
6
+ before_filter :prepare_and_validate, :handle_cookie_crypt
7
+
8
+ def show
9
+ if has_matching_encrypted_cookie?
10
+ if !using_an_agent_that_is_already_being_used?
11
+ #An attacker has successfully obtained a user's cookie and login credentials and is trying to pass themselves off as the target
12
+ #This is an attacker because the agent data does not match the agent data from when a cookie is generated for this user's machine.
13
+ #A machine that "suddenly" has a cookie despite not being auth'd is an attacker.
14
+
15
+ log_hack_attempt
16
+
17
+ resource.cookie_crypt_attempts_count = resource.class.max_cookie_crypt_login_attempts
18
+ resource.save #prevents attacker from deleting cookie and trying to login "normally" by inputting the user's two_fac answers
19
+
20
+ sign_out(resource)
21
+ redirect_to :root and return
22
+ else
23
+ authentication_success
24
+ end
25
+ else
26
+ flash[:notice] = "Signed In Successfully, now going through two factor authentication."
27
+ @user = resource
28
+ render template: "devise/cookie_crypt/show"
29
+ end
30
+ end
31
+
32
+ def update
33
+ if resource.security_question_one.blank? # initial case (first login)
34
+
35
+ resource.security_question_one = sanitize(params[:security_question_one])
36
+ resource.security_question_two = sanitize(params[:security_question_two])
37
+ resource.security_answer_one = Digest::SHA512.hexdigest(sanitize(params[:security_answer_one]))
38
+ resource.security_answer_two = Digest::SHA512.hexdigest(sanitize(params[:security_answer_two]))
39
+ resource.save
40
+
41
+ authentication_success
42
+ else
43
+
44
+ if matching_answers?
45
+ generate_cookie
46
+ log_agent_to_resource
47
+ authentication_success
48
+ else
49
+ resource.cookie_crypt_attempts_count += 1
50
+ resource.save
51
+ set_flash_message :error, :attempt_failed
52
+ if resource.max_cookie_crypt_login_attempts?
53
+ sign_out(resource)
54
+ render template: 'devise/cookie_crypt/max_login_attempts_reached' and return
55
+ else
56
+ render :show
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def authenticate_scope!
65
+ self.resource = send("current_#{resource_name}")
66
+ end
67
+
68
+ def encrypted_username_and_pass
69
+ Digest::SHA512.hexdigest("#{resource.username}_#{resource.encrypted_password}")
70
+ end
71
+
72
+ def generate_cookie
73
+ cookies["#{resource.username}_#{Rails.application.class.to_s.split("::").first}".to_sym] = {
74
+ value: "#{encrypted_username_and_pass}",
75
+ expires: Date.class_eval("#{resource.class.cookie_deletion_time_frame}")
76
+ }
77
+ end
78
+
79
+ def has_matching_encrypted_cookie?
80
+ cookies["#{resource.username}_#{Rails.application.class.to_s.split("::").first}"] == encrypted_username_and_pass
81
+ end
82
+
83
+ def log_hack_attempt
84
+ logger = Logger.new("#{Rails.root.join('log','hack_attempts.log')}")
85
+ logger.warn "Attempt to bypass two factor authentication and devise detected from ip #{request.remote_ip} using #{resource_name}: #{resource.inspect}!"
86
+ end
87
+
88
+ def log_agent_to_resource
89
+ unless using_an_agent_that_is_already_being_used?
90
+ resource.agent_list = "#{resource.agent_list}#{'|' unless resource.agent_list.blank?}#{request.user_agent}"
91
+ resource.save
92
+ end
93
+ end
94
+
95
+ def matching_answers?
96
+ resource.security_answer_one == Digest::SHA512.hexdigest(sanitize(params[:security_answer_one])) &&
97
+ resource.security_answer_two == Digest::SHA512.hexdigest(sanitize(params[:security_answer_two]))
98
+ end
99
+
100
+ def prepare_and_validate
101
+ redirect_to :root and return if resource.nil?
102
+ @limit = resource.class.max_cookie_crypt_login_attempts
103
+ if resource.max_cookie_crypt_login_attempts?
104
+ sign_out(resource)
105
+ render template: 'devise/cookie_crypt/max_login_attempts_reached' and return
106
+ end
107
+ end
108
+
109
+ def authentication_success
110
+ flash[:notice] = 'Signed in through two-factor authentication successfully.'
111
+ warden.session(resource_name)[:need_cookie_crypt_auth] = false
112
+ sign_in resource_name, resource, :bypass => true
113
+ resource.update_attribute(:cookie_crypt_attempts_count, 0)
114
+ redirect_to stored_location_for(resource_name) || :root
115
+ end
116
+
117
+ def using_an_agent_that_is_already_being_used?
118
+ unless resource.agent_list.blank?
119
+ request_agent = UserAgent.parse("#{request.user_agent}")
120
+ resource.agent_list.split('|').each do |agent_string|
121
+ if agent_string.include?("#{request_agent.application}")
122
+ agent = UserAgent.parse("#{agent_string}")
123
+ if agent.application == request_agent.application && agent.browser == request_agent.browser
124
+ if request_agent >= agent #version number is higher for example
125
+ #update user agent string and return true
126
+ resource.agent_list = resource.agent_list.gsub("#{agent.browser}/#{agent.version}","#{request_agent.browser}/#{request_agent.version}")
127
+ resource.save
128
+ return true
129
+ elsif request_agent.version == agent.version
130
+ return true
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+ false
137
+ end
138
+
139
+ def unrecognized_agent?
140
+ resource.agent_list.include?("#{request.user_agent}")
141
+ end
142
+ end
@@ -0,0 +1,3 @@
1
+ <h2>Access completely denied as you have reached your attempts limit = <%= @limit %>.</h2>
2
+ <p>Please contact your system administrator.</p>
3
+
@@ -0,0 +1,51 @@
1
+
2
+ <h2>Two Factor Login Page</h2>
3
+
4
+ <%=form_tag([resource_name, :cookie_crypt], method: :put) do %>
5
+ <% if @user.security_question_one.blank? %>
6
+ <h2>You have not yet setup two-factor questions and answers. Please follow the instructions below.</h2>
7
+
8
+ <h2>Note: It is a generally a good idea to have your questions be about people/events/objects that do not change over time.</h2>
9
+
10
+ <h3>Please input your first security question</h3>
11
+
12
+ <%=text_field_tag :security_question_one, nil, size: 50 %>
13
+ <br></br>
14
+
15
+ <h3>Please input your first question's answer</h3>
16
+
17
+ <%=text_field_tag :security_answer_one, nil, size: 50 %>
18
+ <br></br>
19
+
20
+ <h3>Please input your second security question </h3>
21
+
22
+ <%=text_field_tag :security_question_two, nil, size: 50 %>
23
+ <br></br>
24
+
25
+ <h3>Please input your second question's answer</h3>
26
+
27
+ <%=text_field_tag :security_answer_two, nil, size: 50 %>
28
+ <br></br>
29
+
30
+ <h2>Please note that you will not be given a security token to login by skipping two factor until you login next time.</h2>
31
+
32
+ <% else %>
33
+
34
+ <h2><%="#{@user.security_question_one}"%></h2>
35
+
36
+ <%=text_field_tag :security_answer_one, nil, size: 50 %>
37
+
38
+ <br></br>
39
+
40
+ <h2><%="#{@user.security_question_two}" %></h2>
41
+
42
+ <%=text_field_tag :security_answer_two, nil, size: 50 %>
43
+
44
+ <br></br>
45
+ <% end %>
46
+
47
+ <%= submit_tag "Submit" %>
48
+
49
+ <% end %>
50
+ <br></br>
51
+ <%=link_to "Sign out", destroy_user_session_path, :method => :delete %>
@@ -0,0 +1,4 @@
1
+ en:
2
+ devise:
3
+ cookie_crypt:
4
+ attempt_failed: "Attempt failed."
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cookie_crypt/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "cookie_crypt"
7
+ s.version = CookieCrypt::VERSION.dup
8
+ s.authors = ["Dmitrii Golub","Louis Alridge"]
9
+ s.email = ["loualrid@gmail.com"]
10
+ s.homepage = "https://github.com/loualrid/CookieCrypt"
11
+ s.summary = %q{Encrypted cookie two factor authentication plugin for devise}
12
+ s.description = <<-EOF
13
+ ### Features ###
14
+ * User customizable security questions and answers
15
+ * Configurable max login attempts
16
+ * per user level control if he really need two factor authentication
17
+ EOF
18
+
19
+ s.rubyforge_project = "cookie_crypt"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+
26
+ s.add_runtime_dependency 'rails', '>= 3.1.1'
27
+ s.add_runtime_dependency 'devise'
28
+ s.add_runtime_dependency 'useragent'
29
+
30
+ s.add_development_dependency 'bundler'
31
+ s.license = 'MIT'
32
+ end
@@ -0,0 +1,39 @@
1
+ module CookieCrypt
2
+ module Controllers
3
+ module Helpers
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before_filter :handle_cookie_crypt
8
+ end
9
+
10
+ private
11
+
12
+ def handle_cookie_crypt
13
+ unless devise_controller?
14
+ Devise.mappings.keys.flatten.any? do |scope|
15
+ if signed_in?(scope) and warden.session(scope)[:need_cookie_crypt_auth]
16
+ handle_failed_cookie_crypt_auth(scope)
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def handle_failed_cookie_crypt_auth(scope)
23
+ if request.format.present? and request.format.html?
24
+ session["#{scope}_return_tor"] = request.path if request.get?
25
+ redirect_to cookie_crypt_auth_path_for(scope)
26
+ else
27
+ render nothing: true, status: :unauthorized
28
+ end
29
+ end
30
+
31
+ def cookie_crypt_auth_path_for(resource_or_scope = nil)
32
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
33
+ change_path = "#{scope}_cookie_crypt_path"
34
+ send(change_path)
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,6 @@
1
+ Warden::Manager.after_authentication do |user, auth, options|
2
+ if user.respond_to?(:need_cookie_crypt_auth?)
3
+ if auth.session(options[:scope])[:need_cookie_crypt_auth] = user.need_cookie_crypt_auth?(auth.request)
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,20 @@
1
+ require 'cookie_crypt/hooks/cookie_cryptable'
2
+ module Devise
3
+ module Models
4
+ module CookieCryptable
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ ::Devise::Models.config(self, :max_cookie_crypt_login_attempts, :cookie_deletion_time_frame)
9
+ end
10
+
11
+ def need_cookie_crypt_auth?(request)
12
+ true
13
+ end
14
+
15
+ def max_cookie_crypt_login_attempts?
16
+ cookie_crypt_attempts_count >= self.class.max_cookie_crypt_login_attempts
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ module CookieCrypt
2
+ module Orm
3
+ module ActiveRecord
4
+ module Schema
5
+ include CookieCrypt::Schema
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ ActiveRecord::ConnectionAdapters::Table.send :include, CookieCrypt::Orm::ActiveRecord::Schema
12
+ ActiveRecord::ConnectionAdapters::TableDefinition.send :include, CookieCrypt::Orm::ActiveRecord::Schema
@@ -0,0 +1,7 @@
1
+ module CookieCrypt
2
+ class Engine < ::Rails::Engine
3
+ ActiveSupport.on_load(:action_controller) do
4
+ include CookieCrypt::Controllers::Helpers
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module ActionDispatch::Routing
2
+ class Mapper
3
+ protected
4
+
5
+ def devise_cookie_crypt(mapping, controllers)
6
+ resource :cookie_crypt, :only => [:show, :update], :path => mapping.path_names[:cookie_crypt], :controller => controllers[:cookie_crypt]
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module CookieCrypt
2
+ module Schema
3
+
4
+ def cookie_crypt_login_attempts_count
5
+ apply_devise_schema :cookie_crypt_login_attempts_count, Integer, :default => 0
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module CookieCrypt
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,24 @@
1
+ require 'cookie_crypt/version'
2
+ require 'devise'
3
+ require 'digest'
4
+ require 'active_support/concern'
5
+
6
+ module Devise
7
+ mattr_accessor :max_cookie_crypt_login_attempts, :cookie_deletion_time_frame
8
+ @@max_cookie_crypt_login_attempts = 3
9
+ @@cookie_deletion_time_frame = 30.days.from_now
10
+ end
11
+
12
+ module CookieCrypt
13
+ autoload :Schema, 'cookie_crypt/schema'
14
+ module Controllers
15
+ autoload :Helpers, 'cookie_crypt/controllers/helpers'
16
+ end
17
+ end
18
+
19
+ Devise.add_module :cookie_cryptable, :model => 'cookie_crypt/models/cookie_cryptable', :controller => :cookie_crypt, :route => :cookie_crypt
20
+
21
+ require 'cookie_crypt/orm/active_record'
22
+ require 'cookie_crypt/routes'
23
+ require 'cookie_crypt/models/cookie_cryptable'
24
+ require 'cookie_crypt/rails'
@@ -0,0 +1,14 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ module ActiveRecord
4
+ module Generators
5
+ class CookieCryptGenerator < ActiveRecord::Generators::Base
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ def copy_cookie_crypt_migration
9
+ migration_template "migration.rb", "db/migrate/cookie_crypt_add_to_#{table_name}"
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ class CookieCryptAddTo<%= table_name.camelize %> < ActiveRecord::Migration
2
+ def change
3
+ change_table :<%= table_name %> do |t|
4
+ <%='t.string :username, null: false, default: ""' if ActiveRecord::Base.class_eval("#{table_name.camelize.singularize}.inspect['username: string'].blank?") %>
5
+ t.string :security_question_one, default: ""
6
+ t.string :security_question_two, default: ""
7
+ t.string :security_answer_one, default: ""
8
+ t.string :security_answer_two, default: ""
9
+ t.text :agent_list, default: ""
10
+ t.integer :cookie_crypt_attempts_count, default: 0
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ module CookieCryptable
2
+ module Generators
3
+ class CookieCryptGenerator < Rails::Generators::NamedBase
4
+ namespace "cookie_crypt"
5
+ desc "Adds :cookie_cryptable directive in the given model.
6
+ It also generates an active record migration."
7
+
8
+ def inject_cookie_crypt_content
9
+ paths = [File.join("app", "models", "#{file_path}.rb"),File.join("config", "initializers", "devise.rb")]
10
+ inject_into_file(paths[0], "cookie_cryptable, :", :after => "devise :") if File.exists?(paths[0])
11
+ if File.exists?(paths[1])
12
+ inject_into_file(paths[1], "\n # ==> Cookie Crypt Configuration Parameters\n config.max_cookie_crypt_login_attempts = 3
13
+ \n # For cookie_deletion_time_frame field, make sure your timeframe parses into an actual date and is a string
14
+ \n config.cookie_deletion_time_frame = '30.days.from_now'", after: "Devise.setup do |config|")
15
+ end
16
+ end
17
+
18
+ source_root File.expand_path('../../../../app/views/devise/cookie_crypt', __FILE__)
19
+
20
+ def generate_files
21
+ Dir.mkdir("app/views/devise") unless Dir.exists?("app/views/devise")
22
+ unless Dir.exists?("app/views/devise/cookie_crypt")
23
+ Dir.mkdir("app/views/devise/cookie_crypt")
24
+ copy_file "max_login_attempts_reached.html.erb", "app/views/devise/cookie_crypt/max_login_attempts_reached.html.erb"
25
+ copy_file "show.html.erb", "app/views/devise/cookie_crypt/show.html.erb"
26
+ end
27
+ end
28
+
29
+ hook_for :orm
30
+ end
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cookie_crypt
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Dmitrii Golub
8
+ - Louis Alridge
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-10-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: 3.1.1
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: 3.1.1
28
+ - !ruby/object:Gem::Dependency
29
+ name: devise
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: useragent
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: bundler
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ description: |2
71
+ ### Features ###
72
+ * User customizable security questions and answers
73
+ * Configurable max login attempts
74
+ * per user level control if he really need two factor authentication
75
+ email:
76
+ - loualrid@gmail.com
77
+ executables: []
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - .gitignore
82
+ - Gemfile
83
+ - LICENSE
84
+ - README.md
85
+ - Rakefile
86
+ - app/controllers/devise/cookie_crypt_controller.rb
87
+ - app/views/devise/cookie_crypt/max_login_attempts_reached.html.erb
88
+ - app/views/devise/cookie_crypt/show.html.erb
89
+ - config/locales/en.yml
90
+ - cookie_crypt.gemspec
91
+ - lib/cookie_crypt.rb
92
+ - lib/cookie_crypt/controllers/helpers.rb
93
+ - lib/cookie_crypt/hooks/cookie_cryptable.rb
94
+ - lib/cookie_crypt/models/cookie_cryptable.rb
95
+ - lib/cookie_crypt/orm/active_record.rb
96
+ - lib/cookie_crypt/rails.rb
97
+ - lib/cookie_crypt/routes.rb
98
+ - lib/cookie_crypt/schema.rb
99
+ - lib/cookie_crypt/version.rb
100
+ - lib/generators/active_record/cookie_crypt_generator.rb
101
+ - lib/generators/active_record/templates/migration.rb
102
+ - lib/generators/cookie_crypt/cookie_crypt_generator.rb
103
+ homepage: https://github.com/loualrid/CookieCrypt
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project: cookie_crypt
123
+ rubygems_version: 2.0.6
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Encrypted cookie two factor authentication plugin for devise
127
+ test_files: []