[40240] Return the original authenticated user in case of optional sso

https://community.openproject.org/wp/40240
This commit is contained in:
Oliver Günther
2021-12-06 09:39:08 +01:00
parent cad48d6a58
commit dea629ce70
3 changed files with 96 additions and 18 deletions
+16 -14
View File
@@ -14,6 +14,17 @@ module AuthSourceSSO
# Get the header-provided login value
login = read_sso_login
if login.present?
perform_header_sso login, user
elsif header_optional?
user
else
handle_sso_failure!
nil
end
end
def perform_header_sso(login, user)
# Log out the current user if the login does not match
logged_user = match_sso_with_logged_user(login, user)
@@ -21,7 +32,9 @@ module AuthSourceSSO
return logged_user if logged_user.present?
Rails.logger.debug { "Starting header-based auth source SSO for #{header_name}='#{op_auth_header_value}'" }
perform_header_sso login
user = find_user_from_auth_source(login) || create_user_from_auth_source(login)
handle_sso_for! user, login
end
def match_sso_with_logged_user(login, user)
@@ -34,16 +47,6 @@ module AuthSourceSSO
nil
end
def perform_header_sso(login)
if login
user = find_user_from_auth_source(login) || create_user_from_auth_source(login)
handle_sso_for! user, login
else
handle_sso_failure!
end
end
def read_sso_login
get_validated_login! op_auth_header_value
end
@@ -162,7 +165,8 @@ module AuthSourceSSO
def handle_sso_for!(user, login)
if sso_login_failed?(user)
handle_sso_failure!({ user: user, login: login })
else # valid user
else
# valid user
# If a user is invited, ensure it gets activated
activated = user.invited?
activate_user_if_invited! user
@@ -191,8 +195,6 @@ module AuthSourceSSO
end
def handle_sso_failure!(session_args = {})
return if header_optional?
session[:auth_source_sso_failure] = session_args.merge(
back_url: request.base_url + request.original_fullpath,
ttl: 1
@@ -45,6 +45,7 @@ describe MyController, type: :controller do
let!(:user) { FactoryBot.create :user, login: login, auth_source_id: auth_source.id, last_login_on: 5.days.ago }
let(:login) { "h.wurst" }
let(:header_login_value) { login }
let(:header_value) { "#{header_login_value}#{secret ? ':' : ''}#{secret}" }
shared_examples 'should log in the user' do
it "logs in given user" do
@@ -81,8 +82,19 @@ describe MyController, type: :controller do
}
end
it "should redirect to login" do
expect(response).to redirect_to("/login?back_url=http%3A%2F%2Ftest.host%2Fmy%2Faccount")
context 'when no header is present' do
let(:header_value) { nil }
it "redirects to login" do
expect(response).to redirect_to("/login?back_url=http%3A%2F%2Ftest.host%2Fmy%2Faccount")
end
end
context 'when the header is present' do
it "shows an error" do
expect(response).to redirect_to("/sso")
expect(session).to have_key(:auth_source_sso_failure)
end
end
end
end
@@ -94,8 +106,7 @@ describe MyController, type: :controller do
.and_return(sso_config)
end
separator = secret ? ':' : ''
request.headers[header] = "#{header_login_value}#{separator}#{secret}"
request.headers[header] = header_value
end
describe 'login' do
@@ -0,0 +1,65 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require 'spec_helper'
describe 'Login with auth source SSO', type: :feature, clear_cache: true do
before do
if sso_config
allow(OpenProject::Configuration)
.to receive(:auth_source_sso)
.and_return(sso_config)
end
end
let(:sso_config) do
{
header: "X-Remote-User",
optional: true
}
end
let(:user_password) { 'bob' * 4 }
let(:user) do
FactoryBot.create(:user,
login: 'bob',
password: user_password,
password_confirmation: user_password)
end
it 'can still login' do
login_with(user.login, user_password)
# on the my page
expect(page)
.to have_current_path my_page_path
expect(page)
.to have_selector("a[title='#{user.name}']")
end
end