mirror of
https://github.com/czhu12/canine.git
synced 2026-05-03 18:09:47 -05:00
more implementation for ldap
This commit is contained in:
@@ -1,41 +1,48 @@
|
||||
require 'net/ldap'
|
||||
require 'devise/strategies/authenticatable'
|
||||
|
||||
module Devise
|
||||
module Strategies
|
||||
class LdapAuthenticatable < Authenticatable
|
||||
class LDAPAuthenticatable < Authenticatable
|
||||
def valid?
|
||||
true
|
||||
end
|
||||
|
||||
def authenticate!
|
||||
if params[:user]
|
||||
ldap_config = find_ldap_configuration
|
||||
ldap_configuration = find_ldap_configuration
|
||||
|
||||
return fail(:invalid_login) unless ldap_config
|
||||
return fail(:invalid_login) unless ldap_configuration
|
||||
|
||||
ldap = Net::LDAP.new(
|
||||
host: ldap_config.host,
|
||||
port: ldap_config.port,
|
||||
encryption: ldap_config.encryption_method
|
||||
host: ldap_configuration.host,
|
||||
port: ldap_configuration.port,
|
||||
encryption: ldap_configuration.encryption_method
|
||||
)
|
||||
|
||||
# Build the user DN for authentication
|
||||
user_dn = build_user_dn(ldap_config, email)
|
||||
user_dn = build_user_dn(ldap_configuration, username)
|
||||
ldap.auth user_dn, password
|
||||
|
||||
if ldap.bind
|
||||
# LDAP authentication successful, find or create user
|
||||
user = User.find_or_create_by(email: email) do |u|
|
||||
u.password = SecureRandom.hex(32) # Set random password since LDAP handles auth
|
||||
u.account = find_or_create_account_for_ldap(ldap_config)
|
||||
email = construct_email(username, ldap_configuration)
|
||||
user = User.find_or_create_by(email: email) do |user|
|
||||
password = SecureRandom.hex(32)
|
||||
user.password = password
|
||||
user.password_confirmation = password
|
||||
|
||||
AccountUser.create!(account: ldap_configuration.account, user:)
|
||||
end
|
||||
success!(user)
|
||||
else
|
||||
Rails.logger.info "LDAP bind failed for #{email}: #{ldap.get_operation_result.message}"
|
||||
return fail(:invalid_login)
|
||||
fail(:invalid_login)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def email
|
||||
params[:user][:email]
|
||||
def username
|
||||
params[:user][:username]
|
||||
end
|
||||
|
||||
def password
|
||||
@@ -52,22 +59,25 @@ module Devise
|
||||
if account_id
|
||||
sso_provider = SSOProvider.find_by(account_id: account_id, enabled: true)
|
||||
return sso_provider.configuration if sso_provider&.ldap?
|
||||
else
|
||||
raise "No account ID provided"
|
||||
end
|
||||
|
||||
# Fallback: try to find by email domain or return first enabled LDAP config
|
||||
LdapConfiguration.joins(:sso_provider)
|
||||
.where(sso_providers: { enabled: true })
|
||||
.first
|
||||
end
|
||||
|
||||
def build_user_dn(ldap_config, email)
|
||||
# Extract username from email if needed
|
||||
username = email.split('@').first
|
||||
|
||||
def build_user_dn(ldap_config, username)
|
||||
# Build the DN using the uid attribute and base DN
|
||||
"#{ldap_config.uid_attribute}=#{username},#{ldap_config.base_dn}"
|
||||
end
|
||||
|
||||
def construct_email(username, ldap_config)
|
||||
# If username is already an email, use it as-is
|
||||
return username if username.include?('@')
|
||||
|
||||
# Otherwise, construct email using mail_domain from config if available
|
||||
domain = ldap_config.try(:mail_domain) || ldap_config.host
|
||||
"#{username}@#{domain}"
|
||||
end
|
||||
|
||||
def find_or_create_account_for_ldap(ldap_config)
|
||||
sso_provider = ldap_config.sso_provider
|
||||
sso_provider&.account
|
||||
@@ -75,5 +85,3 @@ module Devise
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Warden::Strategies.add(:ldap_authenticatable, Devise::Strategies::LdapAuthenticatable)
|
||||
|
||||
Reference in New Issue
Block a user