140 lines
3.6 KiB
Ruby
140 lines
3.6 KiB
Ruby
module Authentication
|
|
extend ActiveSupport::Concern
|
|
|
|
included do
|
|
# Checking for tenant must happen first so we redirect before trying to access the db.
|
|
before_action :require_tenant
|
|
|
|
before_action :require_authentication
|
|
helper_method :authenticated?
|
|
|
|
etag { Current.session.id if authenticated? }
|
|
|
|
include LoginHelper
|
|
end
|
|
|
|
class_methods do
|
|
def require_unauthenticated_access(**options)
|
|
allow_unauthenticated_access **options
|
|
before_action :redirect_authenticated_user, **options
|
|
end
|
|
|
|
def allow_unauthenticated_access(**options)
|
|
skip_before_action :require_authentication, **options
|
|
before_action :resume_session, **options
|
|
end
|
|
|
|
def require_untenanted_access(**options)
|
|
skip_before_action :require_tenant, **options
|
|
skip_before_action :require_authentication, **options
|
|
before_action :redirect_tenanted_request, **options
|
|
end
|
|
|
|
def require_identity(**options)
|
|
before_action :require_identity, **options
|
|
end
|
|
end
|
|
|
|
private
|
|
def authenticated?
|
|
Current.session.present?
|
|
end
|
|
|
|
def require_tenant
|
|
unless ApplicationRecord.current_tenant.present?
|
|
if resume_identity
|
|
redirect_to session_login_menu_url(script_name: nil)
|
|
else
|
|
request_authentication
|
|
end
|
|
end
|
|
end
|
|
|
|
def require_identity
|
|
resume_identity || request_authentication
|
|
end
|
|
|
|
def require_authentication
|
|
if resume_identity
|
|
resume_session || request_session_for_identity
|
|
else
|
|
request_authentication
|
|
end
|
|
end
|
|
|
|
def request_session_for_identity
|
|
redirect_to session_login_menu_url(script_name: nil)
|
|
end
|
|
|
|
def resume_identity
|
|
if identity_token = find_identity_by_cookie
|
|
set_current_identity(identity_token)
|
|
end
|
|
end
|
|
|
|
def resume_session
|
|
if session = find_session_by_cookie
|
|
set_current_session session
|
|
end
|
|
end
|
|
|
|
def find_identity_by_cookie
|
|
IdentityProvider.verify_token(cookies.signed[:identity_token])
|
|
end
|
|
|
|
def find_session_by_cookie
|
|
Session.find_signed(cookies.signed[:session_token])
|
|
end
|
|
|
|
def request_authentication
|
|
if ApplicationRecord.current_tenant.present?
|
|
session[:return_to_after_authenticating] = request.url
|
|
end
|
|
|
|
redirect_to_login_url
|
|
end
|
|
|
|
def after_authentication_url
|
|
session.delete(:return_to_after_authenticating) || root_url
|
|
end
|
|
|
|
def after_identification_url
|
|
session.delete(:return_to_after_identification) || session_login_menu_path
|
|
end
|
|
|
|
def redirect_authenticated_user
|
|
redirect_to root_url if authenticated?
|
|
end
|
|
|
|
def redirect_tenanted_request
|
|
redirect_to root_url if ApplicationRecord.current_tenant
|
|
end
|
|
|
|
def start_new_session_for(user)
|
|
user.sessions.create!(user_agent: request.user_agent, ip_address: request.remote_ip).tap do |session|
|
|
set_current_session session
|
|
end
|
|
end
|
|
|
|
def set_current_identity(identity_token)
|
|
Current.identity_token = if identity_token
|
|
cookies.signed.permanent[:identity_token] = { value: identity_token.to_h, httponly: true, same_site: :lax }
|
|
identity_token
|
|
else
|
|
nil
|
|
end
|
|
end
|
|
|
|
def set_current_session(session)
|
|
logger.struct " Authorized User##{session.user.id}", authentication: { user: { id: session.user.id } }
|
|
Current.session = session
|
|
cookies.signed.permanent[:session_token] = { value: session.signed_id, httponly: true, same_site: :lax, path: Account.sole.slug }
|
|
end
|
|
|
|
def terminate_session
|
|
Current.session.destroy
|
|
cookies.delete(:session_token)
|
|
cookies.delete(:identity_token)
|
|
end
|
|
end
|