I am developing a custom strategy for LDAP authentication, and I have implemented the valid?
and authenticate!
methods as per http://kyan.com/blog/2013/10/11/devise-authentication-strategies and this Devise wiki. My custom strategy works by itself.
I also want to use the Lockable module (and other Devise modules), but they seem to work only when Database_Authenticatable is also present. I have been reading the Devise source code, but I do not understand how Lockable is able to find the user (resource) in order to increment the :failed_attempts count. How do I pass the user record or resource to Lockable using my custom strategy?
My custom strategy is below. I am using Devise 3.5 and Rails 4.2
require 'net/ldap'
require 'devise/strategies/authenticatable'
module Devise
module Strategies
class LdapAuthenticatable < Authenticatable
def valid?
params[:user] && login.present? && password.present?
end
def authenticate!
resource = mapping.to.find_for_authentication(email: params[:user][:email])
if params[:user]
begin
ldap = Net::LDAP.new
ldap.auth(my_ldap_service, my_ldap_service_password)
ldap.encryption(:simple_tls)
ldap.base = "base_here"
ldap.host = my_ldap_host
ldap.port = "636"
result_attrs = ["employeenumber", "givenname", "sn", "mail", "department"]
result = ldap.bind_as(base: "base_here", filter: "(mail=#{login})", attributes: result_attrs, password: password, time: 3)
if result
#valid ldap credentials
user = get_user_from_database(result)
if user
success!(user)
else
fail!(:invalid_login)
end
else
fail!(:invalid_login)
end
rescue => e
Rails.logger.error e.message
fail!(:invalid_login)
end
end
end
def login
params[:user][:email]
end
def password
params[:user][:password]
end
end
end
end
I ended up using devise_custom_authenticatable in combination with the resources posted on the original question. For lockable to work, database_authenticable must be present. Toni's answer above should work if you have control over LDAP, which I did not when I posed the question.