Seite 1 von 1

SingleSignOn

Verfasst: 03.02.2009 13:32
von kiwuff
Hallo,
ich habe phpBB3.0 auf einem Debianserver installiert, auf dem die Benutzer per Kerberos authentifiziert werden (mittels der Windowsanmeldung).
Der Benutzername wird vom Apache in der Variable $_SERVER['REMOTE_USER'] übergeben.
Gibt es eine einfache Möglichkeit, phpBB diese Authentifizierung verwenden zu lassen, ohne gleich wild an safemodes rumdrehen zu müssen (bzw. warum soll der safemode off sein für diese Authentifizierung)?
Des weiteren wäre schön, wenn bei bisher nichtexistierenden Benutzern diese direkt angelegt würden in der DB. Ein LDAP-Lookup wäre nicht so prickelnd, da das dahinterstehende AD ein wenig grösser ist - die Performance wäre hier wohl eher mies.

Gibt es da bereits fertige Lösungen, oder muss ich das selber anpassen? Wenn keine Lösung existiert, gibt es irgendwo einen Überblick, an welchen Stellen die Benutzerauthentifizierung angepasst werden müsste?

Wundert mich, das scheinbar bisher niemand dieses Anliegen hatte, zumindest habe ich nichts konkretes in der Suche finden können (wie gesagt, SSO ist Pflicht).

Any hints?

Danke für jede Hilfe,

kiwuff

Re: SingleSignOn

Verfasst: 04.02.2009 10:52
von kiwuff
Ok, hab mich reingewühlt und mir ein passendes Modul auth_sso.php in /includes/auth/ gebaut, bzw. von auth_apache.php abgleitet.
Benutzer werden neu angelegt, wenn noch nicht in der DB vorhanden, normales Login ist nicht mehr möglich (alle Benutzer werden ohne Passwort in der Datenbank gespeichert, daher wäre es schlecht, zusätzlich normalen Login zu erlauben).
In der Variablen $_SERVER['REMOTE_USER'] muss der von Apache (auf welche Art auch immer) authentifizierte Benutzer stehen, z.B.:

Benutzer@domäne.tld (wird von mod_auth_kerb unter Linux geliefert)
oder einfach
Benutzer

Wenn das GSSAPI-Modul unter Windows verwendet wird, muss der Code angepasst werden, statt:

Code: Alles auswählen

strtoupper(array_shift(explode('@',$_SERVER['REMOTE_USER'])))
muss es dann heissen:

Code: Alles auswählen

strtoupper(end(explode('\\',$_SERVER['REMOTE_USER'])))
(Das GSSAPI-Module liefert den authentifizierten Domänenbenutzer in der Form "Domäne.tld\Benutzer")

Das strtoupper dient nur dazu, die Benutzernamen konstant in Grossschreibung zu bekommen.. wer sich mal mit case-insensitiven Benuzternamen bei der Domänenanmeldung in Windows und Kerberosauthentifizierung rumgeprügelt hat, weiss warum. :-)

Damit der Login als Admin weiterhin funktioniert (ohne Login), muss noch die Datei index.php unter /adm angepasst werden:

Code: Alles auswählen

// Have they authenticated (again) as an admin for this session?
// if (!isset($user->data['session_admin']) || !$user->data['session_admin'])
// {
//      login_box('', $user->lang['LOGIN_ADMIN_CONFIRM'], $user->lang['LOGIN_ADMIN_SUCCESS'], true, false);
// }
.. also einfach die Loginbox auskommentieren.

Ein Problem bleibt noch: Es gibt dann leider keinen Adminaccount mehr (da ja kein Login mehr möglich ist). Es gibt 3 einfache Möglichkeiten, einen Domänenbenutzer als Admin einzutragen:
A.
Vor der Umstellung auf SSO einen Benutzer anlegen mit dem Namen des zukünftigen Domänenbenutzers, danach umstellen
B.
Auf SSO umstellen, dann Forum als Domänenbenuzter aufrufen, dann per Mysqlabfrage authentifizierung wieder auf db umstellen und
Domänenbenutzer Rechte zuweisen
C.
Auf SSO umstellen, dann Forum als Domänenbenutzer aufrufen, dann per Mysqlabfrage dem Domänenbenutzer die Berechtigungen zuweisen


So.. das wars erstmal. Hier noch die neu zugefügte Authentifizierungsdate auth_sso.php in /includes/auth:

Code: Alles auswählen


<?php
/**
* SSO-Login for phpBB3
*
*/

/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
        exit;
}

/**
* return boolean|string false if the user is identified and else an error message
*/
function init_kerb()
{
        global $user;

        if (!isset($_SERVER['REMOTE_USER']) || $user->data['username'] !== strtoupper(array_shift(explode('@',$_SERVER['REMOTE_USER'])))  )
        {
                return $user->lang['APACHE_SETUP_BEFORE_USE'];
        }
        return false;
}

/**
* Login function
*/
function login_kerb(&$username, &$password)
{
        global $db;
        // no normal login should be possible when using sso
        return array(
                'status'                => LOGIN_ERROR_EXTERNAL_AUTH,
                'error_msg'             => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE',
                'user_row'              => array('user_id' => ANONYMOUS),
        );
}

/**
* Autologin function
*
* @return array containing the user row or empty if no auto login should take place
*/
function autologin_kerb()
{
        global $db;

        if (!isset($_SERVER['REMOTE_USER']))
        {
                return array();
        }

        $php_auth_user = strtoupper(array_shift(explode('@',$_SERVER['REMOTE_USER'])));

        if (!empty($php_auth_user))
        {
                set_var($php_auth_user, $php_auth_user, 'string', true);

                $sql = 'SELECT *
                        FROM ' . USERS_TABLE . "
                        WHERE username = '" . $db->sql_escape($php_auth_user) . "'";
                $result = $db->sql_query($sql);
                $row = $db->sql_fetchrow($result);
                $db->sql_freeresult($result);

                if ($row)
                {
                        return ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE) ? array() : $row;
                }

                if (!function_exists('user_add'))
                {
                        global $phpbb_root_path, $phpEx;

                        include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
                }

                // create the user if he does not exist yet
                user_add(user_row_kerb($php_auth_user));

                $sql = 'SELECT *
                        FROM ' . USERS_TABLE . "
                        WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($php_auth_user)) . "'";
                $result = $db->sql_query($sql);
                $row = $db->sql_fetchrow($result);
                $db->sql_freeresult($result);

                if ($row)
                {
                        return $row;
                }
        }

        return array();
}

/**
* This function generates an array which can be passed to the user_add function in order to create a user
*/
function user_row_kerb($username)
{
        global $db, $config, $user;
        // first retrieve default group id
        $sql = 'SELECT group_id
                FROM ' . GROUPS_TABLE . "
                WHERE group_name = '" . $db->sql_escape('REGISTERED') . "'
                        AND group_type = " . GROUP_SPECIAL;
        $result = $db->sql_query($sql);
        $row = $db->sql_fetchrow($result);
        $db->sql_freeresult($result);

        if (!$row)
        {
                trigger_error('NO_GROUP');
        }

        // generate user account data
        return array(
                'username'              => $username,
                'user_password' => phpbb_hash(''),
                'user_email'    => '',
                'group_id'              => (int) $row['group_id'],
                'user_type'             => USER_NORMAL,
                'user_ip'               => $user->ip,
        );
}

/**
* The session validation function checks whether the user is still logged in
*
* @return boolean true if the given user is authenticated or false if the session should be closed
*/
function validate_session_kerb(&$user)
{
        if (!isset($_SERVER['REMOTE_USER']))
        {
                return false;
        }

        $php_auth_user = '';
        set_var($php_auth_user, strtoupper(array_shift(explode('@',$_SERVER['REMOTE_USER']))), 'string', true);

        return ($php_auth_user === $user['username']) ? true : false;
}
Edit:

Da man den Logout-Button nicht mehr braucht (bzw. der ja logischerweise nicht mehr funktionieren kann), macht es Sinn, das Biest auch zu entfernen:
Dazu in /styles/<<stylename>>/template/overall_header.html den Link rausnehmen (nach U_LOGIN_LOGOUT suchen).

Re: SingleSignOn

Verfasst: 29.05.2009 16:30
von kiwuff
Kann den Beitrag nicht mehr editieren, darum hier noch eine Korrektur:

Die Funktionsnamen in auth_sso.php müssen noch angepasst werden:
Statt init_kerb() muss es init_sso() heissen, statt login_kerb() login_sso() usw.