feat: move SAML code to enterprise
This commit is contained in:
@@ -1,75 +1,12 @@
|
||||
class DeviseOverrides::OmniauthCallbacksController < DeviseTokenAuth::OmniauthCallbacksController
|
||||
include EmailHelper
|
||||
|
||||
def saml
|
||||
# Call parent's omniauth_success which handles the auth
|
||||
omniauth_success
|
||||
end
|
||||
|
||||
def redirect_callbacks
|
||||
# derive target redirect route from 'resource_class' param, which was set
|
||||
# before authentication.
|
||||
devise_mapping = get_devise_mapping
|
||||
redirect_route = get_redirect_route(devise_mapping)
|
||||
|
||||
# preserve omniauth info for success route. ignore 'extra' in twitter
|
||||
# auth response to avoid CookieOverflow.
|
||||
session['dta.omniauth.auth'] = request.env['omniauth.auth'].except('extra')
|
||||
session['dta.omniauth.params'] = request.env['omniauth.params']
|
||||
|
||||
# For SAML, use 303 See Other to convert POST to GET and preserve session
|
||||
if params[:provider] == 'saml'
|
||||
redirect_to redirect_route, { status: 303 }.merge(redirect_options)
|
||||
else
|
||||
redirect_to redirect_route, { status: 307 }.merge(redirect_options)
|
||||
end
|
||||
end
|
||||
|
||||
def omniauth_success
|
||||
case auth_hash&.dig('provider')
|
||||
when 'saml'
|
||||
handle_saml_auth
|
||||
else
|
||||
handle_standard_auth
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def handle_saml_auth
|
||||
# Check if enterprise edition and SAML feature are available
|
||||
return redirect_to login_page_url(error: 'saml-not-available') unless ChatwootApp.enterprise?
|
||||
|
||||
account_id = extract_saml_account_id
|
||||
return redirect_to login_page_url(error: 'saml-not-enabled') unless saml_enabled_for_account?(account_id)
|
||||
|
||||
@resource = SamlUserBuilder.new(auth_hash, account_id: account_id).perform
|
||||
|
||||
if @resource.persisted?
|
||||
sign_in_user
|
||||
else
|
||||
redirect_to login_page_url(error: 'saml-authentication-failed')
|
||||
end
|
||||
end
|
||||
|
||||
def handle_standard_auth
|
||||
get_resource_from_auth_hash
|
||||
@resource.present? ? sign_in_user : sign_up_user
|
||||
end
|
||||
|
||||
def extract_saml_account_id
|
||||
params[:account_id] || session[:saml_account_id] || request.env['omniauth.params']&.dig('account_id')
|
||||
end
|
||||
|
||||
def saml_enabled_for_account?(account_id)
|
||||
return false unless ChatwootApp.enterprise?
|
||||
return false if account_id.blank?
|
||||
|
||||
account = Account.find_by(id: account_id)
|
||||
return false unless account.feature_enabled?('saml')
|
||||
|
||||
AccountSamlSettings.find_by(account_id: account_id, enabled: true).present?
|
||||
end
|
||||
private
|
||||
|
||||
def sign_in_user
|
||||
@resource.skip_confirmation! if confirmable_enabled?
|
||||
@@ -135,3 +72,5 @@ class DeviseOverrides::OmniauthCallbacksController < DeviseTokenAuth::OmniauthCa
|
||||
'user'
|
||||
end
|
||||
end
|
||||
|
||||
DeviseOverrides::OmniauthCallbacksController.prepend_mod_with('DeviseOverrides::OmniauthCallbacksController')
|
||||
|
||||
@@ -3,7 +3,6 @@ class DeviseOverrides::PasswordsController < Devise::PasswordsController
|
||||
|
||||
skip_before_action :require_no_authentication, raise: false
|
||||
skip_before_action :authenticate_user!, raise: false
|
||||
before_action :check_saml_user, only: [:create]
|
||||
|
||||
def create
|
||||
@user = User.from_email(params[:email])
|
||||
@@ -44,13 +43,6 @@ class DeviseOverrides::PasswordsController < Devise::PasswordsController
|
||||
message: message
|
||||
}, status: status
|
||||
end
|
||||
|
||||
def check_saml_user
|
||||
return if params[:email].blank?
|
||||
|
||||
user = User.from_email(params[:email])
|
||||
return unless user&.saml_user?
|
||||
|
||||
build_response(I18n.t('messages.reset_password_saml_user'), 403)
|
||||
end
|
||||
end
|
||||
|
||||
DeviseOverrides::PasswordsController.prepend_mod_with('DeviseOverrides::PasswordsController')
|
||||
|
||||
@@ -3,7 +3,6 @@ class DeviseOverrides::SessionsController < DeviseTokenAuth::SessionsController
|
||||
# Unpermitted parameter: session
|
||||
wrap_parameters format: []
|
||||
before_action :process_sso_auth_token, only: [:create]
|
||||
before_action :check_saml_user, only: [:create]
|
||||
|
||||
def new
|
||||
redirect_to login_page_url(error: 'access-denied')
|
||||
@@ -47,24 +46,6 @@ class DeviseOverrides::SessionsController < DeviseTokenAuth::SessionsController
|
||||
user = User.from_email(params[:email])
|
||||
@resource = user if user&.valid_sso_auth_token?(params[:sso_auth_token])
|
||||
end
|
||||
|
||||
def check_saml_user
|
||||
# Skip if using SSO token (SAML users can use SSO tokens)
|
||||
return if params[:sso_auth_token].present?
|
||||
return if params[:email].blank?
|
||||
|
||||
user = User.from_email(params[:email])
|
||||
return unless user&.saml_user?
|
||||
|
||||
render_saml_user_error
|
||||
end
|
||||
|
||||
def render_saml_user_error
|
||||
render json: {
|
||||
success: false,
|
||||
errors: [I18n.t('messages.login_saml_user')]
|
||||
}, status: :unauthorized
|
||||
end
|
||||
end
|
||||
|
||||
DeviseOverrides::SessionsController.prepend_mod_with('DeviseOverrides::SessionsController')
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
module Enterprise::DeviseOverrides::OmniauthCallbacksController
|
||||
def saml
|
||||
# Call parent's omniauth_success which handles the auth
|
||||
omniauth_success
|
||||
end
|
||||
|
||||
def redirect_callbacks
|
||||
# derive target redirect route from 'resource_class' param, which was set
|
||||
# before authentication.
|
||||
devise_mapping = get_devise_mapping
|
||||
redirect_route = get_redirect_route(devise_mapping)
|
||||
|
||||
# preserve omniauth info for success route. ignore 'extra' in twitter
|
||||
# auth response to avoid CookieOverflow.
|
||||
session['dta.omniauth.auth'] = request.env['omniauth.auth'].except('extra')
|
||||
session['dta.omniauth.params'] = request.env['omniauth.params']
|
||||
|
||||
# For SAML, use 303 See Other to convert POST to GET and preserve session
|
||||
if params[:provider] == 'saml'
|
||||
redirect_to redirect_route, { status: 303 }.merge(redirect_options)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def omniauth_success
|
||||
case auth_hash&.dig('provider')
|
||||
when 'saml'
|
||||
handle_saml_auth
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def handle_saml_auth
|
||||
# Check if enterprise edition and SAML feature are available
|
||||
return redirect_to login_page_url(error: 'saml-not-available') unless ChatwootApp.enterprise?
|
||||
|
||||
account_id = extract_saml_account_id
|
||||
return redirect_to login_page_url(error: 'saml-not-enabled') unless saml_enabled_for_account?(account_id)
|
||||
|
||||
@resource = SamlUserBuilder.new(auth_hash, account_id: account_id).perform
|
||||
|
||||
if @resource.persisted?
|
||||
sign_in_user
|
||||
else
|
||||
redirect_to login_page_url(error: 'saml-authentication-failed')
|
||||
end
|
||||
end
|
||||
|
||||
def extract_saml_account_id
|
||||
params[:account_id] || session[:saml_account_id] || request.env['omniauth.params']&.dig('account_id')
|
||||
end
|
||||
|
||||
def saml_enabled_for_account?(account_id)
|
||||
return false unless ChatwootApp.enterprise?
|
||||
return false if account_id.blank?
|
||||
|
||||
account = Account.find_by(id: account_id)
|
||||
return false unless account.feature_enabled?('saml')
|
||||
|
||||
AccountSamlSettings.find_by(account_id: account_id, enabled: true).present?
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
module Enterprise::DeviseOverrides::PasswordsController
|
||||
def create
|
||||
check_saml_user
|
||||
super
|
||||
rescue CustomExceptions::Base => e
|
||||
build_response(e.message, e.http_status_code)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_saml_user
|
||||
return if params[:email].blank?
|
||||
|
||||
user = User.from_email(params[:email])
|
||||
return unless user&.saml_user?
|
||||
|
||||
raise CustomExceptions::Base.new(I18n.t('messages.reset_password_saml_user'), :forbidden)
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,14 @@
|
||||
module Enterprise::DeviseOverrides::SessionsController
|
||||
def create
|
||||
check_saml_user
|
||||
super
|
||||
rescue CustomExceptions::Base => e
|
||||
render json: {
|
||||
success: false,
|
||||
errors: [e.message]
|
||||
}, status: e.http_status_code
|
||||
end
|
||||
|
||||
def render_create_success
|
||||
create_audit_event('sign_in')
|
||||
super
|
||||
@@ -22,4 +32,17 @@ module Enterprise::DeviseOverrides::SessionsController
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_saml_user
|
||||
# Skip if using SSO token (SAML users can use SSO tokens)
|
||||
return if params[:sso_auth_token].present?
|
||||
return if params[:email].blank?
|
||||
|
||||
user = User.from_email(params[:email])
|
||||
return unless user&.saml_user?
|
||||
|
||||
raise CustomExceptions::Base.new(I18n.t('messages.login_saml_user'), :unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user