diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index abb5b212a..2cd93c9aa 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -205,13 +205,17 @@ class UsersController < ApplicationController
   def password_reset
     expires_now()
 
-    @user = EmailToken.confirm(params[:token])
+    if EmailToken.valid_token_format?(params[:token])
+      @user = EmailToken.confirm(params[:token])
 
-    if @user
-      session[params[:token]] = @user.id
+      if @user
+        session["password-#{params[:token]}"] = @user.id
+      else
+        user_id = session["password-#{params[:token]}"]
+        @user = User.find(user_id) if user_id
+      end
     else
-      user_id = session[params[:token]]
-      @user = User.find(user_id) if user_id
+      @invalid_token = true
     end
 
     if !@user
diff --git a/app/models/email_token.rb b/app/models/email_token.rb
index 66ac9112d..ff8494378 100644
--- a/app/models/email_token.rb
+++ b/app/models/email_token.rb
@@ -39,9 +39,12 @@ class EmailToken < ActiveRecord::Base
     SecureRandom.hex(EmailToken.token_length)
   end
 
+  def self.valid_token_format?(token)
+    return token.present? && token =~ /[a-f0-9]{#{token.length/2}}/i
+  end
+
   def self.confirm(token)
-    return unless token.present?
-    return unless token.length/2 == EmailToken.token_length
+    return unless valid_token_format?(token)
 
     email_token = EmailToken.where("token = ? and expired = FALSE AND ((NOT confirmed AND created_at >= ?) OR (confirmed AND created_at >= ?))", token, EmailToken.valid_after, EmailToken.confirm_valid_after).includes(:user).first
     return if email_token.blank?
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index 832789326..053eb2391 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -243,7 +243,7 @@ describe UsersController do
       end
     end
 
-    context 'invalid token' do
+    context 'missing token' do
       before do
         get :password_reset, token: SecureRandom.hex
       end
@@ -251,9 +251,22 @@ describe UsersController do
       it 'disallows login' do
         flash[:error].should be_present
         session[:current_user_id].should be_blank
+        assigns[:invalid_token].should be_nil
         response.should be_success
       end
+    end
 
+    context 'invalid token' do
+      before do
+        get :password_reset, token: "evil_trout!"
+      end
+
+      it 'disallows login' do
+        flash[:error].should be_present
+        session[:current_user_id].should be_blank
+        assigns[:invalid_token].should be_true
+        response.should be_success
+      end
     end
 
     context 'valid token' do
@@ -269,18 +282,19 @@ describe UsersController do
     end
 
     context 'submit change' do
+      let(:token) { EmailToken.generate_token }
       before do
-        EmailToken.expects(:confirm).with('asdfasdf').returns(user)
+        EmailToken.expects(:confirm).with(token).returns(user)
       end
 
       it "logs in the user" do
-        put :password_reset, token: 'asdfasdf', password: 'newpassword'
+        put :password_reset, token: token, password: 'newpassword'
         session[:current_user_id].should be_present
       end
 
       it "doesn't log in the user when not approved" do
         SiteSetting.expects(:must_approve_users?).returns(true)
-        put :password_reset, token: 'asdfasdf', password: 'newpassword'
+        put :password_reset, token: token, password: 'newpassword'
         session[:current_user_id].should be_blank
       end
     end