Extension:NTLMActiveDirectory

From MediaWiki.org
Jump to navigation Jump to search

NTLMActiveDirectory extension no longer works with MediaWiki 1.27 and its new authentication mechanism -> https://github.com/robertlabrie/NTLMActiveDirectory/issues/2

MediaWiki extensions manual
Crystal Clear action run.svg
NTLM Active Directory authentication
Release status: beta
Implementation User identity
Description Automatically logs users using the REMOTE_USER environment variable with details pulled from Active Directory.
Author(s) Robert Labrie (Robert.Labrietalk)
Latest version 0.0.1 (2013-09-16)
MediaWiki 1.20+
PHP 5.3+
Database changes No
License GNU General Public License 2.0 or later
Download
Translate the NTLMActiveDirectory extension if it is available at translatewiki.net
Check usage and version matrix.

The NTLMActiveDirectory extension (and wiki page) is a fork of the AutomaticREMOTE USER extension re-written specifically for Windows server. It is a Windows only extension, using the php_com_dotnet extension to create ADSI COM objects.

For AD users on Windows servers, that means there is zero configuration required. The extension uses ADSI to find your Global Catalog and search the directory for users. This is much simpler than using LDAP, because there is no need to setup SSL LDAP binds, or a user account to bind to the directory. When a service, like IIS, is running as "Local Service" on a domain member computer, domain resources are accessed using the computer account, and no external authentication is required.

The default is for all IIS authenticated users to have a wiki user assigned, but this can be overridden with the wikiUserGroups array. This way, users can have "read only" access to the wiki, by disabling anonymous user edits. If a user is created, the following properties are set from active directory:

  • Username (based on a rule)
  • Email address
  • Real name

The extension allows multiple AD groups to be assigned various roles. AD groups can be granted access to:

  • Have Wiki accounts
  • Access the login form dangerous - see below
  • Mapped wiki groups

In an ideal setup, one AD group would be mapped to a wiki role/group, but multiple groups can be mapped.

Installation[edit]

Until this extension is added to Gerrit, it is downloaded from GitHub. Click the link in the info box and then from GitHub click "Download Zip". Extract the ZIP in the MediaWiki extensions directory.

Installation requires the following steps:

  1. Enable php_com_dotnet in php.ini
  2. Enable the extension in LocalSettings.php
  3. Configure IIS for authentication

It's also a good idea to map an administrative domain group to the MediaWiki "sysop" group.


php.ini[edit]

PHP COM extension is usually not enabled by default. Add the following to your php.ini

extension=php_com_dotnet.dll

LocalSettings.php[edit]

Place the following two lines in your LocalSettings.php file:

require_once("$IP/extensions/NTLMActiveDirectory/NTLMActiveDirectory.php");
$wgAuth = new NTLMActiveDirectory();

Configure IIS[edit]

Depending on your version of Internet Information Services (IIS) Manager, your navigation may be slightly different. The instructions below are specified for a corporate server running IIS v8 on Windows Server 2012. It's very similar to Windows Server 2008. Windows 2003 might be different.

To enable simple authentication navigate to the following paths:

  1. Open IIS Manager
  2. (Server Name) → Sites → Your Website → Your wiki directory (if not in the root)
  3. From "Features View" double click, "Authentication"
    • Disable Anonymous Authentication
    • Enable Windows Authentication (HTTP 401 Challenge)
    • Enable Basic Authentication (optional)

Windows authentication is an IIS feature in server 2012. To enable it, use the following steps:

  1. Open server manager
  2. Click Add roles and features
  3. Click Next until you get to server roles
  4. Expand Web Server (IIS) → Web Server → Security
    • Check off Windows Authentication
    • Check off Basic Authentication (optional - if you need to support ancient browsers or cURL)
  5. Click next and finish through the wizard

Directory ACEs[edit]

If you installed MediaWiki through the Web Platform Installer, or just decompressed the zip in wwwroot, you'll inherit the default permissions which is Read+Execute for Domain Users. Anyone logged in to the domain will be able to access the wiki. The place to control this is with directory level ACEs.

Compatibility Matrix[edit]

This extension was developed on MW 1.20, Windows 2012 and PHP 5.3. If anyone else has it working on a different configuration, please let me know.

MW version Windows Version PHP Version Forest Functional Level Domain Functional Level comments
1.20 2012 5.3 2012 2012 developed here

Configuration[edit]

The default configuration is as follows:

  • Authenticated users will automatically have wiki users created in the form of DOMAIN\username
  • Local logins will be impossible

Sample Configuration[edit]

This extension doesn't require any additional configuration, but the below example demonstrates how to use some of the advanced features.

require_once("$IP/extensions/NTLMActiveDirectory/NTLMActiveDirectory.php");

//create the auth module
$wgAuth = new NTLMActiveDirectory();

//use classic NT style usernames
$wgAuth->userFormat = 'nt';

//do an exception for an internal user which is maybe used by some API process
$wgAuth->exemptUserAdd("wikiAPIUser");

//Only users in these groups should be given accounts in the wiki
$wgAuth->wikiUserGroupsAdd("CONTOSO\\Help Desk Users");
$wgAuth->wikiUserGroupsAdd("CONTOSO\\Server Admins");

//Wiki Admins may need to be able to create local users or bypass the auth module
$wgAuth->wikiLocalUserGroupsAdd("CONTOSO\\Wiki Admins");

//Wiki Admins should get internal sysop group
//This make it impossible to assign the group through User Rights Management
$wgAuth->groupMapAdd("sysop","CONTOSO\\Wiki Admins");


//serversetup used to control server namespace per server boss
$wgAuth->groupMapAdd("serversetup","CONTOSO\\Server Admins");

User format[edit]

The extension takes the REMOTE_USER variable passed in from the webserver, and does a lookup in AD to get the user object. This gives you some different options for how the wiki user should be formatted. The options are:

Value Example Description
nt CONTOSO\UserName The classic windows NT domain\username. Domain will always be upper case. Username is in the format from AD.
upn UserName.contoso.com The NT5+ UPN style. The @ symbol is invalid in an MW username, so it's replaced with a period. Be careful, a user might not have a UPN.
sam UserName samAccountName is the username component of an NT account. If you have a multi-domain forest with trusts, users with the same names will trip over eachother. If you have a single domain, and will only ever have a single domain, then this is a good option.
fullname JohnSmith This the the givenName and surname property, glued together without spaces.

Custom Function[edit]

If the above defaults are not suitable, you can set this property to the name of a callback function. The function must return a string, and accept an array as a parameter. Your local settings might have something like this:

function myUsernameMaker( $user )
{
return $user['givenName'] . '_' . $user['sn'];
}

$wgAuth->userFormat = "myUsernameMaker";

The structure of the array is as follows:

Property Example
userPrincipalName john.smith@contoso.com
cn Smith, John (Contoso)
distinguishedName CN=Smith\, John (Contoso),OU=Sales,OU=Business Units,DC=contoso,DC=com
samAccountName john.smith
givenName John
sn Smith
mail jsmith@contoso.com
netBIOSDomain CONTOSO
netBIOSUsername CONTOSO\john.smith

Exempt Users[edit]

You can exempt certain users from participating in automatic login. These users will fall through to the default MW login. This list is Wiki users who should not be checked against the REMOTE_USER variable. The default is WikiSysop. Additional users can be added thusly:

$wgAuth->exemptUserAdd("username");

Wiki Users[edit]

By default, every user who connects will have a wiki account created, and will be automatically signed into that account. You can override this behavior with the WikiUserGroups array. Users who are a member of any of these groups will have an account created. All other users will not have an account, and will not be able to create a local user. See Wiki Local Users below for local users. Groups must be in the DOMAIN\GroupName format, and are added as follows:

$wgAuth->wikiUserGroupsAdd("domain\\groupname");

Allow local login[edit]

Warning Warning: Wiki users created with this extension have blank passwords. Anyone who can interact with the login page can impersonate any user.

By default, no one is allowed to login with a local account. Users which are in groups added to the WikiLocalUserGroups array will have the full suite of login tools available. This is useful for some support users, but in most cases is not desirable. Groups must be in the DOMAIN\GroupName format, and are added as follows:

$wgAuth->wikiLocalUserGroupsAdd("domain\\groupname");

Group Mapping[edit]

Using Lockdown you can control access to different namespaces by wiki group. Using group mapping, you can map domain groups to wiki groups. Wiki groups which are not mapped are not checked. All mapped groups are enforced. The syntax is as follows

$wgAuth->wikiGroupMapAdd("wikigroup","domain\\groupname");

How It Works[edit]

When the user first hits the wiki, the web server authenticates the user and sets the REMOTE_USER variable. The MediaWiki code is then invoked. At the end of Setup.php, before any real processing begins, the extension's hook is called. This code depends primarily on the fact that user is always authenticated by the web server prior to any MediaWiki code being executed.

If the user already has an existing, valid MediaWiki session and account, the hook takes no further action. MediaWiki already has what it needs.

If the user does not have an existing MediaWiki session, the hook looks up the REMOTE_USER variable in active directory, sets a username based on configured options, and expands the AD users group membership. AD lookups are only done if a user is not logged in, to reduce the hits on AD.

wikiUserGroups is expanded. If the user is not allowed to have a wiki account, the hook returns, since there is no reason to attempt a login.

If the user has an existing valid MediaWiki account, it is logged in.

If the user has not created an account, the hook uses MediaWiki's initUser() function to create an account, and sets various default user-options. The hook then issues a Location directive to the browser, using the same URL that was called. When the browser reloads, the user account has been created, a session is now created, and MediaWiki behaves as normal.

Troubleshooting[edit]

Cookies[edit]

If the user has cookies turned off, they will probably find themselves in an endless redirection loop.

Password[edit]

Contrary to previous versions of Mediawiki, the authenticateUserData() function will automatically fail if an empty password is provided, e.g., within a faux login call; for MediaWiki v1.17.0, try using just a space instead.

Backups[edit]

If your backups don't work, try setting the REMOTE_USER environment variable manually:

REMOTE_USER="wikiusername" php dumpBackup.php  --full

Initialization[edit]

This extension makes use of the "Hook" at the end of Setup.php. This allows the extension to perform initialization in the fully initialized environment.

The extension's initialization code adds the name of the extension's primary workhorse function to $wgExtensionFunctions. If the array doesn't exist or is not an array, it is assumed that it is a single string and then converted into an array. All this is done only if REMOTE_USER is actually set. If it's not set, there is no point to the extension.

AuthPlugin routines[edit]

Several routines from AuthPlugin must be overridden for correct operation to occur.

  • userExists() must return true always. The method is misleading. It's only called by MediaWiki in determining whether the user exists in the security context, not whether the user is in the MediaWiki database.
  • authenticate() returns true if a user is allowed to have a wiki account, otherwise false.
  • autoCreate() should always be true. This gets checked only within initUser(), ie, when the Web Server has authenticated a user unknown to the Wiki.
  • strict() is set to true based on the word of the author of the previous version of this extension.
  • modifyUITemplate configures the user interface so that the user does not see configuration options which don't apply to him. I'm not certain this works correctly.

Built-in groups don't expand[edit]

Built in groups like Domain Users and Domain Admins don't seem to expand properly with ADSI.

UPN is optional[edit]

Even now, the UPN is optional, and at least in server 2012 is not set for built-in users like Administrator. The adUserGet() function uses the UPN to find the user, and will fail if one isn't specified. A workaround for this might be to query for samAccountName and then filter the result set based on DC=netbiosdomain, in the same way that adGroupGet works (since groups don't have a UPN). This requires a code change.

Another reason to get the "Maybe the UPN field is not specified" message is that an exception is thrown when trying to connect to open the ADODB connection. This may be due to improper IIS / IWA / Kerberos configuration. If you have no problems when testing locally on the IIS machine, but get the error message when trying remotely, you may be facing a Kerberos delegation issue, which is required for a double hop with IWA / Kerberos. To troubleshoot, try temporarily disabling Windows Authentication in IIS and enable only Basic Authentication. If the problem goes away when you provide username / password credentials, then this is most likely the problem you are facing.

Local groups are not checked[edit]

Even though domain entities can be part of local security groups, the local groups do not appear in the domain objects "memberOf" property, so they will not be expanded.

Case sensitive username[edit]

MW usernames are case sensitive, but AD usernames are not. If CONTOSO\John.Smith becomes CONTOSO\john.smith, MW will create a new user object for this person. Use Extension:UserMerge.