Self Service Password

Recently I set up an LDAP for the different tools/apps I’ve. You can read more about that here.
And while I am still in the process of onboarding my applications a new issue came to light.
Changing/updating your password is not possible in all tools.
I started looking for a simple, well maintained self service solution.
While searching through Github I found a lot of projects but most were barely maintained or didn’t look all that secure.

One that stood out was LDAP Tool Box Self Service Password.

Conveniently they also provide the docker image. For this one no template was available in my unraids community store so I had to create is myself. It’s also possible to just run a docker run command in the cli but then you miss the convenience of using unraids autoupdate, template links to projects git, site, dockerhub etc…

I’ll provide the xml template. You can also create it via the Web-UI.
I used to host my own templates in a git repo but since unraid no longer supports pulling from it and went community store only the 2 ways would be to create a forum thread and promise some sort support on it or paste/create an xml file under /boot/config/plugins/dockerMan/templates/templates/self-service.xml.

<?xml version="1.0"?>
<Container version="2">
  <Name>Self-Service-Password</Name>
  <Repository>ltbproject/self-service-password:latest</Repository>
  <Registry>https://hub.docker.com/r/ltbproject/self-service-password</Registry>
  <Network>bridge</Network>

  <Shell>sh</Shell>
  <Privileged>false</Privileged>
  <Support/>
  <Project/>
  <Overview>https://github.com/ltb-project/self-service-password&#xD;
https://self-service-password.readthedocs.io/en/latest/
https://hub.docker.com/r/ltbproject/self-service-password</Overview>
  <Category/>
  <WebUI>http://[IP]:[PORT:17171]/</WebUI>
  <TemplateURL/>
  <Icon>https://ltb-project.org/documentation/_static/ltb-logo.png</Icon>
  <ExtraParams/>
  <PostArgs/>
  <CPUset/>
  <DonateText/>
  <DonateLink/>
  <Requires/>
  <Config Name="config" Target="/var/www/conf/config.inc.local.php" Default="/mnt/user/appdata/self_service_password/ssp.conf.php" Mode="rw" Description="" Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/self_service_password/ssp.conf.php</Config>
  <Config Name="webui" Target="80" Default="" Mode="tcp" Description="" Type="Port" Display="always" Required="true" Mask="false">17171</Config>
  <Config Name="LLDAP server" Target="ldap_url" Default="" Mode="" Description="" Type="Variable" Display="always" Required="true" Mask="false">ldap://10.xxx.xxx.xxx:389</Config>
  <Config Name="css" Target="/var/www/html/css/custom.css" Default="" Mode="rw" Description="" Type="Path" Display="always" Required="false" Mask="false">/mnt/user/appdata/self_service_password/custom.css</Config>
</Container>

In the template I exposed port 17171. This is the port for the Web-UI.
I set an environment variable “ldap_url” with my LLDAP server address and port.
I also pulled out 2 files from the container into my config folder:

  • config.inc.local.php
  • custom.css

The first file is used to configure the tool the second one is necessary if you want to override some of the default styling.

Configuration – config.inc.local.php

I will provide the complete config and breakdown different aspects of it. Some options are also explained by comment lines in the php itself. If you make changes to this file they will immediately be reflected in the app.

<?php // ziggyds SSP configuration
$keyphrase = "xxxxxxxxxxxxxxxx";
$debug = false;
$smarty_debug = false; // web interface
$lang = "nl";
$allowed_lang = array("nl","en");
$show_menu = true;
$show_help = false;
$use_captcha = true;
$default_action = "change"; # change sendtoken sendsms
$obscure_failure_messages = array("mailnomatch");
$use_restapi = false;
// Cause tunnel
$reset_url = $_SERVER['HTTP_X_FORWARDED_PROTO'] . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'];

// LLDAP connection
$ldap_url = "ldap://10.xxx.xxx.xxx:389";
$ldap_binddn = "uid=admin,ou=people,dc=ziggyds,dc=be";
$ldap_bindpw = "xxxxxxxxxxxxx";
# Who changes the password? Also applicable for question/answer save
# user: the user itself
# manager: the above binddn
$who_change_password = "user";
$ldap_use_exop_passwd = true;
// LDAP search
$ldap_base = "dc=ziggyds,dc=be";
$ldap_filter = "(&(objectClass=person)(uid={login}))";

// Recover methods
$use_sms = false;
$use_questions = false;
$use_tokens = true; // mail
$crypt_tokens = true; // protect the session identifier
$token_lifetime = "1800"; // 30min

## Mail
# LDAP mail attribute
$mail_attributes = array( "mail" );
# Get mail address directly from LDAP (only first mail entry) and hide mail input field
# default = false
$mail_address_use_ldap = true;
$mail_from = "[email protected]";
$mail_from_name = "Ziggyds Password Service";
$mail_signature = "";
$notify_on_change = true; # Notify users anytime their password is changed

// Branding
$logo = "";
$background_image = "";
$custom_css = "css/custom.css";
$display_footer = false;

// Headers
$header_name_preset_login = "Auth-User";

// Messages
// $messages['passwordchangedextramessage'] = "Congratulations!";
// $messages['changehelpextramessage'] = "Contact us if you are lost...";

// Password policy
$pwd_no_reuse = true;
$pwd_show_policy = "always";
$pwd_show_policy_pos = "below";
$pwd_min_length = 8;
$pwd_max_length = 20;
$pwd_min_lower = 3;
$pwd_min_upper = 1;
$pwd_min_digit = 1;
$pwd_min_special = 1;
$show_extended_error = false;

// https://haveibeenpwned.com/
$use_pwnedpasswords = true;

# PHPMailer configuration (see https://github.com/PHPMailer/PHPMailer)
$mail_sendmailpath = '/usr/sbin/sendmail';
$mail_protocol = 'smtp';
$mail_smtp_debug = 0;
$mail_debug_format = 'error_log';
$mail_smtp_host = 'smtp.xxxxxxxx.xxx';
$mail_smtp_auth = true;
$mail_smtp_user = '[email protected]';
$mail_smtp_pass = 'xxxxxxxxxxxxx';
$mail_smtp_port = 587;
$mail_smtp_timeout = 30;
$mail_smtp_keepalive = false;
$mail_smtp_secure = 'tls';
$mail_smtp_autotls = true;
$mail_smtp_options = array();
$mail_contenttype = 'text/plain';
$mail_wordwrap = 0;
$mail_charset = 'utf-8';
$mail_priority = 3;
?>

In the first bit I disable the debugging output, set the default language and languages that are allowed, turn on captcha to prevent bot input and the default password change/reset option to land on.
Setting obscure_failure_messages is also a must imo as it will prevent people from probing the ldap instance. If not in the ldap existing users are tried it will give a generic failure message instead explicitly stating the user exist or not. And since I will not (yet) use the rest api, I disabled that as well.

$keyphrase = "fT$^tPbSJSEfC*HcV$T7";
$debug = false;
$smarty_debug = false; // web interface
$lang = "nl";
$allowed_lang = array("nl","en");
$show_menu = true;
$show_help = false;
$use_captcha = true;
$default_action = "change"; # change sendtoken sendsms
$obscure_failure_messages = array("mailnomatch");
$use_restapi = false;


If you use tunnels like me or a reverse proxy you’d want to set the reset_url variable. If not set it will it will default back to using hostname and port which external users won’t be able to access.

// Cause tunnel
$reset_url = $_SERVER['HTTP_X_FORWARDED_PROTO'] . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'];


Set up the LDAP connection, server to use, service account to use and its password.

// LLDAP connection
$ldap_url = "ldap://192.168.1.200:3890";
$ldap_binddn = "uid=admin,ou=people,dc=ziggyds,dc=be";
$ldap_bindpw = "9iEg4@vya$&&qfFgBft6";


If a user changes his password it should be logged as such no?
For this tool to work with LLDAP it is important to turn on ldap_use_exop_passwd.
The reason is that LLDAP only supports read-only queries + this extended password reset operation.

# Who changes the password? Also applicable for question/answer save
# user: the user itself
# manager: the above binddn
$who_change_password = "user";
$ldap_use_exop_passwd = true;


The tool supports different ways to let users recover his/her password in case s/he forgot. I disabled all of them except for mail.

// Recover methods
$use_sms = false;
$use_questions = false;
$use_tokens = true; // mail
$crypt_tokens = true; // protect the session identifier
$token_lifetime = "1800"; // 30min


To be able to send an emails out to users requesting a password reset the mail settings have to be configured.
The address is pulled from LLDAP based on mail attribute and the textbox to input a mail address is removed.

## Mail
# LDAP mail attribute
$mail_attributes = array( "mail" );
# Get mail address directly from LDAP (only first mail entry) and hide mail input field
# default = false
$mail_address_use_ldap = true;
$mail_from = "[email protected]";
$mail_from_name = "Ziggyds Password Service";
$mail_signature = "";
$notify_on_change = true; # Notify users anytime their password is changed


If you want to sent out mails you’ve to set the settings of the mail provider you are using.

# PHPMailer configuration (see https://github.com/PHPMailer/PHPMailer)
$mail_sendmailpath = '/usr/sbin/sendmail';
$mail_protocol = 'smtp';
$mail_smtp_debug = 0;
$mail_debug_format = 'error_log';
$mail_smtp_host = 'smtp.xxxxxxx.xxx';
$mail_smtp_auth = true;
$mail_smtp_user = '[email protected]';
$mail_smtp_pass = 'xxxxxxxxxxxxxxxxxx';
$mail_smtp_port = 587;
$mail_smtp_timeout = 30;
$mail_smtp_keepalive = false;
$mail_smtp_secure = 'tls';
$mail_smtp_autotls = true;
$mail_smtp_options = array();
$mail_contenttype = 'text/plain';
$mail_wordwrap = 0;
$mail_charset = 'utf-8';
$mail_priority = 3;


You can remove/change the logo and default background image.
I also disabled the footer and set the path to my own css file to load.

// Branding
$logo = "";
$background_image = "";
$custom_css = "css/custom.css";
$display_footer = false;


Of course we define the password policy a new password should be compliant with.
I disabled the extend error option to keep things more secure.
On top of that I enabled the option the check if a password has been leaked before.

// Password policy
$pwd_no_reuse = true;
$pwd_show_policy = "always";
$pwd_show_policy_pos = "below";
$pwd_min_length = 8;
$pwd_max_length = 20;
$pwd_min_lower = 3;
$pwd_min_upper = 1;
$pwd_min_digit = 1;
$pwd_min_special = 1;
$show_extended_error = false;

// https://haveibeenpwned.com/
$use_pwnedpasswords = true;


The last thing I’ve in there is a header option. Am planning to use this to automatically fill in the login if redirected from another tool.

// Headers
$header_name_preset_login = "Auth-User";

Styling – custom.css

a.navbar-brand {
  visibility:hidden;
}
a.navbar-brand:before {
  content: 'Ziggyds password service';
  visibility:visible;
}

.alert {
  box-shadow: none;
  text-shadow: none;
  -webkit-box-shadow: none;
}

.alert-info {
  --background-hue: 264;
  --background-saturation: 14.71%;
  --background-lightness: 13.33%;
  background-color: hsl(var(--background-hue), var(--background-saturation), var(--background-lightness));
  background-image: none;
  border-color: transparent;
}

.form-horizontal {
  --background-hue: 264;
  --background-saturation: 14.71%;
  --background-lightness: 13.33%;
  background-color: hsl(var(--background-hue), var(--background-saturation), var(--background-lightness));
}

.panel-body {
  --background-hue: 264;
  --background-saturation: 14.71%;
  --background-lightness: 13.33%;
  background-color: hsl(var(--background-hue), var(--background-saturation), var(--background-lightness));
}

.navbar-wrapper {
  --background-hue: 264;
  --background-saturation: 14.71%;
  --background-lightness: 13.33%;
  background-color: hsl(var(--background-hue), var(--background-saturation), var(--background-lightness));
  box-shadow: none;
}

.navbar-header {
  --background-hue: 264;
  --background-saturation: 14.71%;
  --background-lightness: 13.33%;
  background-color: hsl(var(--background-hue), var(--background-saturation), var(--background-lightness));
}

.container-fluid {
  --background-hue: 264;
  --background-saturation: 14.71%;
  --background-lightness: 13.33%;
  background-color: hsl(var(--background-hue), var(--background-saturation), var(--background-lightness));
}

.navbar-default {
  background-color: inherit;
  border-color: inherit;
}

html {
  --background-hue: 264;
  --background-saturation: 14.71%;
  --background-lightness: 13.33%;
  background-color: hsl(var(--background-hue), var(--background-saturation), var(--background-lightness));

}

body {
  --background-hue: 264;
  --background-saturation: 14.71%;
  --background-lightness: 13.33%;
  background-color: hsl(var(--background-hue), var(--background-saturation), var(--background-lightness));

}
Leave A Comment

Your email address will not be published. Required fields are marked *