CSteipp has uploaded a new change for review.
https://gerrit.wikimedia.org/r/72657
Change subject: Redirect to correct protocol in SUL2
......................................................................
Redirect to correct protocol in SUL2
Handles situations where:
* The wiki has wgSecureLogin enabled, but the user opts-out of SSL
* The user logs in over http
bug: 50334
Change-Id: I69de057244422c403cde50b9d1755e1dd55e1258
---
M CentralAuthHooks.php
M CentralAuthUser.php
M specials/SpecialCentralLogin.php
3 files changed, 74 insertions(+), 44 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/CentralAuth
refs/changes/57/72657/1
diff --git a/CentralAuthHooks.php b/CentralAuthHooks.php
index 9f6bbab..574aba3 100644
--- a/CentralAuthHooks.php
+++ b/CentralAuthHooks.php
@@ -379,7 +379,7 @@
* @return bool
*/
protected static function doCentralLoginRedirect( User $user,
CentralAuthUser $centralUser, &$inject_html ) {
- global $wgCentralAuthLoginWiki, $wgMemc;
+ global $wgCentralAuthLoginWiki, $wgMemc, $wgSecureLogin;
$context = RequestContext::getMain();
$request = $context->getRequest();
@@ -404,6 +404,12 @@
$returnToQuery = '';
}
+ // Determine the final protocol of page, after login
+ $finalProto = $request->detectProtocol();
+ if ( $wgSecureLogin ) {
+ $finalProto = $request->getCheck(
'wpStickHTTPS' ) ? 'https' : 'http';
+ }
+
// When POSTs triggered from Special:CentralLogin/start
are sent back to
// this wiki, the token will be checked to see if it
was signed with this.
// This is needed as Special:CentralLogin/start only
takes a token argument
@@ -415,7 +421,8 @@
'remember' => $request->getCheck(
'wpRemember' ),
'returnTo' => $returnTo,
'returnToQuery' => $returnToQuery,
- 'stickHTTPS' => $request->getCheck(
'wpStickHTTPS' )
+ 'stickHTTPS' => $request->getCheck(
'wpStickHTTPS' ),
+ 'finalProto' => $finalProto
);
// Create a new token to pass to
Special:CentralLogin/start (central wiki)
@@ -425,7 +432,8 @@
'secret' => $secret,
'name' => $centralUser->getName(),
'guid' => $centralUser->getId(),
- 'wikiId' => wfWikiId()
+ 'wikiId' => wfWikiId(),
+ 'finalProto' => $finalProto
);
$wgMemc->set( $key, $data, 60 );
diff --git a/CentralAuthUser.php b/CentralAuthUser.php
index 6d5e374..8191115 100644
--- a/CentralAuthUser.php
+++ b/CentralAuthUser.php
@@ -1970,9 +1970,13 @@
* @param $name
* @param $value
* @param $exp
+ * @param bool $secure
+ * true: Force setting the secure attribute when setting the cookie
+ * false: Force NOT setting the secure attribute when setting the
cookie
+ * null (default): Use the default ($wgCookieSecure) to set the secure
attribute
* @return void
*/
- static function setCookie( $name, $value, $exp = -1 ) {
+ static function setCookie( $name, $value, $exp = -1, $secure = null ) {
global $wgCentralAuthCookiePrefix, $wgCentralAuthCookieDomain,
$wgCookieSecure,
$wgCookieExpiration, $wgCookieHttpOnly;
@@ -1991,12 +1995,19 @@
// Relative expiry
$exp += time();
}
+
+ // Set the cookie encryption requirements
+ $secureCookie = $secure;
+ if ( is_null( $secure ) ) {
+ $secureCookie = $wgCookieSecure;
+ }
+
setcookie( $wgCentralAuthCookiePrefix . $name,
$value,
$exp,
'/',
$wgCentralAuthCookieDomain,
- $wgCookieSecure,
+ $secureCookie,
$wgCookieHttpOnly );
}
@@ -2022,9 +2033,13 @@
*
* @param $remember Bool|User
* @param $refreshId Bool|string
+ * @param bool $secure
+ * true: Force setting the secure attribute when setting the cookie
+ * false: Force NOT setting the secure attribute when setting the
cookie
+ * null (default): Use the default ($wgCookieSecure) to set the secure
attribute
* @return string Session ID
*/
- function setGlobalCookies( $remember = false, $refreshId = false ) {
+ function setGlobalCookies( $remember = false, $refreshId = false,
$secure = null ) {
if ( $remember instanceof User ) {
// Older code passed a user object here. Be kind and do
what they meant to do.
$remember = $remember->getOption( 'rememberpassword' );
@@ -2038,7 +2053,7 @@
$session['auto-create-blacklist'] = array();
if ( $remember ) {
- self::setCookie( 'Token', $this->getAuthToken() );
+ self::setCookie( 'Token', $this->getAuthToken(),
$secure );
} else {
$this->clearCookie( 'Token' );
}
@@ -2363,16 +2378,20 @@
*
* @param $data Array
* @param $refreshId Bool|String
+ * @param bool $secure
+ * true: Force setting the secure attribute when setting the cookie
+ * false: Force NOT setting the secure attribute when setting the
cookie
+ * null (default): Use the default ($wgCookieSecure) to set the secure
attribute
* @return string Session ID
*/
- static function setSession( $data, $refreshId = false ) {
+ static function setSession( $data, $refreshId = false, $secure = null )
{
global $wgCentralAuthCookies, $wgCentralAuthCookiePrefix,
$wgMemc;
if ( !$wgCentralAuthCookies ) {
return null;
}
if ( $refreshId || !isset( $_COOKIE[$wgCentralAuthCookiePrefix
. 'Session'] ) ) {
$id = is_string( $refreshId ) ? $refreshId :
MWCryptRand::generateHex( 32 );
- self::setCookie( 'Session', $id, 0 );
+ self::setCookie( 'Session', $id, 0, $secure );
} else {
$id = $_COOKIE[$wgCentralAuthCookiePrefix . 'Session'];
}
diff --git a/specials/SpecialCentralLogin.php b/specials/SpecialCentralLogin.php
index 370fccd..839e147 100644
--- a/specials/SpecialCentralLogin.php
+++ b/specials/SpecialCentralLogin.php
@@ -78,11 +78,12 @@
// Start an unusable placeholder session stub and send a cookie.
// The cookie will not be usable until the session is unstubbed.
// Note: the "remember me" token must be dealt with later
(security).
+ $secureCookie = ( $info['finalProto'] !== 'http' );
$newSessionId = CentralAuthUser::setSession( array(
'pending_name' => $centralUser->getName(),
'pending_guid' => $centralUser->getId()
- ) );
- CentralAuthUser::setCookie( 'User', $centralUser->getName() );
+ ), false, $secureCookie );
+ CentralAuthUser::setCookie( 'User', $centralUser->getName(),
-1, $secureCookie );
// Create a new token to pass to Special:CentralLogin/complete
(local wiki).
$token = MWCryptRand::generateHex( 32 );
@@ -96,6 +97,9 @@
$wiki = WikiMap::getWiki( $info['wikiId'] );
// Use WikiReference::getFullUrl(), returns a protocol-relative
URL if needed
$url = $wiki->getFullUrl( 'Special:CentralLogin/complete' );
+ // Ensure $url really is proto relative, and prepend the user's
requested protocol
+ $url = strstr( $url, '//' );
+ $url = $info['finalProto'] . ':' . $url;
if ( $wgCentralAuthSilentLogin ) {
$this->getOutput()->redirect( // expands to
PROTO_CURRENT
@@ -155,6 +159,17 @@
return;
}
+ // For sanity, make sure we're on the right protocol. This
shouldn't happen, but not
+ // really exception worthy either
+ if ( $attempt['finalProto'] !== $request->detectProtocol() ) {
+ $wiki = wfWikiId();
+ wfDebugLog( 'CentralAuth', __METHOD__ . ": wrong
protocol {$request->detectProtocol()}, expecting {$attempt['finalProto']} on
$wiki" );
+ $query = array( 'token' => $token );
+ $url = $this->getFullTitle()->getFullUrl( $query,
false, PROTO_HTTP );
+ $this->getOutput()->redirect( $url );
+ return;
+ }
+
$user = User::newFromName( $request->getSessionData(
'wsUserName' ) );
if ( !$user->getId() ) { // sanity
throw new MWException( "The user account logged into
does not exist." );
@@ -170,7 +185,8 @@
// Fully initialize the stub central user session and send the
domain cookie.
// This lets User::loadFromSession to initialize the User
object from the local
// session now that the global session is complete.
- $centralUser->setGlobalCookies( $_SESSION[$skey]['remember'],
$info['sessionId'] );
+ $secureCookie = ( $attempt['finalProto'] !== 'http' );
+ $centralUser->setGlobalCookies( $_SESSION[$skey]['remember'],
$info['sessionId'], $secureCookie );
// Remove the "current login attempt" information
$request->setSessionData( $skey, null );
@@ -180,40 +196,27 @@
// which is needed or the personal links will be wrong.
$this->getContext()->setUser( $user );
- if ( $wgSecureLogin
- && WebRequest::detectProtocol() === 'https' &&
!$attempt['stickHTTPS'] )
- {
- // The user wants an HTTP redirect link (as well as
other links) and
- // this is on HTTPS, so send a redirect to the success
page in HTTP.
- $query = array(
- 'returnto' => $attempt['returnTo'],
- 'returntoquery' => $attempt['returnToQuery']
- );
- $url = $this->getFullTitle()->getFullUrl( $query,
false, PROTO_HTTP );
- $this->getOutput()->redirect( $url );
+ if ( $wgCentralAuthSilentLogin ) {
+ // Mark the session to include the edge login imgs on
the next pageview
+ $request->setSessionData( 'CentralAuthDoEdgeLogin',
true );
+
+ // Show the login success page
+ $form = new LoginForm( new FauxRequest() );
+ $form->showReturnToPage( 'successredirect',
+ $attempt['returnTo'],
$attempt['returnToQuery'], $attempt['stickHTTPS'] );
+ $this->getOutput()->setPageTitle( $this->msg(
'centralloginsuccesful' ) );
} else {
- if ( $wgCentralAuthSilentLogin ) {
- // Mark the session to include the edge login
imgs on the next pageview
- $request->setSessionData(
'CentralAuthDoEdgeLogin', true );
+ // Show the login success page
+ $form = new LoginForm( new FauxRequest() );
+ $form->showReturnToPage( 'success',
+ $attempt['returnTo'],
$attempt['returnToQuery'], $attempt['stickHTTPS'] );
+ $this->getOutput()->setPageTitle( $this->msg(
'centralloginsuccesful' ) );
- // Show the login success page
- $form = new LoginForm( new FauxRequest() );
- $form->showReturnToPage( 'successredirect',
- $attempt['returnTo'],
$attempt['returnToQuery'], $attempt['stickHTTPS'] );
- $this->getOutput()->setPageTitle( $this->msg(
'centralloginsuccesful' ) );
- } else {
- // Show the login success page
- $form = new LoginForm( new FauxRequest() );
- $form->showReturnToPage( 'success',
- $attempt['returnTo'],
$attempt['returnToQuery'], $attempt['stickHTTPS'] );
- $this->getOutput()->setPageTitle( $this->msg(
'centralloginsuccesful' ) );
-
- // Show HTML to trigger cross-domain cookies.
- // This will trigger filling in the "remember
me" token cookie on the
- // central wiki, which can only be done once
authorization is completed.
- $this->getOutput()->addHtml(
-
CentralAuthHooks::getDomainAutoLoginHtml( $user, $centralUser ) );
- }
+ // Show HTML to trigger cross-domain cookies.
+ // This will trigger filling in the "remember me" token
cookie on the
+ // central wiki, which can only be done once
authorization is completed.
+ $this->getOutput()->addHtml(
+ CentralAuthHooks::getDomainAutoLoginHtml(
$user, $centralUser ) );
}
}
--
To view, visit https://gerrit.wikimedia.org/r/72657
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I69de057244422c403cde50b9d1755e1dd55e1258
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/CentralAuth
Gerrit-Branch: master
Gerrit-Owner: CSteipp <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits