jenkins-bot has submitted this change and it was merged.
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/SpecialCentralAutoLogin.php
M specials/SpecialCentralLogin.php
4 files changed, 97 insertions(+), 49 deletions(-)
Approvals:
Anomie: Looks good to me, approved
jenkins-bot: Verified
diff --git a/CentralAuthHooks.php b/CentralAuthHooks.php
index 9f6bbab..2e40bfa 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,9 @@
'secret' => $secret,
'name' => $centralUser->getName(),
'guid' => $centralUser->getId(),
- 'wikiId' => wfWikiId()
+ 'wikiId' => wfWikiId(),
+ 'finalProto' => $finalProto,
+ 'currentProto' => $request->detectProtocol()
);
$wgMemc->set( $key, $data, 60 );
diff --git a/CentralAuthUser.php b/CentralAuthUser.php
index 6d5e374..33821ab 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' );
@@ -2032,18 +2047,18 @@
$session = array();
$session['user'] = $this->mName;
- self::setCookie( 'User', $this->mName );
+ self::setCookie( 'User', $this->mName, -1, $secure );
$session['token'] = $this->getAuthToken();
$session['expiry'] = time() + 86400;
$session['auto-create-blacklist'] = array();
if ( $remember ) {
- self::setCookie( 'Token', $this->getAuthToken() );
+ self::setCookie( 'Token', $this->getAuthToken(), -1,
$secure );
} else {
$this->clearCookie( 'Token' );
}
- return self::setSession( $session, $refreshId );
+ return self::setSession( $session, $refreshId, $secure );
}
/**
@@ -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/SpecialCentralAutoLogin.php
b/specials/SpecialCentralAutoLogin.php
index 5e86505..7e61f03 100644
--- a/specials/SpecialCentralAutoLogin.php
+++ b/specials/SpecialCentralAutoLogin.php
@@ -138,10 +138,14 @@
return;
}
+ // Notify the attached wiki if cookies need to be
insecure
+ $centralSession = $centralUser->getSession();
+
// Write info for session creation into memc
$memcData += array(
'userName' => $centralUser->getName(),
'token' => $centralUser->getAuthToken(),
+ 'cookieProto' => $centralSession['finalProto'],
);
$wgMemc->set( $key, $memcData, 60 );
@@ -208,8 +212,13 @@
$_SESSION = $tmp;
}
- // Set central cookies too
- $centralUser->setGlobalCookies( false );
+ // Set central cookies too, with a refreshed sessionid.
Also, check if we
+ // need to override the default cookie security policy
+ $secureCookie = null;
+ if ( $memcData['cookieProto'] == 'http' ) {
+ $secureCookie = false;
+ }
+ $centralUser->setGlobalCookies( false, true,
$secureCookie );
// Now, figure out how to report this back to the user.
diff --git a/specials/SpecialCentralLogin.php b/specials/SpecialCentralLogin.php
index 370fccd..8fb04f3 100644
--- a/specials/SpecialCentralLogin.php
+++ b/specials/SpecialCentralLogin.php
@@ -75,14 +75,21 @@
// Delete the temporary token
$wgMemc->delete( $key );
+ // Determine if we can use the default cookie security, or if
we need
+ // to override it to insecure
+ $secureCookie = null;
+ if ( $info['finalProto'] == 'http' ) {
+ $secureCookie = false;
+ }
+
// 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).
$newSessionId = CentralAuthUser::setSession( array(
'pending_name' => $centralUser->getName(),
'pending_guid' => $centralUser->getId()
- ) );
- CentralAuthUser::setCookie( 'User', $centralUser->getName() );
+ ), true, $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,9 +103,13 @@
$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
protocol of the original
+ // login. If the local wiki is using wgSecureLogin, it will be
https.
+ $url = strstr( $url, '//' );
+ $url = $info['currentProto'] . ':' . $url;
if ( $wgCentralAuthSilentLogin ) {
- $this->getOutput()->redirect( // expands to
PROTO_CURRENT
+ $this->getOutput()->redirect( // expands to
PROTO_CURRENT if $url doesn't have protocol
wfAppendQuery( $url, array( 'token' => $token )
)
);
} else {
@@ -170,7 +181,20 @@
// 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'] );
+ // Without $wgSecureLogin, we should be on the correct protocol
now, and we use the
+ // default cookie security. With $wgSecureLogin, we use the
stickHTTPS checkbox.
+ $secureCookie = null;
+ if ( $wgSecureLogin && !$attempt['stickHTTPS'] ) {
+ $secureCookie = false;
+ }
+ $centralUser->setGlobalCookies( $_SESSION[$skey]['remember'],
$info['sessionId'], $secureCookie );
+
+ //Add to the session the target protocol of the login, so
autologin can use it
+ $centralSessionKey = CentralAuthUser::memcKey( 'session',
$info['sessionId'] );
+ $centralSession = $wgMemc->get( $centralSessionKey );
+ $centralSession['finalProto'] = $attempt['finalProto'];
+ $wgMemc->set( $centralSessionKey, $centralSession, 86400 );
+
// Remove the "current login attempt" information
$request->setSessionData( $skey, null );
@@ -180,40 +204,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: merged
Gerrit-Change-Id: I69de057244422c403cde50b9d1755e1dd55e1258
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/CentralAuth
Gerrit-Branch: master
Gerrit-Owner: CSteipp <[email protected]>
Gerrit-Reviewer: Aaron Schulz <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: CSteipp <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits