Rectangle 27 3

You could do this with a callback or validation on the User (or equivalent) model.

before_create :user_is_not_member_of_specified_group?

private

def user_is_not_member_of_specified_group?
  member_of = Devise::LdapAdapter.get_ldap_param(self.username,"memberOf")
  test member_of
end

where test is a method that returns true/false based on your conditions for the member groups.

Devise::LdapAdapter.get_ldap_param(self.username,"memberOf")
devise_ldap_authenticatable

If you use a validation you could specify an error message for users that failed the test. Hope this helps.

authorized?
Devise::LdapAdapter::LdapConnect
Devise::LdapAdapter::LdapConnect.class_eval do
  def user_group_test
    member_of = self.ldap_param_value("memberOf")
    test member_of # your group test method
  end

  def authorized?
    DeviseLdapAuthenticatable::Logger.send("Authorizing user #{dn}")
    if !user_group_test
      DeviseLdapAuthenticatable::Logger.send("Not authorized because custom authentication failed.")
      return false
    elsif !authenticated?
      DeviseLdapAuthenticatable::Logger.send("Not authorized because not authenticated.")
      return false
    elsif !in_required_groups?
      DeviseLdapAuthenticatable::Logger.send("Not authorized because not in required groups.")
      return false
    elsif !has_required_attribute?
      DeviseLdapAuthenticatable::Logger.send("Not authorized because does not have required attribute.")
      return false
    else
      return true
    end
  end

end

You would want to put this in a custom initializer file in config/initializers.

I am still learning the finer bits of rails and ruby. Is what you wrote there a helper?

helpers
view

Ahh so this method lives in the User.rb model and the callback is defined before_create and then I can run that method which basically checks the groups for me and gives it a thumbs up or down if the user should be created in the User table of the devise database piece yah?

Correct. Rails will call user_is_not_member_of_specified_group? before it saves the new user; if this method returns false it will prevent the user from being created. However, this will display a nasty error message to the user. You'll probably want to use validation or a Devise exception to let the user know what went wrong and what they should do next.

ruby - checking groups at runtime with devise and devise_ldap_authenti...

ruby ruby-on-rails-3 devise ldap
Rectangle 27 3

You could do this with a callback or validation on the User (or equivalent) model.

before_create :user_is_not_member_of_specified_group?

private

def user_is_not_member_of_specified_group?
  member_of = Devise::LdapAdapter.get_ldap_param(self.username,"memberOf")
  test member_of
end

where test is a method that returns true/false based on your conditions for the member groups.

Devise::LdapAdapter.get_ldap_param(self.username,"memberOf")
devise_ldap_authenticatable

If you use a validation you could specify an error message for users that failed the test. Hope this helps.

authorized?
Devise::LdapAdapter::LdapConnect
Devise::LdapAdapter::LdapConnect.class_eval do
  def user_group_test
    member_of = self.ldap_param_value("memberOf")
    test member_of # your group test method
  end

  def authorized?
    DeviseLdapAuthenticatable::Logger.send("Authorizing user #{dn}")
    if !user_group_test
      DeviseLdapAuthenticatable::Logger.send("Not authorized because custom authentication failed.")
      return false
    elsif !authenticated?
      DeviseLdapAuthenticatable::Logger.send("Not authorized because not authenticated.")
      return false
    elsif !in_required_groups?
      DeviseLdapAuthenticatable::Logger.send("Not authorized because not in required groups.")
      return false
    elsif !has_required_attribute?
      DeviseLdapAuthenticatable::Logger.send("Not authorized because does not have required attribute.")
      return false
    else
      return true
    end
  end

end

You would want to put this in a custom initializer file in config/initializers.

I am still learning the finer bits of rails and ruby. Is what you wrote there a helper?

helpers
view

Ahh so this method lives in the User.rb model and the callback is defined before_create and then I can run that method which basically checks the groups for me and gives it a thumbs up or down if the user should be created in the User table of the devise database piece yah?

Correct. Rails will call user_is_not_member_of_specified_group? before it saves the new user; if this method returns false it will prevent the user from being created. However, this will display a nasty error message to the user. You'll probably want to use validation or a Devise exception to let the user know what went wrong and what they should do next.

ruby - checking groups at runtime with devise and devise_ldap_authenti...

ruby ruby-on-rails-3 devise ldap
Rectangle 27 143

Importing a whole library seems inefficient when all you need is essentially two lines of code...

$ldap = ldap_connect("ldap.example.com");
if ($bind = ldap_bind($ldap, $_POST['username'], $_POST['password'])) {
  // log them in!
} else {
  // error message
}

Some installations of AD will bind successfully if the password provided is empty. Watch out for this! You may need to ensure a non-empty password before trying to authenticate.

@diolemo Is there any way to prevent this without checking if the password is empty?

@Neal You may be able to use ldap_set_option to make it behave in a different way. Perhaps setting the protocol version? You will have to experiment. I would personally suggest you check for an empty password anyway, just to be safe.

To the anonymous editor: no, to my knowledge, input sanitization isn't required here as ldap_bind would be handling it and special characters aren't an issue.

authentication - Authenticating in PHP using LDAP through Active Direc...

php authentication active-directory ldap
Rectangle 27 1

Your PHP installation uses two different ini files - one when running from the command line, and a different one when running through Apache. This is evidenced by the fact that it works from the CLI, but not in a browser.

You can find the paths to the two files using phpinfo() (in a browser) and by passing the -i flag to php from the command line. Near the top of both sets of output you will find the path to the ini file in use, and I would be mighty surprised if they were identical. From the command line you can get more detailed information by passing the --ini flag.

The fact that you are getting Call to undefined function ldap_connect() can only mean that the LDAP extension was not loaded, and this can only be true through Apache but not through the CLI if they use two different ini files.

Sorry for the delay. I posted this late in the day at work and forgot to check it when I got home. Output from running php via cli with the -i flag shows this as the path: Loaded Configuration File => C:\Program Files (x86)\PHP\php.ini php_info() shows this as the path: Loaded Configuration File C:\Program Files (x86)\PHP\php.ini Am I crazy or are those the same thing?

apache - PHP ldap_connect() problems - Stack Overflow

php apache ldapconnection
Rectangle 27 7

function check_auth_ldap () {

  $sessionTimeoutSecs = 10;
  $ldapServer = '11.22.33.44';
  $ldapPort = 389;

  if (!isset($_SESSION)) session_start();

  if (!empty($_SESSION['lastactivity']) && $_SESSION['lastactivity'] > time() - $sessionTimeoutSecs && !isset($_GET['logout'])) {

    // Session is already authenticated
    $ds = ldap_connect($ldapServer, $ldapPort);
    if (ldap_bind($ds, $_SESSION['username'], $_SESSION['password'])) {
      $_SESSION['lastactivity'] = time();
      return $ds;
    } else {
      unset($_SESSION['lastactivity'], $_SESSION['username'], $_SESSION['password']);
      header("Location: endSession.php");
      exit;
    }

  } else if (isset($_POST['username'], $_POST['password'])) {

    // Handle login requests
    $ds = ldap_connect($ldapServer, $ldapPort);
    if (ldap_bind($ds, $_POST['username'], $_POST['password'])) {
      // Successful auth
      $_SESSION['lastactivity'] = time();
      $_SESSION['username'] = $_POST['username'];
      $_SESSION['password'] = $_POST['password'];
      return $ds;
    } else {
      // Auth failed
      header("Location: endSession.php");
      exit;
    }

  } else {

    // Session has expired or a logout was requested
    unset($_SESSION['lastactivity'], $_SESSION['username'], $_SESSION['password']);
    header("Location: endSession.php");
    exit;

  }

}

Just call the above function at the top of every protected page. This will handle all the authentication processes. It will return the LDAP connection resource if the user is authenticated, and redirect them to endSession.php if they are not.

Just place this line at the top of each page:

$ds = check_auth_ldap();

...and the function will do all the legwork for you.

So the POST variables come from the LDAP form, right?

Sorry, forgot to explain that in the question: The POST variables come from the login form - so your login form looks like <form action="yourscript.php" method="post"><input type="text" name="username" /><input type="password" name="password" /></form>. You can logout by passing a GET parameter of logout - it doesn't matter what the value is, just that the key is set

php - Sessions and LDAP - Stack Overflow

php session ldap
Rectangle 27 3

It doesn't serve any purpose. ldap_connect will return false if it fails thus die, so you can delete one of the 2.

You should be careful with testing ldap_connect in PHP5.3 I can successfully connect to any server ( existing or not ) where ldap_connect always returns true. The link type is always ldap_connection but may not actually work / be successful. I'd suggest verifying the connection is valid with @ldap_bind then check for errors.

ldap - PHP: die or check results? - Stack Overflow

php ldap exit die
Rectangle 27 1

I will try that and see if it helps. It certainly seems likely.

I added in ldap_close() prior to all "return" statements in the above however I am still experiencing the issue.

PHP Connection to LDAP fails randomly until Apache restart - Stack Ove...

php apache ldap openldap
Rectangle 27 1

There is often a need for a bind based on the uid. I've modified the function a little to achieve this. cn for bind comes from a search operation based on uid for username. Hope this could help someone.

function check_auth_ldap () {

  if (!($_POST['username'] && $_POST['password'])) {

    header("Location: login.php?failure=6");

  }

  $sessionTimeoutSecs = 10;
  $ldapServer = localhost;
  $ldapBaseDN = ou=users,ou=subtree,dc=domain,dc=tld;
  $ldapPort = 389;
  $ldapFilter = "(&(objectClass=*)(uid=".$_POST['username']."))";
  $ldapAttributes = array("cn");

  if (!isset($_SESSION)) session_start();

  if (!empty($_SESSION['lastactivity']) && $_SESSION['lastactivity'] > time() - $sessionTimeoutSecs && !isset($_GET['logout'])) {

    // Session is already authenticated
    $ds = ldap_connect($ldapServer, $ldapPort);
    $sr = ldap_search($ds,$ldapBaseDN,$ldapFilter,$ldapAttributes);
    $result = ldap_get_entries($ds, $sr);

    if ($result) {
        $binddn = $result[0]['dn'];
    } else {
        header("Location: login.php?failure=1");
    }

    ldap_close ($ds);

    $ds = ldap_connect($ldapServer, $ldapPort);
    ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);

    if (ldap_bind($ds, $binddn, $_SESSION['password'])) {
      $_SESSION['lastactivity'] = time();
      return $ds;
    } else {
      unset($_SESSION['lastactivity'], $_SESSION['username'], $_SESSION['password']);
      header("Location: login.php?failure=2");
      exit;
    }

  } else if (isset($_POST['username'], $_POST['password'])) {

    // Handle login requests
    $ds = ldap_connect($ldapServer, $ldapPort);
    $sr = ldap_search($ds,$ldapBaseDN,$ldapFilter,$ldapAttributes);
    $result = ldap_get_entries($ds, $sr);

    if ($result) {
        $binddn = $result[0]['dn'];
    } else {
        header("Location: login.php?failure=3");
    }
    ldap_close ($ds);

    $ds = ldap_connect($ldapServer, $ldapPort);
    ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);

    if (ldap_bind($ds, $binddn, $_POST['password'])) {
      // Successful auth
      $_SESSION['lastactivity'] = time();
      $_SESSION['username'] = $_POST['username'];
      $_SESSION['password'] = $_POST['password'];
      return $ds;
    } else {
      // Auth failed
      header("Location: login.php?failure=4");
      exit;
    }

  } else {

    // Session has expired or a logout was requested
    unset($_SESSION['lastactivity'], $_SESSION['username'], $_SESSION['password']);
    header("Location: login.php?failure=5");
    exit;

  }

}

php - Sessions and LDAP - Stack Overflow

php session ldap
Rectangle 27 1

Ideally you should have warnings disabled on your production environment so you shouldn't see PHP warnings, however to discern that the warning was raised by your LDAP you may have to get creative. This code shows two places where errors are raised, it sets the error level to hide the Warnings and then has a mechanism to test if the warning was raided by the ldap functions.

user_error('Raise an error');
// Suppress Warnings
$previousErrorReportingLevel = error_reporting();
error_reporting( error_reporting() & ~E_WARNING );
$previousError = error_get_last();
if(isset($_POST['username'],$_POST['password']) === true and $ldap_connection = ldap_connect("DOMAINHERE") and $ldap_bind = ldap_bind($ldap_connection,$_POST['username'],$_POST['password']))
{
  var_dump($ldap_connection);
  var_dump($ldap_bind);
}
else
{
  $lastError = error_get_last();
  // You can either look for a specific message
  if( $lastError['message'] === 'ldap_bind(): Unable to bind to server: Invalid credentials' )
  {
    echo("Login Credential Error");
  }
  // or look that the last error is different from the previously recorded error
  elseif( $lastError !== $previousError )
  {
    echo("LDAP Connection error");
  }
}
// Restore Error Reporting Level
error_reporting( $previousErrorReportingLevel );
user_error('Raise an error');

php - Codigniter Error Handling with LDAP - Stack Overflow

php codeigniter error-handling ldap
Rectangle 27 4

Now I can take a certificate from UI and connect to LDAP via SSL :)

import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.util.ssl.SSLUtil;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.io.ByteArrayInputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

String base64EncodedCertificateString = "...";
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(base64EncodedCertificateString.getBytes());
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
int i = 0;
while (byteArrayInputStream.available() > 0) {
    Certificate cert = cf.generateCertificate(byteArrayInputStream);
    trustStore.setCertificateEntry("cert " + i++, cert);
}

TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
TrustManager[] trustManagers = tmf.getTrustManagers();
SSLUtil sslUtil = new SSLUtil(trustManagers);
SSLSocketFactory socketFactory = sslUtil.createSSLSocketFactory();
LDAPConnection connection = new LDAPConnection(socketFactory);
connection.connect("place.myserver.com", 636);

How to use UnboundID SDK to connect to an LDAP server with the SSL ser...

ssl ldap ssl-certificate ldapconnection unboundid-ldap-sdk
Rectangle 27 1

the first idea would be: check network configuration. You may start with "Windows 7 machine". Please, check if firewall isn't blocking 636. Another firewall may be between "Windows 7 machine" and server, which allows 389 and blocks 636. You can try to user tools as "telnet" or "tracert" to check it.

The second thing to check would be certificates at server side. If you want to enable SSL certificates, you have to use certificates and certificate authorities. My question would be: what's your current configuration?

In the official documentation from Microsoft is 0x51 treated as: LDAP_SERVER_DOWN 0x51 Cannot contact the LDAP server. So this is not very helpful, but "standard situation" with LDAP servers :-).

Connect to LDAP over SSL - Stack Overflow

ldap
Rectangle 27 199

The website says that python-ldap is based on OpenLDAP, so you need to have the development files (headers) in order to compile the Python module. If you're on Ubuntu, the package is called libldap2-dev.

sudo apt-get install libsasl2-dev python-dev libldap2-dev libssl-dev
sudo yum install python-devel openldap-devel

Thanks for that. It's got further it's now failing with sasl.h no such file or directory

@VacuumTube: Missing headers are almost always a sign for missing -dev packages (sometimes also named -devel). Just do apt-cache search sasl | grep dev and you'll probably find the right package - I would guess it's libsasl2-dev.

You don't have to compile from source on Windows. Just use one of the installers from pypi.python.org/pypi/python-ldap.

module - I can't install python-ldap - Stack Overflow

python module ldap
Rectangle 27 2

If using env.put(Context.SECURITY_AUTHENTICATION, "none"); did not work, then your AD environment may not support anonymous authentication, understandably. Anonymous authentication is disabled by default.

When you use new DirectoryEntry(...); in C#, it may seem like you are not using any credentials, but it really uses the credentials of the currently logged on user. So it's borrowing your own credentials to make the call to AD.

Java does not do that. In fact, from the brief Googling I've done just now, it seems like it's quite difficult to make it do that, if that's what you want to do.

The comment there gives a couple products to look into.

But if you don't want to use any third-party products that may complicate things, you can just provide a username and password.

If you want to test anonymous authentication in C#, you can use something like this:

new DirectoryEntry(ldapPath, null, null, AuthenticationTypes.Anonymous)

c# - Connect to the LDAP Active Directory in Java without username and...

java c# authentication active-directory ldap
Rectangle 27 68

sudo yum install python-devel
sudo yum install openldap-devel

and yum will also install cyrus-sasl-devel as a dependency. Then you can run:

pip-2.7 install python-ldap

This helped me. Thanks a ton !!

module - I can't install python-ldap - Stack Overflow

python module ldap
Rectangle 27 3

If there is a specific certificate or set of certificates that you want trusted, then you could just create your own custom javax.net.ssl.X509TrustManager implementations that examines the presented certificate chain and determines whether it represents one of the expected certificates. You could hard-code information about those certificates into your code (or better yet, put it in a config file so you could change it without altering any code) and do something like comparing certificate fingerprints to get an appropriate degree of assurance that it is actually the legitimate certificate.

If you don't know what the individual certificates will be but know that they all have a common issuer, and you trust that issuer to only issue good certificates, then you could include trust information for that issuer.

If you want to allow for a range of unknown certificates, potentially from untrusted issuers (and you don't know what those issuers might be in advance), and you don't want to prompt the user about whether to trust them (which you could potentially cache so you only have to ask once), then I'm not sure what you could do. Unless you can find some way to differentiate certificates from good servers versus those from bad servers, then your application will run the risk of either trusting bad certificates or not trusting good ones.

How to use UnboundID SDK to connect to an LDAP server with the SSL ser...

ssl ldap ssl-certificate ldapconnection unboundid-ldap-sdk
Rectangle 27 463

Active Directory is a database based system that provides authentication, directory, policy, and other services in a Windows environment

LDAP (Lightweight Directory Access Protocol) is an application protocol for querying and modifying items in directory service providers like Active Directory, which supports a form of LDAP.

Short answer: AD is a directory services database, and LDAP is one of the protocols you can use to talk to it.

What are the differences between LDAP and Active Directory? - Stack Ov...

active-directory ldap
Rectangle 27 43

I had the same problem, and it solved it for me.

The root cause of this bug is that you have referrals in the initial response and the windows LDAP code does not send the credentials to the referral server. If you used kerberos credentials it should work.

I had different symptoms but this same option fixed my problem. Summarized it in a blog post: chaverma.com/blog/index.php/2013/06/

Not sure if related, but I had the same problem and it seems 1729's solution did something - But sometimes the LDAP server just answers INVALID CREDENTIALS immediately. After a while it calms down and works again.

authentication - Authenticating against active directory using python ...

python authentication active-directory ldap
Rectangle 27 138

To install python-ldap successfully with pip, following development libraries are needed (package names taken from ubuntu environment):

sudo apt-get install -y python-dev libldap2-dev libsasl2-dev libssl-dev
sudo pip install python-ldap

module - I can't install python-ldap - Stack Overflow

python module ldap
Rectangle 27 30

$ sudo apt-get install python-dev libldap2-dev libsasl2-dev libssl-dev
 $ sudo pip install python-ldap

module - I can't install python-ldap - Stack Overflow

python module ldap
Rectangle 27 14

<ldap-authentication-provider>
<authentication-provider>
<authentication-manager>
<authentication-manager>
    <ldap-authentication-provider user-search-filter="(samaccountname={0})" user-search-base="dc=company,dc=com"/> 
</authentication-manager>

thanks! Now, I have some issues with remeber-me: Error creating bean with name 'o.s.s.w.a.rememberme.TokenBasedRememberMeServices#0': Initialization of bean failed; nested exception is org.springframework.context.ApplicationContextException: No UserDetailsService registered.org.springframework.context.ApplicationContextException: No UserDetailsService registered. at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521) if I take out remember-me it runs fine, but no ldap communication happens...

Spring security ldap: no declaration can be found for element 'ldap-au...

ldap spring-security