Skip to content

Commit 747751a

Browse files
author
José Valim
committed
Protect against CSRF token fixation attacks
1 parent 8e0327e commit 747751a

File tree

5 files changed

+30
-0
lines changed

5 files changed

+30
-0
lines changed

lib/devise.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ module Strategies
223223
mattr_accessor :omniauth_path_prefix
224224
@@omniauth_path_prefix = nil
225225

226+
# Set if we should clean up the CSRF Token on authentication
227+
mattr_accessor :clean_up_csrf_token_on_authentication
228+
@@clean_up_csrf_token_on_authentication = true
229+
226230
def self.encryptor=(value)
227231
warn "\n[DEVISE] To select a encryption which isn't bcrypt, you should use devise-encryptable gem.\n"
228232
end

lib/devise/hooks/csrf_cleaner.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Warden::Manager.after_authentication do |record, warden, options|
2+
if Devise.clean_up_csrf_token_on_authentication
3+
warden.request.session.try(:delete, :_csrf_token)
4+
end
5+
end

lib/devise/models/authenticatable.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'devise/hooks/activatable'
2+
require 'devise/hooks/csrf_cleaner'
23

34
module Devise
45
module Models

lib/generators/templates/devise.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@
7676
# passing :skip => :sessions to `devise_for` in your config/routes.rb
7777
config.skip_session_storage = [:http_auth]
7878

79+
# By default, Devise cleans up the CSRF token on authentication to
80+
# avoid CSRF token fixation attacks. This means that, when using AJAX
81+
# requests for sign in and sign up, you need to get a new CSRF token
82+
# from the server. You can disable this option at your own risk.
83+
# config.clean_up_csrf_token_on_authentication = true
84+
7985
# ==> Configuration for :database_authenticatable
8086
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
8187
# using other encryptors, it sets how many times you want the password re-encrypted.

test/integration/authenticatable_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,20 @@ class AuthenticationSessionTest < ActionDispatch::IntegrationTest
327327
assert_redirected_to new_user_session_path
328328
end
329329

330+
test 'refreshes _csrf_token' do
331+
ApplicationController.allow_forgery_protection = true
332+
333+
begin
334+
get new_user_session_path
335+
token = request.session[:_csrf_token]
336+
337+
sign_in_as_user
338+
assert_not_equal request.session[:_csrf_token], token
339+
ensure
340+
ApplicationController.allow_forgery_protection = false
341+
end
342+
end
343+
330344
test 'allows session to be set for a given scope' do
331345
sign_in_as_user
332346
get '/users'

0 commit comments

Comments
 (0)