Skip to content

Commit

Permalink
Save OIDC tokens to OpenProject database.
Browse files Browse the repository at this point in the history
  • Loading branch information
ba1ash authored and NobodysNightmare committed Dec 10, 2024
1 parent f48be19 commit 67f649f
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 8 deletions.
8 changes: 4 additions & 4 deletions app/services/authentication/omniauth_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def call(additional_user_params = nil)

# Create or update the user from omniauth
# and assign non-nil parameters from the registration form - if any
assignable_params = (additional_user_params || {}).reject { |_, v| v.nil? }
assignable_params = (additional_user_params || {}).compact
update_user_from_omniauth!(assignable_params)

# If we have a new or invited user, we still need to register them
Expand Down Expand Up @@ -99,7 +99,7 @@ def inspect_response(log_level)
# After login flow
def tap_service_result(call)
if call.success? && user.active?
OpenProject::Hook.call_hook :omniauth_user_authorized, { auth_hash:, controller: }
OpenProject::Hook.call_hook :omniauth_user_authorized, { auth_hash:, controller:, user: }
# Call deprecated login hook
OpenProject::OmniAuth::Authorization.after_login! user, auth_hash, self
end
Expand Down Expand Up @@ -165,7 +165,7 @@ def find_existing_user
def remap_existing_user
return unless Setting.oauth_allow_remapping_of_existing_users?

User.not_builtin.find_by_login(user_attributes[:login]) # rubocop:disable Rails/DynamicFindBy
User.not_builtin.find_by_login(user_attributes[:login])
end

##
Expand Down Expand Up @@ -285,7 +285,7 @@ def identity_url_from_omniauth
# Try to provide some context of the auth_hash in case of errors
def auth_uid
hash = auth_hash || {}
hash.dig(:info, :uid) || hash.dig(:uid) || "unknown"
hash.dig(:info, :uid) || hash[:uid] || "unknown"
end
end
end
34 changes: 34 additions & 0 deletions db/migrate/20240806174815_add_tokens_to_oidc_user_session_links.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 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.
#++

class AddTokensToOidcUserSessionLinks < ActiveRecord::Migration[7.1]
def change
add_column :oidc_user_session_links, :access_token, :string
add_column :oidc_user_session_links, :refresh_token, :string
end
end
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2024 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.
#++

module OpenIDConnect
class UserSessionLink < ::ApplicationRecord
self.table_name = "oidc_user_session_links"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ class Engine < ::Rails::Engine
end

# Remember oidc session values when logging in user
h[:retain_from_session] = %w[omniauth.oidc_sid]
h[:retain_from_session] = %w[
omniauth.oidc_sid
omniauth.oidc_access_token
omniauth.oidc_refresh_token
]

h[:backchannel_logout_callback] = ->(logout_token) do
::OpenProject::OpenIDConnect::SessionMapper.handle_logout(logout_token)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,28 @@ class Hook < OpenProject::Hook::Listener
def user_logged_in(context)
session = context[:session]
oidc_sid = session["omniauth.oidc_sid"]

return if oidc_sid.nil?

::OpenProject::OpenIDConnect::SessionMapper.handle_login(oidc_sid, session)
end

##
# Called once omniauth has returned with an auth hash
# NOTE: It's a passthrough as we no longer persist the access token into the cookie
def omniauth_user_authorized(_context); end
def omniauth_user_authorized(context)
auth_hash = context[:auth_hash]
controller = context[:controller]
_user = context[:user]
credentials = auth_hash[:credentials]
access_token = credentials[:token]
refresh_token = credentials[:refresh_token]
session = controller.session
session["omniauth.oidc_access_token"] = access_token
session["omniauth.oidc_refresh_token"] = refresh_token
nil
rescue StandardError => e
Rails.logger.info "Something went wrong in omniauth_user_authorized hook: #{e}"
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ def self.handle_login(oidc_session, session)
return
end

link = ::OpenIDConnect::UserSessionLink.new(oidc_session:)
link = ::OpenIDConnect::UserSessionLink.new(oidc_session:,
access_token: session["omniauth.oidc_access_token"],
refresh_token: session["omniauth.oidc_refresh_token"])
new(link).link_to_internal!(session)
rescue StandardError => e
Rails.logger.error { "Failed to map OIDC session to internal: #{e.message}" }
Expand Down

0 comments on commit 67f649f

Please sign in to comment.