Open main menu

Extension:DNNAuthentication

MediaWiki extensions manual
OOjs UI icon advanced.svg
DNNAuthentication
Release status: experimental
Implementation User identity
Description Authenticate WikiMedia to the aspnet_membership table on MS SQL used by ASP.NET and DotNetNuke. Tested with DNN 4.5 using 3DES encryption.
Author(s) Kim Pham-Guilbeault
Latest version 0.1 (2009-04-07)
MediaWiki 1.14
License GPL
Download #Source Code
Translate the DNNAuthentication extension if it is available at translatewiki.net
Check usage and version matrix.

NoteEdit

I am not a PHP programmer so feel free to modify as you wish. This extension has been tested with DotNetNuke but should also work with any asp.net website whose membership tables (aspnet_membership and aspnet_user) are populated by the SqlMembershipProvider. Note: This will only work if the website uses a fixed decryption key using the 3DES algorithm. This will not work with an AutoGenerate decryption key.

Tested onEdit

Current Version (0.1) has been tested on:

  • MediaWiki
    • MediaWiki 1.14
  • Operating Systems
    • Microsoft Windows XP
    • Microsoft Windows 2003
  • Web Servers
    • IIS5+PHP FASTCGI
    • IIS6+PHP FASTCGI
  • Database Server
    • SQL SERVER EXPRESS 2005
    • SQL SERVER 2005

ChangelogEdit

v0.1Edit

  • Initial Release

RoadmapEdit

Next versionEdit

Override function to create a DNN user from WikiMedia and implement other missing AuthPlugin functions.

To doEdit

Check if it's possible to add the option of Windows authentication rather than SQL Server Authentication

Add compatibility with other membership providers and encryption method thus decoupling it from DNN and making it a generic ASP.NET identity extension.

Enabling the pluginEdit

When the plugin is dropped in extensions (preferred)

Add the following line to your LocalSettings.php file.

require_once "$IP/extensions/DNNAuthentication.php";
$wgAuth = new DNNAuthentication();
$wgDNNAuthSQLServer = 'SERVERNAME\INSTANCENAME';
$wgDNNAuthSQLDatabase = 'database';
$wgDNNAuthSQLUsername = "username";
$wgDNNAuthSQLPassword = "password";
$wgDNNAuthMachineDecryptionKey = "94BAG9SF75AB37FD00C223FBBC0EA8A17B5BA664FD76CA8E"; // 192 bits machine decryption key found in web.config

PHP extensionsEdit

You will need to enable the following php extensions:

  • php_mssql.dll
  • php_mcrypt.dll
  • php_mhash.dll


Source CodeEdit

<?php
# Copyright (C) 2009 Kim Pham-Guilbeault <kimphamg@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# http://www.gnu.org/copyleft/gpl.html


require_once( 'AuthPlugin.php' );

class DNNAuthentication extends AuthPlugin {
	
	function userExists( $username )
	{
		$username = mysql_real_escape_string(trim($username));
	
		$link = $this->connect();
		
		// query the database for the membership information
		$result = mssql_query("SELECT u.UserId, m.Password, m.PasswordSalt FROM aspnet_Users as u JOIN aspnet_Membership as m on u.UserId = m.UserId WHERE u.UserName = '$username'");

		mssql_close($link);
		
		return mssql_num_rows($result) > 0;
	}

	function connect()
	{
		global $wgDNNAuthSQLServer, $wgDNNAuthSQLDatabase, $wgDNNAuthSQLUsername, $wgDNNAuthSQLPassword;
	
		$link = mssql_connect($wgDNNAuthSQLServer, $wgDNNAuthSQLUsername, $wgDNNAuthSQLPassword);
		
		if(!$link || !mssql_select_db($wgDNNAuthSQLDatabase, $link))
		{
			die('Something went wrong while connecting to MSSQL and database $this->database');
		}
		
		return $link;
	}
	
	function authenticate($username, $password)
	{
		$username = mysql_real_escape_string(trim($username));
		
		if (strlen($password) == 0) return false;
		
		global $wgDNNAuthMachineDecryptionKey;
		
		$link = $this->connect();
		
		// query the database for the membership information
		$result = mssql_query("SELECT u.UserId, m.Password, m.PasswordSalt FROM aspnet_Users as u JOIN aspnet_Membership as m on u.UserId = m.UserId WHERE u.UserName = '$username'");

		if (mssql_num_rows($result) == 0) { return false; }
		
		$row = mssql_fetch_assoc($result);

		// decode the salt
		$salty = base64_decode($row['PasswordSalt']);

		// the membership provider password format is the concatenation of salt and password
		// make sure the password characters are separated by the NUL character
		$toEncrypt = $this->hexstr(bin2hex($salty)) . implode("\0", str_split(trim($password))) . "\0";
		
		$key = $this->hexstr($wgDNNAuthMachineDecryptionKey);
		
		// The ASP.NET membership provider use an empty 8-bytes array for its initialization vector
		$encodedPassword = base64_encode($this->encryptNET3DES($key, "\0\0\0\0\0\0\0\0", $toEncrypt));

		mssql_close($link);

		return $encodedPassword == $row['Password'];
	}

	function autoCreate() {
		return true;
	}
	
	function hexstr($hexstr) {
	  $hexstr = str_replace(' ', '', $hexstr);
	  $hexstr = str_replace('\x', '', $hexstr);
	  $retstr = pack('H*', $hexstr);
	  return $retstr;
	}

	/* Function by ale_ferrer@yahoo.com found at http://www.php.net/manual/en/function.mcrypt-encrypt.php */
	function encryptNET3DES($key, $vector, $text){
		$td = mcrypt_module_open (MCRYPT_3DES, '', MCRYPT_MODE_CBC, '');

		// Complete the key
		$key_add = 24-strlen($key);
		$key .= substr($key,0,$key_add);

		// Padding the text
		$text_add = strlen($text)%8;
		for($i=$text_add; $i<8; $i++){
			$text .= chr(8-$text_add);
		}

		mcrypt_generic_init ($td, $key, $vector);
		$encrypt64 = mcrypt_generic ($td, $text);
		mcrypt_generic_deinit($td);
		mcrypt_module_close($td);

		 // Return the encrypt text in 64 bits code
		return $encrypt64;
	}
	
	function strict()
	{
		return true;
	}
	
	function getCanonicalName( $username ) {
		//Change username to lowercase so that multiple user accounts
		//won't be created for the same user.
		$username = strtolower($username);

		//The wiki considers an all lowercase name to be invalid; need to
		//uppercase the first letter
		$username = ucfirst($username);

		return $username;
	}


}