summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzul <azul@leap.se>2014-05-01 10:45:57 +0200
committerAzul <azul@leap.se>2014-05-26 09:58:40 +0200
commit5764daae090227bf4c5967900b708392c967be47 (patch)
treed611429113b8b0ebc363f8b0333c6896a41c7ced
parent0f686b1256b4190522bcb101ba06cd2c7406eb36 (diff)
hash token with sha512 against timing attacs #3398
-rw-r--r--app/controllers/controller_extension/token_authentication.rb4
-rw-r--r--app/models/token.rb13
-rw-r--r--test/functional/test_helpers_test.rb2
-rw-r--r--test/functional/v1/sessions_controller_test.rb2
-rw-r--r--test/integration/api/token_test.rb15
-rw-r--r--test/support/auth_test_helper.rb5
-rw-r--r--test/unit/token_test.rb23
7 files changed, 47 insertions, 17 deletions
diff --git a/app/controllers/controller_extension/token_authentication.rb b/app/controllers/controller_extension/token_authentication.rb
index 6e0a6ce..b0ed624 100644
--- a/app/controllers/controller_extension/token_authentication.rb
+++ b/app/controllers/controller_extension/token_authentication.rb
@@ -2,8 +2,8 @@ module ControllerExtension::TokenAuthentication
extend ActiveSupport::Concern
def token
- @token ||= authenticate_with_http_token do |token_id, options|
- Token.find(token_id)
+ @token ||= authenticate_with_http_token do |token, options|
+ Token.find_by_token(token)
end
end
diff --git a/app/models/token.rb b/app/models/token.rb
index e759ee3..ff2ad12 100644
--- a/app/models/token.rb
+++ b/app/models/token.rb
@@ -1,3 +1,5 @@
+require 'digest/sha2'
+
class Token < CouchRest::Model::Base
use_database :tokens
@@ -11,10 +13,16 @@ class Token < CouchRest::Model::Base
validates :user_id, presence: true
+ attr_accessor :token
+
design do
view :by_last_seen_at
end
+ def self.find_by_token(token)
+ self.find Digest::SHA512.hexdigest(token)
+ end
+
def self.expires_after
APP_CONFIG[:auth] && APP_CONFIG[:auth][:token_expires_after]
end
@@ -31,7 +39,7 @@ class Token < CouchRest::Model::Base
end
def to_s
- id
+ token
end
def authenticate
@@ -65,7 +73,8 @@ class Token < CouchRest::Model::Base
def initialize(*args)
super
if new_record?
- self.id = SecureRandom.urlsafe_base64(32).gsub(/^_*/, '')
+ self.token = SecureRandom.urlsafe_base64(32).gsub(/^_*/, '')
+ self.id = Digest::SHA512.hexdigest(self.token)
self.last_seen_at = Time.now
end
end
diff --git a/test/functional/test_helpers_test.rb b/test/functional/test_helpers_test.rb
index 845e516..ca85482 100644
--- a/test/functional/test_helpers_test.rb
+++ b/test/functional/test_helpers_test.rb
@@ -27,7 +27,7 @@ class TestHelpersTest < ActionController::TestCase
def test_login_adds_token_header
login
token_present = @controller.authenticate_with_http_token do |token, options|
- assert_equal @token.id, token
+ assert_equal @token.to_s, token
end
# authenticate_with_http_token just returns nil and does not
# execute the block if there is no token. So we have to also
diff --git a/test/functional/v1/sessions_controller_test.rb b/test/functional/v1/sessions_controller_test.rb
index df0d681..8bb6acd 100644
--- a/test/functional/v1/sessions_controller_test.rb
+++ b/test/functional/v1/sessions_controller_test.rb
@@ -48,7 +48,7 @@ class V1::SessionsControllerTest < ActionController::TestCase
assert_response :success
assert json_response.keys.include?("id")
assert json_response.keys.include?("token")
- assert token = Token.find(json_response['token'])
+ assert token = Token.find_by_token(json_response['token'])
assert_equal @user.id, token.user_id
end
diff --git a/test/integration/api/token_test.rb b/test/integration/api/token_test.rb
new file mode 100644
index 0000000..ad3ac22
--- /dev/null
+++ b/test/integration/api/token_test.rb
@@ -0,0 +1,15 @@
+require 'test_helper'
+require_relative 'srp_test'
+
+class TokenTest < SrpTest
+
+ setup do
+ register_user
+ end
+
+ test "stores token SHA512 encoded" do
+ authenticate
+ token = server_auth['token']
+ assert Token.find(Digest::SHA512.hexdigest(token))
+ end
+end
diff --git a/test/support/auth_test_helper.rb b/test/support/auth_test_helper.rb
index 57f9f9b..28e9633 100644
--- a/test/support/auth_test_helper.rb
+++ b/test/support/auth_test_helper.rb
@@ -46,8 +46,9 @@ module AuthTestHelper
protected
def header_for_token_auth
- @token = find_record(:token, :authenticate => @current_user)
- ActionController::HttpAuthentication::Token.encode_credentials @token.id
+ @token = stub_record(:token, :authenticate => @current_user)
+ Token.stubs(:find_by_token).with(@token.token).returns(@token)
+ ActionController::HttpAuthentication::Token.encode_credentials @token.token
end
def expect_warden_logout
diff --git a/test/unit/token_test.rb b/test/unit/token_test.rb
index a3c6cf6..b143345 100644
--- a/test/unit/token_test.rb
+++ b/test/unit/token_test.rb
@@ -14,17 +14,22 @@ class ClientCertificateTest < ActiveSupport::TestCase
assert_equal @user, sample.authenticate
end
- test "token id is secure" do
+ test "token is secure" do
sample = Token.new(:user_id => @user.id)
other = Token.new(:user_id => @user.id)
- assert sample.id,
- "id is set on initialization"
- assert sample.id[0..10] != other.id[0..10],
- "token id prefixes should not repeat"
- assert /[g-zG-Z]/.match(sample.id),
- "should use non hex chars in the token id"
- assert sample.id.size > 16,
- "token id should be more than 16 chars long"
+ assert sample.token,
+ "token is set on initialization"
+ assert sample.token[0..10] != other.token[0..10],
+ "token prefixes should not repeat"
+ assert /[g-zG-Z]/.match(sample.token),
+ "should use non hex chars in the token"
+ assert sample.token.size > 16,
+ "token should be more than 16 chars long"
+ end
+
+ test "token id is hash of the token" do
+ sample = Token.new(:user_id => @user.id)
+ assert_equal Digest::SHA512.hexdigest(sample.token), sample.id
end
test "token checks for user" do