diff --git a/authentication/ldap/controller.php b/authentication/ldap/controller.php
new file mode 100644
index 0000000000000000000000000000000000000000..d01b105b5e88ce3f6e007b87755f01a38b2df498
--- /dev/null
+++ b/authentication/ldap/controller.php
@@ -0,0 +1,147 @@
+<?php
+namespace Concrete\Package\LdapLogin\Authentication\Ldap;
+
+use Concrete\Core\Authentication\AuthenticationTypeController;
+use User;
+use UserInfo;
+use View;
+use Config;
+use Loader;
+use Exception;
+
+
+class Controller extends AuthenticationTypeController {
+
+  const YUBIKEY_VERIFY_URL = "http://api.yubico.com/wsapi/2.0/verify";
+
+  public function getHandle() {
+    return 'ldap';
+  }
+
+  public function view() {
+
+  }
+
+  public function edit()
+  {
+    $this->set('form', \Loader::helper('form'));
+    $this->set('ldapServerURI', \Config::get('auth.ldap.ldapServerURI', ''));
+    $this->set('ldapBaseDN', \Config::get('auth.ldap.ldapBaseDN', ''));
+    $this->set('ldapBindDN', \Config::get('auth.ldap.ldapBindDN', ''));
+    $this->set('ldapBindPassword', \Config::get('auth.ldap.ldapBindPassword', ''));
+    $this->set('ldapSearchFilter', \Config::get('auth.ldap.ldapSearchFilter', ''));
+    $this->set('yubikeyEnabled',\Config::get('auth.ldap.yubikeyEnabled', false));
+    $this->set('yubikeyClientID',\Config::get('auth.ldap.yubikeyClientID', ''));
+    $this->set('yubikeySecretKey',\Config::get('auth.ldap.yubikeySecretKey', ''));
+    $this->set('yubikeyServerURI',\Config::get('auth.ldap.yubikeyServerURI', ''));
+    $this->set('yubikeyAllowEmptyKey',\Config::get('auth.ldap.yubikeyAllowEmptyKey', false));
+
+  }
+
+  public function saveAuthenticationType($args)
+  {
+    \Config::save('auth.ldap.ldapServerURI',$args['ldapServerURI']);
+    \Config::save('auth.ldap.ldapBaseDN',$args['ldapBaseDN']);
+    \Config::save('auth.ldap.ldapBindDN',$args['ldapBindDN']);
+    \Config::save('auth.ldap.ldapBindPassword',$args['ldapBindPassword']);
+    \Config::save('auth.ldap.ldapSearchFilter',$args['ldapSearchFilter']);
+    \Config::save('auth.ldap.yubikeyEnabled',$args['yubikeyEnabled']);
+    \Config::save('auth.ldap.yubikeyClientID',$args['yubikeyClientID']);
+    \Config::save('auth.ldap.yubikeySecretKey',$args['yubikeySecretKey']);
+    \Config::save('auth.ldap.yubikeyServerURI',$args['yubikeyServerURI']);
+    \Config::save('auth.ldap.yubikeyAllowEmptyKey',$args['yubikeyAllowEmptyKey']);
+  }
+
+  public function getAuthenticationTypeIconHTML() {
+    return "";
+  }
+
+  private function __connect() {
+    if (!is_object($this->ldap_conn)) {
+      $this->ldap_conn = ldap_connect(\Config::get('auth.ldap.ldapServerURI',''))
+        or die(t('Connection to LDAP Server failed.'));
+      ldap_set_option($this->ldap_conn, LDAP_OPT_PROTOCOL_VERSION, 3);
+      $bindDN = \Config::get('auth.ldap.ldapBindDN', '');
+      $bindPW = \Config::get('auth.ldap.ldapBindPassword', '');
+      if ($bindDN) {
+        $this->ldap_bind = ldap_bind($this->ldap_conn,$bindDN,$bindPW);
+      } else {
+        $this->ldap_bind = ldap_bind($this->ldap_conn);
+      }
+      if (!$this->ldap_bind) {
+        throw new Exception(t("Binding with LDAP Server failed."));
+      }
+    }
+  }
+
+
+  public function authenticate() {
+    $post = $this->post();
+    if (!isset($post['uName']) || !isset($post['uPassword'])) {
+      throw new Exception(t('Please provide both username and password.'));
+    }
+    $uName = $post['uName'];
+    $uPassword = $post['uPassword'];
+    $this->__connect();
+    $search_result = ldap_search($this->ldap_conn,\Config::get('auth.ldap.ldapBaseDN', ''),
+      "(uid=$uName)");
+    if (ldap_count_entries($this->ldap_conn,$search_result)!=1) {
+      throw new \Exception(t('Invalid username or password.'));
+    }
+    $entry = ldap_first_entry($this->ldap_conn,$search_result);
+
+    $user_bind = ldap_bind($this->ldap_conn,ldap_get_dn($this->ldap_conn,$entry),$uPassword);
+    if (!$user_bind) {
+      throw new \Exception(t('Invalid username or password.'));
+    }
+    $userInfo = UserInfo::getByUserName($uName);
+    if (!is_object($userInfo)) {
+      throw new \Exception(t('Invalid username or password.'));
+    }
+
+
+    $user = User::loginByUserID($userInfo->uID);
+    if (!is_object($user) || !($user instanceof User) || $user->isError()) {
+      switch ($user->getError()) {
+        case USER_SESSION_EXPIRED:
+          throw new \Exception(t('Your session has expired. Please sign in again.'));
+          break;
+        case USER_NON_VALIDATED:
+          throw new \Exception(t(
+              'This account has not yet been validated. Please check the email associated with this account and follow the link it contains.'));
+          break;
+        case USER_INVALID:
+          if (Config::get('concrete.user.registration.email_registration')) {
+            throw new \Exception(t('Invalid email address or password.'));
+          } else {
+            throw new \Exception(t('Invalid username or password.'));
+          }
+          break;
+        case USER_INACTIVE:
+          throw new \Exception(t('This user is inactive. Please contact us regarding this account.'));
+          break;
+      }
+    }
+    if ($post['uMaintainLogin']) {
+      $user->setAuthTypeCookie('concrete');
+    }
+    return $user;
+  }
+
+  public function deauthenticate(User $u) {
+
+  }
+
+  public function isAuthenticated(User $u) {
+
+  }
+
+  public function buildHash(User $u) {
+    return "";
+  }
+
+  public function verifyHash(User $u, $hash) {
+    return false;
+  }
+}
+?>
diff --git a/authentication/ldap/form.php b/authentication/ldap/form.php
new file mode 100644
index 0000000000000000000000000000000000000000..73470afa3700851f2957f0f782c285324c3d0b79
--- /dev/null
+++ b/authentication/ldap/form.php
@@ -0,0 +1,44 @@
+<?php
+defined('C5_EXECUTE') or die('Access denied.');
+$form = Loader::helper('form');
+?>
+
+<form method='post'
+      action='<?= View::url('/login', 'authenticate', $this->getAuthenticationTypeHandle()) ?>'>
+    <div class="form-group concrete-login">
+        <span><?= t('Sign in with a ldap account.') ?> </span>
+        <hr>
+    </div>
+    <div class="form-group">
+        <input name="uName" class="form-control col-sm-12"
+               placeholder="<?= Config::get('concrete.user.registration.email_registration') ? t('Email Address') : t('Username')?>" />
+    </div>
+
+    <div class="form-group">
+        <label>&nbsp;</label>
+        <input name="uPassword" class="form-control" type="password"
+               placeholder="<?=t('Password')?>" />
+    </div>
+
+    <?php
+    if (isset($locales) && is_array($locales) && count($locales) > 0) {
+    ?>
+        <div class="form-group">
+            <label for="USER_LOCALE" class="control-label"><?= t('Language') ?></label>
+            <?= $form->select('USER_LOCALE', $locales) ?>
+        </div>
+    <?php
+    }
+    ?>
+
+    <div class="form-group">
+        <button class="btn btn-primary"><?= t('Log in') ?></button>
+        <a href="<?= View::url('/login', 'concrete', 'forgot_password') ?>" class="btn pull-right"><?= t('Forgot Password') ?></a>
+    </div>
+
+    <script type="text/javascript">
+        document.querySelector('input[name=uName]').focus();
+    </script>
+
+    <?php Loader::helper('validation/token')->output('login_' . $this->getAuthenticationTypeHandle()); ?>
+</form>
diff --git a/authentication/ldap/type_form.php b/authentication/ldap/type_form.php
new file mode 100644
index 0000000000000000000000000000000000000000..75ac8fe4c244afb993d64dbe0f72dc667ff92498
--- /dev/null
+++ b/authentication/ldap/type_form.php
@@ -0,0 +1,61 @@
+<?php defined('C5_EXECUTE') or die('Access denied.'); ?>
+<fieldset>
+  <legend><?= t("LDAP Server Configuration")?></legend>
+  <div class='form-group'>
+    <?= $form->label('ldapServerURI', t('LDAP Server URI')) ?>
+    <?= $form->text('ldapServerURI', $ldapServerURI) ?>
+  </div>
+  <div class='form-group'>
+    <?= $form->label('ldapBaseDN', t('LDAP Base DN')) ?>
+    <?= $form->text('ldapBaseDN', $ldapBaseDN) ?>
+  </div>
+  <div class='form-group'>
+    <?= $form->label('ldapBindDN', t('LDAP Bind DN')) ?>
+    <?= $form->text('ldapBindDN', $ldapBindDN) ?>
+  </div>
+  <div class='form-group'>
+    <?= $form->label('ldapBindPassword', t('LDAP Bind Password')) ?>
+    <?= $form->text('ldapBindPassword', $ldapBindPassword) ?>
+  </div>
+  <div class='form-group'>
+    <?= $form->label('ldapSearchFilter', t('LDAP Search Filter')) ?>
+    <?= $form->text('ldapSearchFilter', $ldapSearchFilter) ?>
+  </div>
+</fieldset>
+<fieldset>
+  <legend>Yubikey Configuration</legend>
+  <div class='form-group'>
+    <?= $form->label('yubikeyEnabled', t('Enable Yubikey')) ?>
+    <?= $form->checkbox('yubikeyEnabled', 1, $yubikeyEnabled) ?>
+  </div>
+  <div id="yubikey-options" style="display: <?= $yubikeyEnabled ? 'block' : 'none' ?>;">
+    <div class='form-group'>
+      <?= $form->label('yubikeyClientID', t('Yubikey Client ID')) ?>
+      <?= $form->text('yubikeyClientID', $yubikeyClientID) ?>
+    </div>
+    <div class='form-group'>
+      <?= $form->label('yubikeySecretKey', t('Yubikey Secret Key')) ?>
+      <?= $form->text('yubikeySecretKey', $yubikeySecretKey) ?>
+    </div>
+    <div class='form-group'>
+      <?= $form->label('yubikeyServerURI', t('Yubikey Verify URI')) ?>
+      <?= $form->text('yubikeyServerURI', $yubikeyServerURI) ?>
+    </div>
+    <div class='form-group'>
+      <?= $form->label('yubikeyLDAPAtttribute', t('Yubikey LDAP Attribute')) ?>
+      <?= $form->text('yubikeyLDAPAtttribute', $yubikeyLDAPAtttribute) ?>
+    </div>
+    <div class='form-group'>
+      <?= $form->label('yubikeyAllowEmptyKey', t('Allow login with no Yubikey specified')) ?>
+      <?= $form->checkbox('yubikeyAllowEmptyKey', 1, $yubikeyAllowEmptyKey) ?>
+    </div>
+  </div>
+  <script>
+    $('#yubikeyEnabled').click(function(){
+      if ( $(this).is(':checked') )
+        $('#yubikey-options').show()
+      else
+        $('#yubikey-options').hide();
+    });
+    </script>
+</fieldset>
diff --git a/controller.php b/controller.php
new file mode 100644
index 0000000000000000000000000000000000000000..dfd9b3bc17553d9bec8b624515ea09738b0ef767
--- /dev/null
+++ b/controller.php
@@ -0,0 +1,36 @@
+<?php
+namespace Concrete\Package\LdapLogin;
+
+use Concrete\Core\Package\Package;
+use Concrete\Core\Authentication\AuthenticationType;
+
+
+defined('C5_EXECUTE') or die(_('Access denied.'));
+
+class Controller extends Package {
+
+  protected $pkgHandle = 'ldap_login';
+  protected $appVersionRequired = '5.7.2';
+  protected $pkgVersion = '1.0';
+
+  public function getPackageDescription() {
+    return t("Add LDAP login functionality.");
+  }
+
+  public function getPackageName() {
+    return "LDAP Login";
+  }
+
+  public function install() {
+    $pkg = parent::install();
+    $at = AuthenticationType::add('ldap','LDAP',0,$pkg);
+  }
+
+  public function uninstall() {
+    $at = AuthenticationType::getByHandle('ldap');
+    $at->delete();
+    parent::uninstall();
+  }
+
+}
+?>