FUDforum
Fast Uncompromising Discussions. FUDforum will get your users talking.

Home » FUDforum » FUDforum Suggestions » SSO with TYPO3
Show: Today's Messages :: Polls :: Message Navigator
Switch to threaded view of this topic Create a new topic Submit Reply
SSO with TYPO3 [message #166236] Sun, 16 October 2011 11:57 Go to next message
kaystrobach is currently offline  kaystrobach   
Messages: 28
Registered: May 2006
Location: Bannewitz
Karma: 0
Junior Member

Hello guys,

currently i'm working on a SSO Adapter for fudforum from TYPO3 based on http://single-signon.com during the development i found some problems for implementing SSO Adapters:

first cool things:
- external_* functions are great

there some functions missing:
- it would be nice to have a additional function, called external_sync_groups(int $userId, array $groupnames), which automatically checks if a user is in the given groups an add or remove the membership
- also it would be nice to have a function like the following one to get the id for a given username without knowing a password

function external_getUserByUsername($login) {
	__fud_login_common(1);
	$r = db_sab('SELECT id FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'users WHERE login='. _esc($login));
	if($r) {
		return $r->id;
}
}


Thanks so far.

The code of the sso adapter can be obtained via PM, i will add it to single-singon.com when it's stable with group sync.

Regards
Kay
Re: SSO with TYPO3 [message #166241 is a reply to message #166236] Sun, 16 October 2011 17:17 Go to previous messageGo to next message
naudefj is currently offline  naudefj   South Africa
Messages: 3771
Registered: December 2004
Karma: 28
Senior Member
Administrator
Core Developer
Great, the lookup function will be added.

Not sure how "external_sync_groups()" will work, but it you code it, we will definitely consider it.
Aw: Re: SSO with TYPO3 [message #166250 is a reply to message #166241] Mon, 17 October 2011 05:56 Go to previous messageGo to next message
kaystrobach is currently offline  kaystrobach   
Messages: 28
Registered: May 2006
Location: Bannewitz
Karma: 0
Junior Member

the groups function should accept a comma list of group names (or array) and do the following stuff:

- add group if not existing
- add user to group if not member
- remove user from groups which are not in the list

This way it's really easy to have very flexible and powerfull sso adapters Wink
Re: Aw: Re: SSO with TYPO3 [message #166251 is a reply to message #166250] Mon, 17 October 2011 09:34 Go to previous messageGo to next message
naudefj is currently offline  naudefj   South Africa
Messages: 3771
Registered: December 2004
Karma: 28
Senior Member
Administrator
Core Developer
Sounds great! Can you help us to code it?
Aw: Re: Aw: Re: SSO with TYPO3 [message #166253 is a reply to message #166251] Mon, 17 October 2011 09:37 Go to previous messageGo to next message
kaystrobach is currently offline  kaystrobach   
Messages: 28
Registered: May 2006
Location: Bannewitz
Karma: 0
Junior Member

i do - what's the schedule for the next release?

could you please decide:

a) a name for the function
b) if the input should be a array of groups or a comma seperated string - while i prefer an array (would enable the use of commas in groupnames)

Regards
Kay
Re: Aw: Re: Aw: Re: SSO with TYPO3 [message #166256 is a reply to message #166253] Mon, 17 October 2011 10:07 Go to previous messageGo to next message
naudefj is currently offline  naudefj   South Africa
Messages: 3771
Registered: December 2004
Karma: 28
Senior Member
Administrator
Core Developer
See FUDforum 3.0.4 - 2011/Q4 or 2012/Q1.

It doesn't really matter, we can finalize the name and input parameters later.
Aw: Re: Aw: Re: Aw: Re: SSO with TYPO3 [message #166257 is a reply to message #166256] Mon, 17 October 2011 10:36 Go to previous messageGo to next message
kaystrobach is currently offline  kaystrobach   
Messages: 28
Registered: May 2006
Location: Bannewitz
Karma: 0
Junior Member

mhmm, i would like to use the final name in the sso adapter to avoid refactoring Wink
Aw: Re: Aw: Re: Aw: Re: SSO with TYPO3 [message #166258 is a reply to message #166257] Mon, 17 October 2011 13:08 Go to previous messageGo to next message
kaystrobach is currently offline  kaystrobach   
Messages: 28
Registered: May 2006
Location: Bannewitz
Karma: 0
Junior Member

during working with fudforum i found a problem :

function db_all($q)
{
	return uq($q)->fetchAll(PDO::FETCH_COLUMN);
}


should be

function db_all($q)
{
	$qo = uq($q);
	if(method_exists($qo, 'fetchAll)) {
		return ->fetchAll(PDO::FETCH_COLUMN);
	} else {
		return null;
	}
}
Aw: Re: Aw: Re: Aw: Re: SSO with TYPO3 [message #166259 is a reply to message #166258] Mon, 17 October 2011 15:47 Go to previous messageGo to next message
kaystrobach is currently offline  kaystrobach   
Messages: 28
Registered: May 2006
Location: Bannewitz
Karma: 0
Junior Member

currently i struggle at the following problem:

my function looks so:

function sso_syncGroups($userID, $groupNames) {
		// iterate
	foreach($groupNames as $groupName) {
			// Use special name
		$groupName = 'SSO: ' . $groupName;
			// Check wether group exists
		$r = db_sab('SELECT id FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups WHERE name='. _esc($groupName));
		if($r) {
			$groupId = $r->id;
		} else {
			$groupId = ins_m(
				$GLOBALS['DBHOST_TBL_PREFIX'] .'groups',
				'name',
				_esc($groupName)
			);
		}
			// Check wether user is in group and add it
		$r = db_sab('SELECT id FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members WHERE group_id='. _esc($groupId) . ' AND user_id=' . _esc($userID));
		if(!$r) {
			ins_m(
				$GLOBALS['DBHOST_TBL_PREFIX'] .'group_members',
				'group_id, user_id',
				array(
					_esc($groupId),
					_esc($userID)
				)
			);
		}
	}
		// remove groups which are removed in external adapter
	$list = '';
	foreach($groupNames as $groupName) {
		if($list !== '') {
			$list.= ', ';
		}
		$list.= _esc($groupName);
	}
	$q = '
		SELECT * 
		FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members 
		LEFT JOIN '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups ON '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members.group_id = fud_groups.id
		WHERE '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members.user_id = ' . _esc($userID) . '
		AND '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups.name NOT IN (' . $list . ')
		AND '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups.name LIKE "SSO:%"
	';
	$groupsToRemove = uq($q);
	if(method_exists($groupsToRemove, 'fetchAll')) {
		$groupsToRemove = $groupsToRemove->fetchAll(PDO::FETCH_COLUMN);
		foreach($groupsToRemove as $group) {
			echo $group;
			uq('DELETE FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members WHERE id = ' . _esc($group->id));
		}
	}
}


Using external_fud_login($User_ID) afterwards throws the following sql error - any idea?

HY000: Cannot execute queries while other unbuffered queries are active.


Thanks in advice - regards
Kay
Aw: Re: Aw: Re: Aw: Re: SSO with TYPO3 [message #166263 is a reply to message #166259] Wed, 19 October 2011 03:42 Go to previous messageGo to next message
kaystrobach is currently offline  kaystrobach   
Messages: 28
Registered: May 2006
Location: Bannewitz
Karma: 0
Junior Member

would be nice, if you would point me to the right usage of the fudapi (know how to bypass it - but that should'nt be the goal).

Below is the complete adapter throwing the error:

The function sso is called twice in my use case:
1. create user
2. login user

The Problem occurs during login, if i add the groups, so i assume, that i misuse some of the api functions, but i didn't found anyway to close the buffered query cursors in your queries (except closing the connection ...)

<?php
/*
* Signature-Based Single Sign-On Framework
* TPA Adapter for
* fudforum (http://www.fudforum.org )
*
*  Version            : 3.0.3
*  Last update        : 13.10.2011
*
* (c) Kay Strobach, Bannewitz, Germany
*  http://www.kay-strobach.de
*  http://www.single-signon.com
*/

/**
*  function which is called after including this file in the SSO-Agent.
*
*  @param
*    User_Name    string    Username the Session will be created for
*    remote_addr  string    Remoteaddress of the users system
*    agent        string    Browser
*    sso_url      string    Url where the user will be redirected after establishing a session for him
*    sso_version  string    the protocol version of the calling agent
*    sso_action   string    the action to perform. Right now this is either 'logon' or 'create_modify'
*    sso_userdata string    the userdata submitted by the agent
*
*  @return        string    return the session data
*
*  Leave stubs if you dont need all four params.
*/

/*
* return the protocol version
*/

//include libs
require_once('GLOBALS.php');
require_once($INCLUDE.'../scripts/forum_login.php');
require_once($INCLUDE.'../scripts/fudapi.inc.php');



function get_version(){
	return "2.0";
}

function sso($User_Name,$ip,$agent,$sso_url,$sso_version="",$sso_action="",$sso_userdata="") {
		// alternative: return error
	if ($sso_version == "") return array("Error"=>"sso version out of date");

		//process sso data
	$sso_userdata = process_userdata($sso_userdata);

	$User_ID   = sso_get_userByUsername($User_Name);

	$err = null;

	switch($sso_action){	
		// action: create user / update userdata
		case 'create_modify':
			$vals = array(
				'login' =>$User_Name,
				'passwd'=>md5(microtime(true)),
				'email' =>$sso_userdata['email'],
				'name'  =>$sso_userdata['name']
			);

			__fud_login_common(1);

			if(!$User_ID) {
				$User_ID = fud_add_user(
					$vals,
					$err
				);
			} else {
				fud_update_user(
					$User_ID,
					$vals,
					$err
				);
			}
			if(array_key_exists('usergroup', $sso_userdata)) {
				sso_syncGroups($User_ID, explode(',', $sso_userdata['usergroup']));
			}
		break;
		// perform logon for given $User_Name
		case 'logon':
			if (external_fud_login($User_ID)) {
				$return_val    = array();
				$return_val[0] = array();
				$return_val   += array( "redirecturl" => $sso_url);
				return $return_val;
			}
			return array("Error"=>"no account for this user");
		break;
	}
}

/* 
* process the userdata string and return an associative array
* @param string $sso_userdata: the data from fe_users (pipe-separated)
* @return array	$data: the userdata
*/
function process_userdata($sso_userdata){
	$sso_userdata = split("\|",$sso_userdata);
	for ($i=0;$i<count($sso_userdata);$i++) {
		$sso_userdata[$i]=split("=",$sso_userdata[$i]);
		$data[$sso_userdata[$i][0]]=$sso_userdata[$i][1];
	}
	unset ($sso_userdata);
	return $data;
}


function sso_get_userByUsername($login) {
	__fud_login_common(1);
	$r = db_sab('SELECT id FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'users WHERE login='. _esc($login));
	if($r) {
		return $r->id;
	}
}
function sso_syncGroups($userID, $groupNames) {
		// iterate
	foreach($groupNames as $groupName) {
			// Use special name
		$groupName = 'SSO: ' . $groupName;
			// Check wether group exists
		$r = db_sab('SELECT id FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups WHERE name='. _esc($groupName));
		if($r) {
			$groupId = $r->id;
		} else {
			$groupId = ins_m(
				$GLOBALS['DBHOST_TBL_PREFIX'] .'groups',
				'name',
				_esc($groupName)
			);
		}
			// Check wether user is in group and add it
		$r = db_sab('SELECT id FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members WHERE group_id='. _esc($groupId) . ' AND user_id=' . _esc($userID));
		if(!$r) {
			ins_m(
				$GLOBALS['DBHOST_TBL_PREFIX'] .'group_members',
				'group_id, user_id',
				array(
					_esc($groupId),
					_esc($userID)
				)
			);
		}
	}
		// remove groups which are removed in external adapter
	$list = '';
	foreach($groupNames as $groupName) {
		if($list !== '') {
			$list.= ', ';
		}
		$list.= _esc($groupName);
	}
	$q = '
		SELECT * 
		FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members 
		LEFT JOIN '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups ON '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members.group_id = fud_groups.id
		WHERE '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members.user_id = ' . _esc($userID) . '
		AND '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups.name NOT IN (' . $list . ')
		AND '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups.name LIKE "SSO:%"
	';
	$groupsToRemove = uq($q);
	if(method_exists($groupsToRemove, 'fetchAll')) {
		$groupsToRemove = $groupsToRemove->fetchAll(PDO::FETCH_COLUMN);
		foreach($groupsToRemove as $group) {
			echo $group;
			uq('DELETE FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members WHERE id = ' . _esc($group->id));
		}
	}
}
Aw: Re: Aw: Re: Aw: Re: SSO with TYPO3 [message #166292 is a reply to message #166263] Wed, 02 November 2011 09:00 Go to previous messageGo to next message
kaystrobach is currently offline  kaystrobach   
Messages: 28
Registered: May 2006
Location: Bannewitz
Karma: 0
Junior Member

no idea so far - i would really like to get the sso adapter ready, and the problem seems to be a small misuse of the fud db api - so please provide a tipp Wink

[Updated on: Wed, 02 November 2011 09:00]

Report message to a moderator

Re: Aw: Re: Aw: Re: Aw: Re: SSO with TYPO3 [message #166293 is a reply to message #166292] Wed, 02 November 2011 09:36 Go to previous messageGo to next message
naudefj is currently offline  naudefj   South Africa
Messages: 3771
Registered: December 2004
Karma: 28
Senior Member
Administrator
Core Developer
> "Cannot execute queries while other unbuffered queries are active."

Use q() instead of uq();
Aw: Re: Aw: Re: Aw: Re: Aw: Re: SSO with TYPO3 [message #166298 is a reply to message #166293] Wed, 02 November 2011 10:35 Go to previous message
kaystrobach is currently offline  kaystrobach   
Messages: 28
Registered: May 2006
Location: Bannewitz
Karma: 0
Junior Member

is db_sab buffering ready, for me it seems, that using that function is the problem, so i replaced it as well.

the following function should be modified for future releases:

function db_all($q)
{
	$r = uq($q);
	if($r) {
		return $r->fetchAll(PDO::FETCH_COLUMN);
	} else {
		return array();
	}
}


i still have the same problem, it always occurs in sso_get_userByUsername

This is my current state (same error and a bit frustrated Very Happy ):

<?php
/*
* Signature-Based Single Sign-On Framework
* TPA Adapter for
* fudforum (http://www.fudforum.org )
*
*  Version            : 3.0.3
*  Last update        : 13.10.2011
*
* (c) Kay Strobach, Bannewitz, Germany
*  http://www.kay-strobach.de
*  http://www.single-signon.com
*/

/**
*  function which is called after including this file in the SSO-Agent.
*
*  @param
*    User_Name    string    Username the Session will be created for
*    remote_addr  string    Remoteaddress of the users system
*    agent        string    Browser
*    sso_url      string    Url where the user will be redirected after establishing a session for him
*    sso_version  string    the protocol version of the calling agent
*    sso_action   string    the action to perform. Right now this is either 'logon' or 'create_modify'
*    sso_userdata string    the userdata submitted by the agent
*
*  @return        string    return the session data
*
*  Leave stubs if you dont need all four params.
*/

/*
* return the protocol version
*/

//include libs
require_once('GLOBALS.php');
require_once($INCLUDE.'../scripts/forum_login.php');
require_once($INCLUDE.'../scripts/fudapi.inc.php');


define('fud_debug', 1);

function get_version(){
	return "2.0";
}

function sso($User_Name,$ip,$agent,$sso_url,$sso_version="",$sso_action="",$sso_userdata="") {
		// alternative: return error
	if ($sso_version == "") return array("Error"=>"sso version out of date");

		//process sso data
	$sso_userdata = process_userdata($sso_userdata);

	__fud_login_common(1);
	$User_ID   = sso_get_userByUsername($User_Name);

	$err = null;

	switch($sso_action){	
		// action: create user / update userdata
		case 'create_modify':
			$vals = array(
				'login' =>$User_Name,
				'passwd'=>md5(microtime(true)),
				'email' =>$sso_userdata['email'],
				'name'  =>$sso_userdata['name']
			);

			

			if(!$User_ID) {
				$User_ID = fud_add_user(
					$vals,
					$err
				);
			} else {
				fud_update_user(
					$User_ID,
					$vals,
					$err
				);
			}
			if(array_key_exists('usergroup', $sso_userdata)) {
				sso_syncGroups($User_ID, explode(',', $sso_userdata['usergroup']));
			}
		break;
		// perform logon for given $User_Name
		case 'logon':
			if (external_fud_login($User_ID)) {
				$return_val    = array();
				$return_val[0] = array();
				$return_val   += array( "redirecturl" => $sso_url);
				return $return_val;
			}
			return array("Error"=>"no account for this user");
		break;
	}
}

/* 
* process the userdata string and return an associative array
* @param string $sso_userdata: the data from fe_users (pipe-separated)
* @return array	$data: the userdata
*/
function process_userdata($sso_userdata){
	$sso_userdata = split("\|",$sso_userdata);
	for ($i=0;$i<count($sso_userdata);$i++) {
		$sso_userdata[$i]=split("=",$sso_userdata[$i]);
		$data[$sso_userdata[$i][0]]=$sso_userdata[$i][1];
	}
	unset ($sso_userdata);
	return $data;
}


function sso_get_userByUsername($login) {
	$r = db_all('SELECT id FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'users WHERE login='. _esc($login));
	if(count($r)) {
		return $r[0];
	}
}
function sso_syncGroups($userID, $groupNames) {
		// iterate
	foreach($groupNames as $groupName) {
			// Use special name
		$groupName = 'SSO: ' . $groupName;
			// Check wether group exists
		
		$r = db_all('SELECT id FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups WHERE name='. _esc($groupName));
		
		if(count($r)) {
			$groupId = $r[0];
		} else {
			$groupId = ins_m(
				$GLOBALS['DBHOST_TBL_PREFIX'] .'groups',
				'name',
				0,
				array(
					_esc($groupName)
				)
			);
		}
			// Check wether user is in group and add it
		$r = db_all('SELECT id FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members WHERE group_id='. _esc($groupId) . ' AND user_id=' . _esc($userID));
		if(!count($r)) {
			ins_m(
				$GLOBALS['DBHOST_TBL_PREFIX'] .'group_members',
				'group_id, user_id',
				0,
				array(
					_esc($groupId) . ',' . _esc($userID)
				)
			);
		}
	}
		// remove groups which are removed in external adapter
	$list = '';
	foreach($groupNames as $groupName) {
		if($list !== '') {
			$list.= ', ';
		}
		$list.= _esc($groupName);
	}
	$q = '
		SELECT fud_group_members.id 
		FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members 
		LEFT JOIN '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups ON '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members.group_id = fud_groups.id
		WHERE '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members.user_id = ' . _esc($userID) . '
		AND '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups.name NOT IN (' . $list . ')
		AND '. $GLOBALS['DBHOST_TBL_PREFIX'] .'groups.name LIKE "SSO:%"
	';
	$groupsToRemove = db_all($q);
	if(count($groupsToRemove)) {
		foreach($groupsToRemove as $group) {
			echo $group;
			q('DELETE FROM '. $GLOBALS['DBHOST_TBL_PREFIX'] .'group_members WHERE id = ' . _esc($group));
		}
	}
}
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: RSS 2 Topic
Next Topic: list all smilies on the same page
Goto Forum:
  

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ]

Current Time: Wed Nov 27 17:15:20 GMT 2024

Total time taken to generate the page: 0.03104 seconds