From 3d32e12a1fc99540302ae87de3d0afa6b72f6cc2 Mon Sep 17 00:00:00 2001 From: Ryan Lerch Date: Mon, 22 May 2023 13:16:21 +1000 Subject: [PATCH] [wiki] Remove old patched openIDConnect, and comment about new setup We previously moved the FPCA check from a patched file held here in ansible into the RPM itself when it was built for the Fedora infra repos. While we no longer installed the patched file, it remained here in the files dir of the wiki role, so we are deleting it. Also, have added a comment to the play to say where we are holding this patch now, so when i forget about it again, and come back to it in another year or so, i can remember faster Signed-off-by: Ryan Lerch --- roles/mediawiki/files/OpenIDConnect.php | 496 ------------------------ roles/mediawiki/tasks/main.yml | 3 + 2 files changed, 3 insertions(+), 496 deletions(-) delete mode 100644 roles/mediawiki/files/OpenIDConnect.php diff --git a/roles/mediawiki/files/OpenIDConnect.php b/roles/mediawiki/files/OpenIDConnect.php deleted file mode 100644 index 4798f23698..0000000000 --- a/roles/mediawiki/files/OpenIDConnect.php +++ /dev/null @@ -1,496 +0,0 @@ -get( 'iss' ); - - if ( $iss !== null ) { - - if ( isset( $_REQUEST['code'] ) && isset( $_REQUEST['status'] ) ) { - $session->remove( 'iss' ); - } - - if ( isset( $GLOBALS['wgOpenIDConnect_Config'][$iss] ) ) { - - $config = $GLOBALS['wgOpenIDConnect_Config'][$iss]; - - if ( !isset( $config['clientID'] ) || - !isset( $config['clientsecret'] ) ) { - wfDebugLog( 'OpenID Connect', - 'OpenID Connect: clientID or clientsecret not set for ' . $iss . - '.' . PHP_EOL ); - $params = [ - 'uri' => urlencode( $_SERVER['REQUEST_URI'] ), - 'query' => urlencode( $_SERVER['QUERY_STRING'] ) - ]; - self::redirect( 'Special:SelectOpenIDConnectIssuer', - $params, true ); - return false; - } - - } else { - wfDebugLog( 'OpenID Connect', 'Issuer ' . $iss . - ' does not exist in wgOpeIDConnect_Config.' . PHP_EOL ); - return false; - } - - } else { - - $iss_count = count( $GLOBALS['wgOpenIDConnect_Config'] ); - - if ( $iss_count < 1 ) { - return false; - } - - if ( $iss_count == 1 ) { - - $iss = array_keys( $GLOBALS['wgOpenIDConnect_Config'] ); - $iss = $iss[0]; - - $values = array_values( $GLOBALS['wgOpenIDConnect_Config'] ); - $config = $values[0]; - - if ( !isset( $config['clientID'] ) || - !isset( $config['clientsecret'] ) ) { - wfDebugLog( 'OpenID Connect', - 'OpenID Connect: clientID or clientsecret not set for ' . - $iss . '.' . PHP_EOL ); - return false; - } - - } else { - - $params = [ - 'uri' => urlencode( $_SERVER['REQUEST_URI'] ), - 'query' => urlencode( $_SERVER['QUERY_STRING'] ) - ]; - self::redirect( 'Special:SelectOpenIDConnectIssuer', - $params, true ); - return false; - } - } - - $clientID = $config['clientID']; - $clientsecret = $config['clientsecret']; - - $oidc = new OpenIDConnectClient( $iss, $clientID, $clientsecret ); - if ( isset( $_REQUEST['forcelogin'] ) ) { - $oidc->addAuthParam( [ 'prompt' => 'login' ] ); - } - if ( isset( $config['authparam'] ) && - is_array( $config['authparam'] ) ) { - $oidc->addAuthParam( $config['authparam'] ); - } - if ( isset( $config['scope'] ) ) { - $scope = $config['scope']; - if ( is_array( $scope ) ) { - foreach ( $scope as $s ) { - $oidc->addScope( $s ); - } - } else { - $oidc->addScope( $scope ); - } - } - if ( isset( $config['proxy'] ) ) { - $oidc->setHttpProxy( $config['proxy'] ); - } - if ( isset( $config['verifyHost'] ) ) { - $oidc->setVerifyHost( $config['verifyHost'] ); - } - if ( isset( $config['verifyPeer'] ) ) { - $oidc->setVerifyPeer( $config['verifyPeer'] ); - } - $redirectURL = - SpecialPage::getTitleFor( 'PluggableAuthLogin' )->getFullURL(); - $oidc->setRedirectURL( $redirectURL ); - wfDebugLog( 'OpenID Connect', 'Redirect URL: ' . $redirectURL ); - if ( $oidc->authenticate() ) { - - if(!in_array("signed_fpca", $oidc->requestUserInfo('groups'))) { - $errorMessage = 'You need to have signed the FPCA'; - return false; - } - /* - * Enable the following block to require the equivalent of CLA+1 - * - if(!in_array("fedora-contributor", $oidc->requestUserInfo('groups'))) { - $errorMessage = 'You need to be in at least one group'; - return false; - } - */ - - $realname = $oidc->requestUserInfo( 'name' ); - $email = $oidc->requestUserInfo( 'email' ); - $this->subject = $oidc->requestUserInfo( 'sub' ); - $this->issuer = $oidc->getProviderURL(); - wfDebugLog( 'OpenID Connect', 'Real name: ' . $realname . - ', Email: ' . $email . ', Subject: ' . $this->subject . - ', Issuer: ' . $this->issuer ); - - list( $id, $username ) = - $this->findUser( $this->subject, $this->issuer ); - if ( $id !== null ) { - wfDebugLog( 'OpenID Connect', - 'Found user with matching subject and issuer.' . PHP_EOL ); - return true; - } - - wfDebugLog( 'OpenID Connect', - 'No user found with matching subject and issuer.' . PHP_EOL ); - - if ( $GLOBALS['wgOpenIDConnect_MigrateUsersByEmail'] === true ) { - wfDebugLog( 'OpenID Connect', 'Checking for email migration.' . - PHP_EOL ); - list( $id, $username ) = $this->getMigratedIdByEmail( $email ); - if ( $id !== null ) { - $this->saveExtraAttributes( $id ); - wfDebugLog( 'OpenID Connect', 'Migrated user ' . $username . - ' by email: ' . $email . '.' . PHP_EOL ); - return true; - } - } - - $preferred_username = $this->getPreferredUsername( $config, $oidc, - $realname, $email ); - wfDebugLog( 'OpenID Connect', 'Preferred username: ' . - $preferred_username . PHP_EOL ); - - if ( $GLOBALS['wgOpenIDConnect_MigrateUsersByUserName'] === true ) { - wfDebugLog( 'OpenID Connect', 'Checking for username migration.' . - PHP_EOL ); - $id = $this->getMigratedIdByUserName( $preferred_username ); - if ( $id !== null ) { - $this->saveExtraAttributes( $id ); - wfDebugLog( 'OpenID Connect', 'Migrated user by username: ' . - $preferred_username . '.' . PHP_EOL ); - $username = $preferred_username; - return true; - } - } - - $username = self::getAvailableUsername( $preferred_username, - $realname, $email ); - - wfDebugLog( 'OpenID Connect', 'Available username: ' . - $username . PHP_EOL ); - - $authManager = Authmanager::singleton(); - $authManager->setAuthenticationSessionData( - self::OIDC_SUBJECT_SESSION_KEY, $this->subject ); - $authManager->setAuthenticationSessionData( - self::OIDC_ISSUER_SESSION_KEY, $this->issuer ); - return true; - } - - } catch ( Exception $e ) { - wfDebugLog( 'OpenID Connect', $e->__toString() . PHP_EOL ); - $errorMessage = $e->__toString(); - $session->clear(); - return false; - } - } - - /** - * @since 1.0 - * - * @param User &$user - */ - public function deauthenticate( User &$user ) { - if ( $GLOBALS['wgOpenIDConnect_ForceLogout'] === true ) { - $returnto = 'Special:UserLogin'; - $params = [ 'forcelogin' => 'true' ]; - self::redirect( $returnto, $params ); - } - } - - /** - * @since 1.0 - * - * @param int $id user id - */ - public function saveExtraAttributes( $id ) { - $authManager = Authmanager::singleton(); - if ( $this->subject === null ) { - $this->subject = $authManager->getAuthenticationSessionData( - self::OIDC_SUBJECT_SESSION_KEY ); - $authManager->removeAuthenticationSessionData( - self::OIDC_SUBJECT_SESSION_KEY ); - } - if ( $this->issuer === null ) { - $this->issuer = $authManager->getAuthenticationSessionData( - self::OIDC_ISSUER_SESSION_KEY ); - $authManager->removeAuthenticationSessionData( - self::OIDC_ISSUER_SESSION_KEY ); - } - $dbw = wfGetDB( DB_MASTER ); - $dbw->upsert( - 'openid_connect', - [ - 'oidc_user' => $id, - 'oidc_subject' => $this->subject, - 'oidc_issuer' => $this->issuer - ], - [ - [ 'oidc_user' ] - ], - [ - 'oidc_subject' => $this->subject, - 'oidc_issuer' => $this->issuer - ], - __METHOD__ - ); - } - - private static function findUser( $subject, $issuer ) { - $dbr = wfGetDB( DB_REPLICA ); - $row = $dbr->selectRow( - [ - 'user', - 'openid_connect' - ], - [ - 'user_id', - 'user_name' - ], - [ - 'oidc_subject' => $subject, - 'oidc_issuer' => $issuer - ], - __METHOD__, - [], - [ - 'openid_connect' => [ 'JOIN', [ 'user_id=oidc_user' ] ] - ] - ); - if ( $row === false ) { - return [ null, null ]; - } else { - return [ $row->user_id, $row->user_name ]; - } - } - - private static function getPreferredUsername( $config, $oidc, $realname, - $email ) { - if ( isset( $config['preferred_username'] ) ) { - wfDebugLog( 'OpenID Connect', 'Using ' . $config['preferred_username'] . - ' attribute for preferred username.' . PHP_EOL ); - $preferred_username = - $oidc->requestUserInfo( $config['preferred_username'] ); - } else { - $preferred_username = $oidc->requestUserInfo( 'preferred_username' ); - } - if ( strlen( $preferred_username ) > 0 ) { - // do nothing - } elseif ( strlen( $realname ) > 0 && - $GLOBALS['wgOpenIDConnect_UseRealNameAsUserName'] === true ) { - $preferred_username = $realname; - } elseif ( strlen( $email ) > 0 && - $GLOBALS['wgOpenIDConnect_UseEmailNameAsUserName'] === true ) { - $pos = strpos( $email, '@' ); - if ( $pos !== false && $pos > 0 ) { - $preferred_username = substr( $email, 0, $pos ); - } else { - $preferred_username = $email; - } - } else { - return null; - } - $nt = Title::makeTitleSafe( NS_USER, $preferred_username ); - if ( $nt === null ) { - return null; - } - return $nt->getText(); - } - - private static function getMigratedIdByUserName( $username ) { - $nt = Title::makeTitleSafe( NS_USER, $username ); - if ( $nt === null ) { - wfDebugLog( 'OpenID Connect', - 'Invalid preferred username for migration: ' . $username . '.' . - PHP_EOL ); - return null; - } - $username = $nt->getText(); - $dbr = wfGetDB( DB_REPLICA ); - $row = $dbr->selectRow( - [ - 'user', - 'openid_connect' - ], - [ - 'user_id' - ], - [ - 'user_name' => $username, - 'oidc_user' => null - ], - __METHOD__, - [], - [ - 'openid_connect' => [ 'LEFT JOIN', [ 'user_id=oidc_user' ] ] - ] - ); - if ( $row !== false ) { - return $row->user_id; - } - return null; - } - - private static function getMigratedIdByEmail( $email ) { - wfDebugLog( 'OpenID Connect', 'Matching user to email ' . $email . '.' . - PHP_EOL ); - $dbr = wfGetDB( DB_REPLICA ); - $row = $dbr->selectRow( - [ - 'user', - 'openid_connect' - ], - [ - 'user_id', - 'user_name', - 'oidc_user' - ], - [ - 'user_email' => $email - ], - __METHOD__, - [ - // if multiple matching accounts, use the oldest one - 'ORDER BY' => 'user_registration' - ], - [ - 'openid_connect' => [ 'LEFT JOIN', [ 'user_id=oidc_user' ] ] - ] - ); - if ( $row !== false && $row->oidc_user === null ) { - return [ $row->user_id, $row->user_name ]; - } - return [ null, null ]; - } - - private static function getAvailableUsername( $preferred_username ) { - if ( $preferred_username === null ) { - $preferred_username = 'User'; - } - - if ( User::idFromName( $preferred_username ) === null ) { - return $preferred_username; - } - - $count = 1; - while ( User::idFromName( $preferred_username . $count ) !== null ) { - $count++; - } - return $preferred_username . $count; - } - - private static function redirect( $page, $params = [], $doExit = false ) { - $title = Title::newFromText( $page ); - if ( $title === null ) { - $title = Title::newMainPage(); - } - $url = $title->getFullURL( $params ); - header( 'Location: ' . $url ); - if ( $doExit ) { - exit; - } - } - - /** - * Implements LoadExtensionSchemaUpdates hook. - * - * @param DatabaseUpdater $updater - */ - public static function loadExtensionSchemaUpdates( $updater ) { - $dir = $GLOBALS['wgExtensionDirectory'] . '/OpenIDConnect/sql/'; - $type = $updater->getDB()->getType(); - $updater->addExtensionTable( 'openid_connect', - $dir . $type . '/AddTable.sql' ); - $updater->addExtensionUpdate( [ [ __CLASS__, 'migrateSubjectAndIssuer' ], - $updater ] ); - } - - /** - * Migrate subject and issuer columns from user table to openid_connect - * table. - * - * @param DatabaseUpdater $updater - */ - public static function migrateSubjectAndIssuer( $updater ) { - if ( $updater->getDB()->fieldExists( 'user', 'subject', __METHOD__ ) && - $updater->getDB()->fieldExists( 'user', 'issuer', __METHOD__ ) ) { - $maintenance = new FakeMaintenance(); - $task = $maintenance->runChild( - 'MigrateOIDCSubjectAndIssuerFromUserTable' ); - if ( $task->execute() ) { - $dir = $GLOBALS['wgExtensionDirectory'] . '/OpenIDConnect/sql/'; - $type = $updater->getDB()->getType(); - $patch = $dir . $type . '/DropColumnsFromUserTable.sql'; - $updater->modifyField( 'user', 'subject', $patch, true ); - } - } else { - $updater->output( - '...user table does not have subject and issuer columns.' . PHP_EOL ); - } - } -} diff --git a/roles/mediawiki/tasks/main.yml b/roles/mediawiki/tasks/main.yml index ac3e908888..0df1c4f40f 100644 --- a/roles/mediawiki/tasks/main.yml +++ b/roles/mediawiki/tasks/main.yml @@ -51,6 +51,9 @@ - packages - mediawiki +# mediawiki-OpenIDConnect here is pulled from the infra repo, which is also patched to add +# the FPCA check, and returns the message to the user: +# "You need to have signed the FPCA to log into the wiki" - name: install needed packages (fedora only) package: name={{ item }} state=present with_items: