Authenticating Mediawiki users with FreeIPA LDAP

Following my success in configuring Jenkins to authenticate against FreeIPA LDAP I thought I would also integrate LDAP into Mediawiki.

The first step is to install the LdapAuthentication extension for Mediawiki. Installation is pretty simple, extract the LdapAuthentication archive to the extensions folder in your mediawiki installation. e.g. /var/www/mediawiki/extensions

On the FreeIPA server we need to create an unprivileged user to bind to LDAP:

-bash-4.2$ cat mediawiki.ldif 
dn: uid=mediawiki,cn=sysaccounts,cn=etc,dc=watchmysys,dc=com
changetype: add
objectclass: account
objectclass: simplesecurityobject
uid: mediawiki
userPassword: EpQIJjhRj
passwordExpirationTime: 20380119031407Z
nsIdleTimeout: 0

To create the mediawiki user you need to apply the LDIF to LDAP:

ldapmodify -h ipa.watchmysys.com -p 389 -x -D "cn=Directory Manager" -W -f mediawiki.ldif

Create a new role inside FreeIPA for Mediawiki users:
IPA Mediawiki Role

Here is what the corresponding LDAP object is:

# mediawiki, roles, accounts, watchmysys.com
dn: cn=mediawiki,cn=roles,cn=accounts,dc=watchmysys,dc=com
objectClass: groupofnames
objectClass: nestedgroup
objectClass: top
cn: mediawiki
description: mediawiki administrators
member: uid=hmartin,cn=users,cn=accounts,dc=watchmysys,dc=com

Inside the LdapAuthentication extension we need to configure the parameters used to query LDAP for users:

$wgLDAPDomainNames = array('watchmysys.com');
$wgLDAPServerNames = array('watchmysys.com' => 'ipa.watchmysys.com');
$wgLDAPUseLocal = false;
$wgLDAPEncryptionType = array('watchmysys.com' => 'tls');
$wgLDAPOptions = array();
$wgLDAPPort = array();
$wgLDAPSearchStrings = array('watchmysys.com' => 'uid=USER-NAME,cn=users,cn=accounts,dc=watchmysys,dc=com');
$wgLDAPProxyAgent = array('watchmysys.com' => 'uid=mediawiki,cn=sysaccounts,cn=etc,dc=watchmysys,dc=com');
$wgLDAPProxyAgentPassword = array('watchmysys.com' => 'EpQIJjhRj');
$wgLDAPSearchAttributes = array();
$wgLDAPBaseDNs = array('watchmysys.com' => 'dc=watchmysys,dc=com');
$wgLDAPGroupBaseDNs = array('watchmysys.com' => 'cn=roles,cn=accounts,dc=watchmysys,dc=com');
$wgLDAPUserBaseDNs = array('watchmysys.com' => 'cn=users,cn=accounts,dc=watchmysys,dc=com');
$wgLDAPWriterDN = array();
$wgLDAPWriterPassword = array();
$wgLDAPWriteLocation = array();
$wgLDAPAddLDAPUsers = array();
$wgLDAPUpdateLDAP = array();
$wgLDAPPasswordHash = array();
$wgLDAPMailPassword = array();
$wgLDAPPreferences = array('email'=>'mail','realname'=>'displayname','nickname'=>'cn');
$wgLDAPDisableAutoCreate = array();
$wgLDAPDebug = 0;
$wgLDAPGroupUseFullDN = array('watchmysys.com' => true);
$wgLDAPLowerCaseUsername = array('watchmysys.com' => true);
$wgLDAPGroupUseRetrievedUsername = array();
$wgLDAPGroupObjectclass = array('watchmysys.com' => 'groupofnames');
$wgLDAPGroupAttribute = array('watchmysys.com' => 'member');
$wgLDAPGroupNameAttribute = array('watchmysys.com' => 'cn');
$wgLDAPGroupsUseMemberOf = array('watchmysys.com' => false);
$wgLDAPUseLDAPGroups = array();
$wgLDAPLocallyManagedGroups = array();
$wgLDAPGroupsPrevail = array();
$wgLDAPRequiredGroups = array('watchmysys.com' => array('cn=mediawiki,cn=roles,cn=accounts,dc=watchmysys,dc=com'));
$wgLDAPExcludedGroups = array();
$wgLDAPGroupSearchNestedGroups = array('watchmysys.com' => false);
$wgLDAPAuthAttribute = array();
$wgLDAPAutoAuthUsername = "";
$wgLDAPAutoAuthDomain = "";
$wgPasswordResetRoutes['domain'] = true;
$wgLDAPActiveDirectory = array();

The above configuration uses direct binds to authenticate users, and anonymous binds to verify that the user is part of the specified wgLDAPRequiredGroups. There are instructions for how to authenticate a user against Active Directory using only anonymous binds but I wasn’t able to get this working against the FreeIPA LDAP implementation.

Additionally, I found that you need to set $wgLDAPGroupUseFullDN = array('watchmysys.com' => true); for group memberships to be found. Otherwise the LDAP Authentication extension will fail to find the mediawiki group and verify that the username is a member, thus refusing to authenticate the user.

Now that you have the LDAP Authentication extension configured you need to enable it in LocalSettings.php:

require_once "$IP/extensions/LdapAuthentication/LdapAuthentication.php";
require_once 'includes/AuthPlugin.php';
$wgAuth = new LdapAuthenticationPlugin();

After many unsuccessful login attempts I found that the MediaWiki database needed to be updated before I could login using my LDAP credentials:

/var/www/mediawiki$ php maintenance/update.php
...
Creating ldap_domains table ...done.
...
Done 0 files in 0.0 seconds
Fixing protocol-relative entries in the externallinks table...
Done, 0 rows updated.
Populating fa_sha1 field from fa_storage_key

Done 0 files in 0.0 seconds
Purging caches...done.

Done.

If you still cannot login it is possible to enable additional logging from the LdapAuthentication extension. To enable verbose logging edit LdapAuthnetication.php, change $wgLDAPDebug = 3; and add:

$wgDebugLogGroups["ldap"] = "/tmp/ldapdebug.log";

The log file defined in wgDebugLogGroups will contain information from the LdapAuthentication extension and will help you diagnose why authentication is failing.

Note: If a user’s Mediawiki username is the same as their LDAP username Mediawiki will remove their password from the database.

Before LDAP:

MariaDB [mediawiki]> select user_id,user_name,user_real_name,user_password from user where user_name='Hmartin';
+---------+-----------+----------------+----------------------------------------------+
| user_id | user_name | user_real_name | user_password                                |
+---------+-----------+----------------+----------------------------------------------+
|       2 | Hmartin   | Hal Martin     | :B:a24f940c:89ebc6b51ad2529ef6fd503b9ab1c8db |

After logging in as my LDAP user:

MariaDB [mediawiki]> select user_id,user_name,user_real_name,user_password from user where user_name='Hmartin';
+---------+-----------+----------------+----------------------------------------------+
| user_id | user_name | user_real_name | user_password                                |
+---------+-----------+----------------+----------------------------------------------+
|       2 | Hmartin   | Hal Martin     |                                              |

I’m guessing this means that if the LDAP server is down authentication will not fall back to the user password stored in the database (since it’s now absent).

That’s it. You should have LDAP authentication working for Mediawiki. If you run into any problems I suggest enabling wgLDAPDebug and wgDebugLogGroups and examining the logs to find out what went wrong. As always, tcpdump is your friend!

Leave a Reply

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