Skip to content
This repository has been archived by the owner on Feb 6, 2024. It is now read-only.

Add context parameter for authenticators #126

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/casino/sessions_controller.rb
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def new
end

def create
validation_result = validate_login_credentials(params[:username], params[:password])
validation_result = validate_login_credentials(params[:username], params[:password], current_authenticator_context)
if !validation_result
show_login_error I18n.t('login_credential_acceptor.invalid_login_credentials')
else
Expand Down
4 changes: 4 additions & 0 deletions app/helpers/casino/sessions_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def current_user
tgt.user
end

def current_authenticator_context
CASino.config.authenticator_context_builder.call(params, request)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the suggested approach to set CASino.config.authenticator_context_builder?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pencil it's very simple -- your "builder" returns an object that is used by your custom authenticator. In my case, I just need to get the host of the request, so that I can look up specific records segmented by the current hostname (or domain name or subdomain name). In my case, I return a Hash such as {host: request.host}. I could look at headers, request parameters, or other places to get more data about the request that may be relevant to my authenticator (particularly in a multi-tenant setup, where the database is segmented based on something like the domain name).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more thinking about: How is the config option set? Options are currently loaded from the cas.yml which in this case will not work (since it has to be a Proc). Is the suggested approach to set this specific option in an initializer?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pencil we could have a authenticator_context_builder_class option that is "constantized" and set to the authenticator_context_builder property. The class would simply need to have a call method on it.

Of course, we could create a default constant class that parses config options and does something like refer to request properties, but that gets very complicated and also requires specific opinions about what the context does or consists of. We should keep it to declarative procs or classes.

Thoughts?

end

def ensure_signed_in
redirect_to login_path unless signed_in?
end
Expand Down
10 changes: 8 additions & 2 deletions app/processors/casino/authentication_processor.rb
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
module CASino::AuthenticationProcessor
extend ActiveSupport::Concern

def validate_login_credentials(username, password)
def validate_login_credentials(username, password, context = nil)
authentication_result = nil
authenticators.each do |authenticator_name, authenticator|
begin
data = authenticator.validate(username, password)
credentials = [ username, password, context ]

# Old authenticators that don't accept a 3rd context parameter will have a validate
# method that only accepts 2 arguments, so check for that.
credentials.pop if authenticator.class.instance_method(:validate).arity == 2

data = authenticator.validate(*credentials)
rescue CASino::Authenticator::AuthenticatorError => e
Rails.logger.error "Authenticator '#{authenticator_name}' (#{authenticator.class}) raised an error: #{e}"
end
Expand Down
1 change: 1 addition & 0 deletions lib/casino.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module CASino

defaults = {
authenticators: HashWithIndifferentAccess.new,
authenticator_context_builder: ->(params, request){ },
logger: Rails.logger,
frontend: HashWithIndifferentAccess.new(
sso_name: 'CASino',
Expand Down