diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ebd5b0343..12e30346b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,7 +5,13 @@ class ApplicationController < ActionController::Base before_action :force_tablet_html has_mobile_fu - protect_from_forgery except: :receive + protect_from_forgery except: :receive, with: :exception + + rescue_from ActionController::InvalidAuthenticityToken do + sign_out current_user + flash[:error] = I18n.t("error_messages.csrf_token_fail") + redirect_to new_user_session_path format: request[:format] + end before_action :ensure_http_referer_is_set before_action :set_locale diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 8d952a298..523e9615f 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -75,6 +75,7 @@ en: helper: correct_the_following_errors_and_try_again: "Correct the following errors and try again." need_javascript: "This website requires JavaScript to function properly. If you disabled JavaScript, please enable it and refresh this page." + csrf_token_fail: "The CSRF token is invalid. Please sign in and try again." admins: admin_bar: diff --git a/spec/integration/application_spec.rb b/spec/integration/application_spec.rb new file mode 100644 index 000000000..014b40e5c --- /dev/null +++ b/spec/integration/application_spec.rb @@ -0,0 +1,48 @@ +require "spec_helper" + +describe ApplicationController, type: :request do + describe "csrf token validation" do + context "without a current user" do + before do + @user = alice + @user.password = "evankorth" + @user.password_confirmation = "evankorth" + @user.save + end + + it "redirects to the new session page on validation fails" do + expect_any_instance_of(SessionsController).to receive(:verified_request?).and_return(false) + post "/users/sign_in", user: {remember_me: 0, username: @user.username, password: "evankorth"} + expect(response).to redirect_to new_user_session_path + expect(flash[:error]).to eq(I18n.t("error_messages.csrf_token_fail")) + end + + it "doesn't redirect to the new session page if the validation succeeded" do + expect_any_instance_of(SessionsController).to receive(:verified_request?).and_return(true) + post "/users/sign_in", user: {remember_me: 0, username: @user.username, password: "evankorth"} + expect(response).to redirect_to stream_path + expect(flash[:error]).to be_blank + end + end + + context "with a current user" do + before do + sign_in alice + end + + it "signs out users if a wrong token was given" do + expect_any_instance_of(UsersController).to receive(:verified_request?).and_return(false) + put edit_user_path, user: {language: "en"} + expect(response).to redirect_to new_user_session_path + expect(flash[:error]).to eq(I18n.t("error_messages.csrf_token_fail")) + end + + it "doesn't sign out users if the token was correct" do + expect_any_instance_of(UsersController).to receive(:verified_request?).and_return(true) + put edit_user_path, user: {language: "en"} + expect(response).not_to be_redirect + expect(flash[:error]).to be_blank + end + end + end +end