Extension:OpenAM

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual
Crystal Clear action run.png
OpenAM

Release status: stable

Implementation User identity
Description OpenAM Authentication
Author(s) Alexandre Porto da Silva (Alexandre Portotalk)
Latest version 12.06.14
License GPL
Download copy/paste

Translate the OpenAM extension if it is available at translatewiki.net

Check usage and version matrix; code metrics

Pre-requisites[edit | edit source]

You must have the pecl_http extension (http://pecl.php.net/package/pecl_http) installed into PHP, since MediaWiki's built in http functions do not allow us to set cookies. [1]

To install the pecl_http PHP extension on Ubuntu follow the instructions below [2]:

  1. Install the required packages:
    # apt-get install php-pear php5-dev libcurl4-openssl-dev
    
  2. Install pecl_http:
    # pecl install pecl_http
    
    or [3]
    download from: http://pecl.php.net/package/pecl_http
    end
    cd /path/to/download
    tar -xzvf pecl_http-x.x.x.tgz
    cd pecl_http-x.x.x/
    phpize
    ./configure
    make
    make install
    
  3. Create file /etc/php5/conf.d/http.ini with the following content:
    extension=http.so
    
  4. Reload Apache2:
    # service apache2 reload
    

Install[edit | edit source]

Copy & paste in: /path/to/wiki/extensions/OpenAM/OpenAM.php

Include on LocalSettings.php:

# OpenAM
# More info: http://www.mediawiki.org/wiki/Extension:OpenAM
require_once( "$IP/extensions/OpenAM/OpenAM.php" );
// You MUST set the distAuth URL
$wgAuth->setDistAuthUrl( 'http://openam.server.com/distAuth/UI/' );
// You MUST set the identity URL
$wgAuth->setIdentityUrl( 'http://openam.server.com/identity' );
// Set this to the OpenSSO profile attribute that holds users' MediaWiki names
$wgAuth->setUid( 'uid' );
// You will only need to change the cookie name if you have changed it on the OpenSSO server (recommended)
$wgAuth->setCookie( 'iPlanetDirectoryPro' );
// new
$wgAuth->setLdapGroups( 'ldap-groups' );

Source[edit | edit source]

OpenAM.php[edit | edit source]

<?php
/**
 * Based on:
 * 
 * OpenSSO = http://sources.forgerock.org/browse/openam/trunk/community/extensions/mediawikiextension
 *           http://openam.forgerock.org/doc/dev-guide/OpenAM-Dev-Guide.html
 *     License.: CDDLv1.0
 *     Revision: 6
 *     Date....: 17 Feb 10
 *           
 * and:
 * 
 * LdapAuthentication = http://www.mediawiki.org/wiki/Extension:LDAP_Authentication
 *     License.: GPL 2
 *     Version.: 1.2c
 */
 
/**
 * Protect against register_globals vulnerabilities.
 * This line must be present before any global variable is referenced.
 */
if( !defined( 'MEDIAWIKI' ) ) {
        echo( "This is an extension to the MediaWiki package and cannot be run standalone.\n" );
        die( -1 );
}
 
define( 'OPENAM_VERSION', '12.06.14' );
 
# Extension credits that will show up on Special:Version    
$wgExtensionCredits['OpenAM'][] = array(
	'path'           => __FILE__,
	'name'           => 'OpenAM',
	'version'        => OPENAM_VERSION,
	'author'         => 'Alexandre Porto da Silva', 
	'url'            => 'http://www.mediawiki.org/wiki/Extension:OpenAM',
	'descriptionmsg' => 'OpenAM Authentication',
	'description'    => 'OpenAM Authentication'
);
 
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['user']['createaccount'] = false;
$wgGroupPermissions['sysop']['createaccount'] = false;
$wgGroupPermissions['bureaucrat']['createaccount'] = false;
 
class OpenAM extends AuthPlugin {
	// based on: OpenSSO and LdapAuthentication
 
	// based on: OpenSSO
	var $mDistAuthUrl;
	var $mIdentityUrl;
	var $mUid = 'uid';
	var $mCookie = 'iPlanetDirectoryPro';
	var $mLdapGroups = ''; //new
	var $mToken = ''; //new
	// name change from: LdapAuthentication
	var $mLdapInfo;
	var $mUserInfo;
	var $mUserName;
 
	function setDistAuthUrl( $distAuthUrl ) {
		// based on: OpenSSO->mOpenssoBaseUrl
		$this->mDistAuthUrl = $distAuthUrl;
	}
 
	function setIdentityUrl( $identityUrl ) {
		// based on: OpenSSO->mOpenssoBaseUrl
		$this->mIdentityUrl = $identityUrl;
	}
 
	function setUid( $uid ) {
		// name change from: OpenSSO->setOpenssoMediaWikiUsernameAttribute
		$this->mUid = $uid;
	}
 
	function setCookie( $cookie ) {
		// name change from: OpenSSO->setOpenssoCookieName
		$this->mCookie = $cookie;
	}
 
	function setLdapGroups( $ldapGroups ) {
		$this->mLdapGroups = $ldapGroups;
	}
 
	function setToken() {
		$this->mToken = isset( $_COOKIE[$this->mCookie] ) ? $_COOKIE[$this->mCookie] : '';
	}
 
	function getToken() {
		if( !$this->mToken ) {
			$this->setToken();
		}
		return $this->mToken;
	}
 
	function setLdapInfo() {
		// based on: OpenSSO and LdapAuthentication->getUserInfo
		$this->mLdapInfo = $this->mUserInfo = array();
		$this->mUserName = '';
 
		// based on: OpenSSO->getMediaWikiName
		$url = $this->mIdentityUrl . '/attributes?subjectid=' . urlencode( $this->getToken() );
		$body = $this->getBody( $url );
		if ( $body ) {
			$attributes = array();
			$lines = explode( "\n", $body );
			foreach ( $lines as $line ) {
				if ( substr( $line, 11, 11 ) == '.attribute.' ) {
					if ( substr( $line, 21, 6 ) == '.name=' ) {
						$name = substr( $line, 27 );
					} else {
						$attributes[$name][] = substr( $line, 28 );
					}
				} elseif ( $this->mLdapGroups && substr( $line, 11, 6 ) == '.role=' ) {
					$attributes[$this->mLdapGroups][] = substr( $line, 17 );
				}
			}
			if ( isset( $attributes[$this->mUid][0] ) ) {
				//start-ldap compatibility: ldap_get_entries()
				$ldapInfo = array();
				$ldapInfo['count'] = 1;
				foreach ( $attributes as $key => $val ) {
					$ldapInfo[0][$key]['count'] = count( $val );
					$ldapInfo[0][$key] += $val;
					$ldapInfo[0][] = $key;
				}
				$ldapInfo[0]['count'] = count( $attributes );
				//end-ldap compatibility: ldap_get_entries()
 
				// set mUserName
				$this->mUserName = $attributes[$this->mUid][0];
 
				// set mLdapInfo
				$this->mLdapInfo = $ldapInfo;
 
				// set mUserInfo
				$userInfo = array();
				wfRunHooks( 'SetUserInfo', array( $this, &$userInfo ) );
				$this->mUserInfo = $userInfo;
			}
		}
	}
 
	function getLdapInfo() {
		if ( !$this->mLdapInfo ) {
			$this->setLdapInfo();
		}
		return $this->mLdapInfo;
	}
 
	function getUserInfo() {
		if ( !$this->mLdapInfo ) {
			$this->setLdapInfo();
		}
		return $this->mUserInfo;
	}
 
	function getUserName() {
		if ( !$this->mLdapInfo ) {
			$this->setLdapInfo();
		}
		return $this->mUserName;
	}
 
	function getUser() {
		$user = new User;
		$username = $this->getUserName();
		if ( $username ) {
			$localId = User::idFromName( $username );
			if ( $localId ) {
				$user->setID( $localId );
				$user->loadFromId();
			} else {
				$user->loadDefaults( $username );
			}
		}
		return $user;
	}
 
	/*
	 * Returns the requested URL without any query parameters
	 */
	function urlNoQuery() {
		// based on: OpenSSO->urlNoQuery
		$url = 'http';
 
		$port = '';
		if ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ) { 
			$url .=  's';
			$port = '443';
		} else {
			$port = '80';
		}
		$port = $_SERVER['SERVER_PORT'] == $port ? '' : ':' . $_SERVER['SERVER_PORT'];
 
		$url .= '://' . $_SERVER['HTTP_HOST'] . $port . $_SERVER['SCRIPT_NAME'];
 
		return $url;
	}
 
	/*
	 * Returns the full requested URL so we can redirect the user back here after 
	 * they authenticate at OpenAM
	 */
	function fullUrl() {
		// based on: OpenSSO->fullUrl
		$full_url = $this->urlNoQuery();
 
		if ( $_SERVER['QUERY_STRING']>' ' ) {
			$full_url .=  '?'.$_SERVER['QUERY_STRING'];
		} elseif ( isset( $_SERVER['PATH_INFO'] ) && $_SERVER['PATH_INFO']>' ' ) { //new
			$full_url .= $_SERVER['PATH_INFO'];   //new
		}
 
		return $full_url;
	}
 
	function getReturnToUrl( $url ) {
		// based on: OpenSSO->getReturnToUrl
		$titleObj = false;
 
		$pageStart = strpos( $url, '&returnto=' ); //"+ 10": moved from here
		if ( $pageStart !== false ) {
			$pageStart += 10; //for here
			$pageEnd = strpos( $url, '&', $pageStart );
 
			if ( $pageEnd === false ) {
				$page = substr( $url, $pageStart );
			} else {
				$page = substr( $url, $pageStart, $pageEnd - $pageStart );
			}
			$page = urldecode( $page );
			$titleObj = Title::newFromText( $page );
		}
 
		if ( !$titleObj || !$titleObj instanceof Title || !$titleObj->exists() ) {
			$titleObj = Title::newMainPage();
		}
 
		return $titleObj->getFullUrl();
	}
 
	function getBody( $url, $options = array() ) {
		$options['timeout'] = 10;
		for ( $i = 0; $i < 3; $i++ ) { //loop timeout: 10 + 10 ...
			$response = @http_get( $url, $options, $info );
			if ( isset( $info['response_code'] ) && $info['response_code'] == 200 ) {
				$std = @http_parse_message( $response );
				if ( $std instanceof stdClass ) {
					return $std->body;
				}
			}
			$options['timeout'] += 10;
		}
		return false;
	}
 
	function isTokenValid() {
		// based on: OpenSSO->isTokenValid
		$cookies = array( $this->mCookie => $this->getToken() );
		if ( $cookies[$this->mCookie] ) {
			$options = array( 'cookies' => $cookies, 'encodecookies' => false );
 
			$body = $this->getBody( $this->mIdentityUrl . '/isTokenValid', $options );
			if ( !$body ) {
				return false;
			}
 
			// value will be of the form boolean=true
			if ( substr( trim( $body ), 8 ) == 'true' ) {
				return true;
			}
		}
 
		return false;
	}
 
	function checkLogin( $user ) {
		// simplified from: OpenSSO->login
		if ( $user->isLoggedIn() ) {
			return true;
		}
 
		$username = $this->getUserName();
		if ( !$username ) {
			return false;
		}
 
		$retval = LoginForm::SUCCESS;
		if( !wfRunHooks( 'AbortLogin', array( $user, $this, &$retval ) ) ) {
			return false;
		}
 
		// simplified from: LdapAutoAuthentication->Authenticate
 
		// Is the user already in the database?
		$localId = User::idFromName( $username );
		if ( !$localId ) {
			$user->loadDefaults( $username );
			$user->addToDatabase();
			$user->saveSettings();
			# Update user count
			$ssUpdate = new SiteStatsUpdate( 0, 0, 0, 0, 1 );
			$ssUpdate->doUpdate();
			# Notify hooks (e.g. Newuserlog)
			wfRunHooks( 'AuthPluginAutoCreate', array( $user, $this ) );
		} else {
			$user->setID( $localId );
			$user->loadFromId();
		}
 
		$user->setCookies();
		wfSetupSession();
 
		wfRunHooks( 'UserLoginComplete', array( &$user, $this ) );
 
		return true;
	}
 
	static function login( $user ) {
		global $wgAuth;
 
		// based on Joomla 1.5: plgSystemSso::onAfterInitialise() in: plugins/system/sso.php
		if ( $wgAuth->isTokenValid() && $wgAuth->checkLogin( $user ) ) {
			return true;
		}
 
		// based on MediaWiki: SpecialUserlogout::execute() in: includes/specials/SpecialUserlogout.php
		$user->logout();
 
		// based on: OpenSSO
		$url = $wgAuth->fullUrl();
		$url = urlencode( $url );
		$url = $wgAuth->mDistAuthUrl . "Login?goto=$url";
		header( "Location: $url" );
		exit;
	}
 
	static function logout( &$user, &$inject_html, $old_name ) {
		global $wgAuth;
 
		// based on: OpenSSO
		$url = $wgAuth->fullUrl();
		$url = $wgAuth->getReturnToUrl( $url );
		$url = urlencode( $url );
		$url = $wgAuth->mDistAuthUrl . "Logout?goto=$url";
		header( "Location: $url" );
		exit;
	}
}
$wgHooks['UserLoadAfterLoadFromSession'][] = 'OpenAM::login';
$wgHooks['UserLogoutComplete'][] = 'OpenAM::logout';
$wgAuth = new OpenAM();