Page MenuHomeWickedGov Phorge

SharedDomainUtils.php
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None

SharedDomainUtils.php

<?php
namespace MediaWiki\Extension\CentralAuth;
use MediaWiki\Config\Config;
use MediaWiki\Extension\CentralAuth\Hooks\Handlers\SsoHookHandler;
use MediaWiki\Request\WebRequest;
use MediaWiki\Title\TitleFactory;
use MediaWiki\WikiMap\WikiMap;
use MobileContext;
use RuntimeException;
use Wikimedia\Assert\Assert;
/**
* Utilities for handling the shared domain name used for SUL3 login.
* This class is kept lightweight, so it can be used in early hooks.
*/
class SharedDomainUtils {
private const SUL3_COOKIE_FLAG = 'sul3OptIn';
private Config $config;
private TitleFactory $titleFactory;
private bool $isSharedDomain;
private ?MobileContext $mobileContext = null;
public function __construct(
Config $config,
TitleFactory $titleFactory,
?MobileContext $mobileContext = null
) {
$this->config = $config;
$this->titleFactory = $titleFactory;
$this->mobileContext = $mobileContext;
}
/**
* Whether the current request is to the shared domain used for SUL3 login.
*
* This assumes:
* - $wgCentralAuthSsoUrlPrefix contains the shared domain.
* - $wgCanonicalServer is set in site configuration to the current domain
* (instead of the actual canonical domain) for requests to the shared domain.
*
* @return bool
*/
public function isSharedDomain(): bool {
// @phan-suppress-next-line PhanRedundantCondition
if ( !isset( $this->isSharedDomain ) ) {
$centralAuthSsoUrlPrefix = $this->config->get( 'CentralAuthSsoUrlPrefix' );
if ( !$centralAuthSsoUrlPrefix ) {
$this->isSharedDomain = false;
} else {
$sharedDomain = parse_url( $centralAuthSsoUrlPrefix, PHP_URL_HOST );
$currentDomain = parse_url( $this->config->get( 'CanonicalServer' ), PHP_URL_HOST );
$this->isSharedDomain = $sharedDomain && $currentDomain === $sharedDomain;
}
}
return $this->isSharedDomain;
}
/**
* Whether the current request must deny non-auth actions.
*
* If $wgCentralAuthRestrictSsoDomain is enabled, then requests to the "fake"
* shared domain within $wgCentralAuthSsoUrlPrefix must only be for authentication
* purposes. All non-authentication-related actions should be prevented.
*
* SUL3 login supports both using a dedicated login wiki for the domain where the central
* session cookies are stored, and a shared domain which serve any wiki (from a virtual
* sub directory). In the latter case, we want to prevent non-authentication actions
* to prevent complications like cache splits. This flag differentiates between the two
* setups.
*
* @return bool
* @see SsoHookHandler
*/
public function shouldRestrictCurrentDomain(): bool {
return $this->isSharedDomain() && $this->config->get( 'CentralAuthRestrictSsoDomain' );
}
/**
* Whether SUL3 mode is enabled on this wiki and/or this request.
*
* In order to facilitate testing of SUL3 migration, this method
* provides mechanisms for testing the SUL3 feature including a
* cookie-based feature flag.
*
* SUL3 mode is enabled if any of the following conditions is true:
* - $wgCentralAuthEnableSul3 contains 'always'
* - $wgCentralAuthEnableSul3 contains 'cookie' and there is a
* cookie named 'sul3OptIn' with the value '1'
* - $wgCentralAuthEnableSul3 contains 'query-flag' and the URL has
* a query parameter 'usesul3' with a truthy value
*
* @param WebRequest $request
* @return bool
*/
public function isSul3Enabled( WebRequest $request ): bool {
$sul3Config = $this->config->get( 'CentralAuthEnableSul3' );
// For B/C, this config was a string before. Now that we're moving
// to an array based value, we need to support both while migrating.
// TEMPORARY: Remove this code below once migration is complete.
if ( $sul3Config === false ) {
$sul3Config = [];
} elseif ( !is_array( $sul3Config ) ) {
$sul3Config = [ $sul3Config ];
}
if ( in_array( 'always', $sul3Config, true ) ) {
return true;
} elseif ( in_array( 'cookie', $sul3Config, true )
&& $request->getCookie( self::SUL3_COOKIE_FLAG, '' ) === '1'
) {
return true;
} elseif ( in_array( 'query-flag', $sul3Config, true )
&& $request->getCheck( 'usesul3' )
) {
return true;
} else {
return false;
}
}
/**
* Assert that the SUL3 mode is allowed.
*
* @param WebRequest $request
* @return void
*/
public function assertSul3Enabled( WebRequest $request ) {
Assert::precondition(
$this->isSul3Enabled( $request ),
'SUL3 is not enabled. Set $wgCentralAuthEnableSul3 to boolean true.'
);
}
/**
* Assert that we're on the shared login domain.
*
* @return void
*/
public function assertIsSharedDomain() {
Assert::precondition(
$this->isSharedDomain(),
'This action is not allowed because the domain is not the shared login domain.'
);
}
/**
* Assert that we're not on the shared login domain.
*
* @return void
*/
public function assertIsNotSharedDomain() {
Assert::precondition(
!( $this->isSharedDomain() ),
'This action is not allowed because the domain is not the shared login domain.'
);
}
/**
* Get the login/signup URL on the shared login domain wiki.
*
* @param string $action 'login' or 'signup' action
* @param WebRequest|null $request There could be more to look at
* in the request like if we're coming from a campaign link.
*
* @return string
*/
public function getUrlForSharedDomainAction( string $action, ?WebRequest $request = null ): string {
switch ( $action ) {
case 'login':
$localUrl = $this->titleFactory->newFromText( 'Special:UserLogin' )->getLocalURL();
break;
case 'signup':
$localUrl = $this->titleFactory->newFromText( 'Special:CreateAccount' )->getLocalURL();
break;
default:
throw new RuntimeException( 'Unknown action: ' . $action );
}
$url = $this->config->get( 'CentralAuthSsoUrlPrefix' ) . $localUrl;
if ( $this->mobileContext && $this->mobileContext->shouldDisplayMobileView() ) {
$url = wfAppendQuery( $url, [ 'useformat' => 'mobile' ] );
} else {
// This is not supposed to happen on the SSO domain but if we're
// in a situation where the shared domain is in mobile view and the
// user is coming from a desktop view, let's inherit that experience
// to the shared domain.
$url = wfAppendQuery( $url, [ 'useformat' => 'desktop' ] );
}
return wfAppendQuery( $url, [
// At this point, we should just be leaving the local
// wiki before hitting the loginwiki.
'wikiid' => WikiMap::getCurrentWikiId(),
// TODO: Fix T369467
'returnto' => 'Main_Page',
'usesul3' => '1',
'campaign' => $request ? $request->getRawVal( 'campaign' ) : null,
] );
}
}

File Metadata

Mime Type
text/x-php
Expires
Sat, May 16, 19:12 (5 h, 39 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
d9/cd/da14b07ce4b6cc42e4d2c0d24e21
Default Alt Text
SharedDomainUtils.php (6 KB)

Event Timeline