more implementation for ldap

This commit is contained in:
Chris
2025-11-22 09:12:10 -08:00
parent 79077f45a8
commit 458381fecf
29 changed files with 687 additions and 210 deletions
+33 -25
View File
@@ -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)