8 use Wikimedia\TestingAccessWrapper;
18 return new \HashConfig( [
19 'CookiePrefix' =>
'CookiePrefix',
20 'CookiePath' =>
'CookiePath',
21 'CookieDomain' =>
'CookieDomain',
22 'CookieSecure' =>
true,
23 'CookieHttpOnly' =>
true,
24 'SessionName' =>
false,
25 'CookieExpiration' => 100,
26 'ExtendedLoginCookieExpiration' => 200,
33 $this->fail(
'Expected exception not thrown' );
34 }
catch ( \InvalidArgumentException $ex ) {
36 'MediaWiki\\Session\\CookieSessionProvider::__construct: priority must be specified',
43 $this->fail(
'Expected exception not thrown' );
44 }
catch ( \InvalidArgumentException $ex ) {
46 'MediaWiki\\Session\\CookieSessionProvider::__construct: Invalid priority',
52 $this->fail(
'Expected exception not thrown' );
53 }
catch ( \InvalidArgumentException $ex ) {
55 'MediaWiki\\Session\\CookieSessionProvider::__construct: Invalid priority',
61 $this->fail(
'Expected exception not thrown' );
62 }
catch ( \InvalidArgumentException $ex ) {
64 'MediaWiki\\Session\\CookieSessionProvider::__construct: Invalid priority',
71 $this->fail(
'Expected exception not thrown' );
72 }
catch ( \InvalidArgumentException $ex ) {
74 'MediaWiki\\Session\\CookieSessionProvider::__construct: cookieOptions must be an array',
80 $p = TestingAccessWrapper::newFromObject(
85 $this->assertEquals( 1, $p->priority );
86 $this->assertEquals( [
87 'callUserSetCookiesHook' =>
false,
88 'sessionName' =>
'CookiePrefix_session',
90 $this->assertEquals( [
91 'prefix' =>
'CookiePrefix',
92 'path' =>
'CookiePath',
93 'domain' =>
'CookieDomain',
96 ], $p->cookieOptions );
98 $config->set(
'SessionName',
'SessionName' );
99 $p = TestingAccessWrapper::newFromObject(
104 $this->assertEquals( 3, $p->priority );
105 $this->assertEquals( [
106 'callUserSetCookiesHook' =>
false,
107 'sessionName' =>
'SessionName',
109 $this->assertEquals( [
110 'prefix' =>
'CookiePrefix',
111 'path' =>
'CookiePath',
112 'domain' =>
'CookieDomain',
115 ], $p->cookieOptions );
119 'callUserSetCookiesHook' =>
true,
121 'prefix' =>
'XPrefix',
123 'domain' =>
'XDomain',
124 'secure' =>
'XSecure',
125 'httpOnly' =>
'XHttpOnly',
127 'sessionName' =>
'XSession',
131 $this->assertEquals( 10, $p->priority );
132 $this->assertEquals( [
133 'callUserSetCookiesHook' =>
true,
134 'sessionName' =>
'XSession',
136 $this->assertEquals( [
137 'prefix' =>
'XPrefix',
139 'domain' =>
'XDomain',
140 'secure' =>
'XSecure',
141 'httpOnly' =>
'XHttpOnly',
142 ], $p->cookieOptions );
148 $this->assertTrue( $provider->persistsSessionId() );
149 $this->assertTrue( $provider->canChangeUser() );
151 $extendedCookies = [
'UserID',
'UserName',
'Token' ];
155 TestingAccessWrapper::newFromObject( $provider )->getExtendedLoginCookies(),
156 'List of extended cookies (subclasses can add values, but we\'re calling the core one here)'
159 $msg = $provider->whyNoSession();
160 $this->assertInstanceOf(
'Message', $msg );
161 $this->assertSame(
'sessionprovider-nocookies', $msg->getKey() );
167 'sessionName' =>
'session',
168 'cookieOptions' => [
'prefix' =>
'x' ],
171 $logger = new \TestLogger(
true );
172 $provider->setLogger( $logger );
173 $provider->setConfig( $this->
getConfig() );
176 $user = static::getTestSysop()->getUser();
177 $id =
$user->getId();
179 $token =
$user->getToken(
true );
181 $sessionId =
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
185 $info = $provider->provideSessionInfo(
$request );
186 $this->assertNull( $info );
187 $this->assertSame( [], $logger->getBuffer() );
188 $logger->clearBuffer();
193 'session' => $sessionId,
195 $info = $provider->provideSessionInfo(
$request );
196 $this->assertNotNull( $info );
197 $this->assertSame(
$params[
'priority'], $info->getPriority() );
198 $this->assertSame( $sessionId, $info->getId() );
199 $this->assertNotNull( $info->getUserInfo() );
200 $this->assertSame( 0, $info->getUserInfo()->getId() );
201 $this->assertNull( $info->getUserInfo()->getName() );
202 $this->assertFalse( $info->forceHTTPS() );
206 'Session "{session}" requested without UserID cookie',
208 ], $logger->getBuffer() );
209 $logger->clearBuffer();
217 $info = $provider->provideSessionInfo(
$request );
218 $this->assertNotNull( $info );
219 $this->assertSame(
$params[
'priority'], $info->getPriority() );
220 $this->assertNotSame( $sessionId, $info->getId() );
221 $this->assertNotNull( $info->getUserInfo() );
222 $this->assertSame( $id, $info->getUserInfo()->getId() );
223 $this->assertSame(
$name, $info->getUserInfo()->getName() );
224 $this->assertFalse( $info->forceHTTPS() );
225 $this->assertSame( [], $logger->getBuffer() );
226 $logger->clearBuffer();
231 'session' => $sessionId,
235 $info = $provider->provideSessionInfo(
$request );
236 $this->assertNotNull( $info );
237 $this->assertSame(
$params[
'priority'], $info->getPriority() );
238 $this->assertSame( $sessionId, $info->getId() );
239 $this->assertNotNull( $info->getUserInfo() );
240 $this->assertSame( $id, $info->getUserInfo()->getId() );
241 $this->assertSame(
$name, $info->getUserInfo()->getName() );
242 $this->assertFalse( $info->forceHTTPS() );
243 $this->assertSame( [], $logger->getBuffer() );
244 $logger->clearBuffer();
249 'session' => $sessionId,
251 'xToken' =>
'BADTOKEN',
253 $info = $provider->provideSessionInfo(
$request );
254 $this->assertNull( $info );
258 'Session "{session}" requested with invalid Token cookie.'
260 ], $logger->getBuffer() );
261 $logger->clearBuffer();
266 'session' => $sessionId,
269 $info = $provider->provideSessionInfo(
$request );
270 $this->assertNotNull( $info );
271 $this->assertSame(
$params[
'priority'], $info->getPriority() );
272 $this->assertSame( $sessionId, $info->getId() );
273 $this->assertNotNull( $info->getUserInfo() );
274 $this->assertFalse( $info->getUserInfo()->isVerified() );
275 $this->assertSame( $id, $info->getUserInfo()->getId() );
276 $this->assertSame(
$name, $info->getUserInfo()->getName() );
277 $this->assertFalse( $info->forceHTTPS() );
278 $this->assertSame( [], $logger->getBuffer() );
279 $logger->clearBuffer();
285 $info = $provider->provideSessionInfo(
$request );
286 $this->assertNull( $info );
287 $this->assertSame( [], $logger->getBuffer() );
288 $logger->clearBuffer();
293 'session' => $sessionId,
296 'forceHTTPS' =>
true,
298 $info = $provider->provideSessionInfo(
$request );
299 $this->assertNotNull( $info );
300 $this->assertSame(
$params[
'priority'], $info->getPriority() );
301 $this->assertSame( $sessionId, $info->getId() );
302 $this->assertNotNull( $info->getUserInfo() );
303 $this->assertSame( $id, $info->getUserInfo()->getId() );
304 $this->assertSame(
$name, $info->getUserInfo()->getName() );
305 $this->assertTrue( $info->forceHTTPS() );
306 $this->assertSame( [], $logger->getBuffer() );
307 $logger->clearBuffer();
312 'session' => $sessionId,
315 $info = $provider->provideSessionInfo(
$request );
316 $this->assertNull( $info );
317 $this->assertSame( [], $logger->getBuffer() );
318 $logger->clearBuffer();
323 'session' => $sessionId,
325 'xUserName' =>
$name,
327 $info = $provider->provideSessionInfo(
$request );
328 $this->assertNotNull( $info );
329 $this->assertSame(
$params[
'priority'], $info->getPriority() );
330 $this->assertSame( $sessionId, $info->getId() );
331 $this->assertNotNull( $info->getUserInfo() );
332 $this->assertFalse( $info->getUserInfo()->isVerified() );
333 $this->assertSame( $id, $info->getUserInfo()->getId() );
334 $this->assertSame(
$name, $info->getUserInfo()->getName() );
335 $this->assertFalse( $info->forceHTTPS() );
336 $this->assertSame( [], $logger->getBuffer() );
337 $logger->clearBuffer();
342 'session' => $sessionId,
344 'xUserName' =>
'Wrong',
346 $info = $provider->provideSessionInfo(
$request );
347 $this->assertNull( $info );
351 'Session "{session}" requested with mismatched UserID and UserName cookies.',
353 ], $logger->getBuffer() );
354 $logger->clearBuffer();
360 'sessionName' =>
'MySessionName',
361 'cookieOptions' => [
'prefix' =>
'MyCookiePrefix' ],
364 'MyCookiePrefixToken',
365 'MyCookiePrefixLoggedOut',
368 ], $provider->getVaryCookies() );
374 'sessionName' =>
'MySessionName',
375 'cookieOptions' => [
'prefix' =>
'x' ],
379 $this->assertEquals(
null, $provider->suggestLoginUsername(
$request ) );
382 'xUserName' =>
'Example',
384 $this->assertEquals(
'Example', $provider->suggestLoginUsername(
$request ) );
390 'sessionName' =>
'MySessionName',
391 'callUserSetCookiesHook' =>
false,
392 'cookieOptions' => [
'prefix' =>
'x' ],
396 $provider->setConfig(
$config );
399 $sessionId =
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
401 $user = static::getTestSysop()->getUser();
407 'provider' => $provider,
413 new \Psr\Log\NullLogger(),
416 TestingAccessWrapper::newFromObject( $backend )->usePhpSessionHandling =
false;
418 $mock = $this->getMockBuilder(
'stdClass' )
419 ->setMethods( [
'onUserSetCookies' ] )
421 $mock->expects( $this->never() )->method(
'onUserSetCookies' );
425 $backend->setUser( $anon );
426 $backend->setRememberUser(
true );
427 $backend->setForceHTTPS(
false );
429 $provider->persistSession( $backend,
$request );
430 $this->assertSame( $sessionId,
$request->response()->getCookie(
'MySessionName' ) );
431 $this->assertSame(
'',
$request->response()->getCookie(
'xUserID' ) );
432 $this->assertSame(
null,
$request->response()->getCookie(
'xUserName' ) );
433 $this->assertSame(
'',
$request->response()->getCookie(
'xToken' ) );
434 $this->assertSame(
'',
$request->response()->getCookie(
'forceHTTPS' ) );
435 $this->assertSame( [], $backend->getData() );
438 $backend->setUser(
$user );
439 $backend->setRememberUser(
false );
440 $backend->setForceHTTPS(
false );
442 $provider->persistSession( $backend,
$request );
443 $this->assertSame( $sessionId,
$request->response()->getCookie(
'MySessionName' ) );
444 $this->assertSame( (
string)
$user->getId(),
$request->response()->getCookie(
'xUserID' ) );
445 $this->assertSame(
$user->getName(),
$request->response()->getCookie(
'xUserName' ) );
446 $this->assertSame(
'',
$request->response()->getCookie(
'xToken' ) );
447 $this->assertSame(
'',
$request->response()->getCookie(
'forceHTTPS' ) );
448 $this->assertSame( [], $backend->getData() );
451 $backend->setUser(
$user );
452 $backend->setRememberUser(
true );
453 $backend->setForceHTTPS(
true );
456 $provider->persistSession( $backend,
$request );
457 $this->assertSame( $sessionId,
$request->response()->getCookie(
'MySessionName' ) );
458 $this->assertSame( (
string)
$user->getId(),
$request->response()->getCookie(
'xUserID' ) );
459 $this->assertSame(
$user->getName(),
$request->response()->getCookie(
'xUserName' ) );
460 $this->assertSame(
$user->getToken(),
$request->response()->getCookie(
'xToken' ) );
461 $this->assertSame(
'true',
$request->response()->getCookie(
'forceHTTPS' ) );
462 $this->assertSame( [], $backend->getData() );
472 'wgSecureLogin' =>
false,
477 'sessionName' =>
'MySessionName',
478 'callUserSetCookiesHook' =>
false,
479 'cookieOptions' => [
'prefix' =>
'x' ],
482 $config->set(
'CookieSecure', $secure );
484 $provider->setConfig(
$config );
487 $sessionId =
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
488 $user = static::getTestSysop()->getUser();
489 $this->assertFalse(
$user->requiresHTTPS(),
'sanity check' );
494 'provider' => $provider,
500 new \Psr\Log\NullLogger(),
503 TestingAccessWrapper::newFromObject( $backend )->usePhpSessionHandling =
false;
504 $backend->setUser(
$user );
505 $backend->setRememberUser( $remember );
506 $backend->setForceHTTPS( $secure );
509 $provider->persistSession( $backend,
$request );
512 'expire' => (int)100,
516 'httpOnly' =>
$config->
get(
'CookieHttpOnly' ),
520 $normalExpiry =
$config->
get(
'CookieExpiration' );
521 $extendedExpiry =
$config->
get(
'ExtendedLoginCookieExpiration' );
522 $extendedExpiry = (int)( $extendedExpiry ===
null ? 0 : $extendedExpiry );
525 'value' => (
string)$sessionId,
529 'value' => (
string)
$user->getId(),
530 'expire' => $remember ? $extendedExpiry : $normalExpiry,
533 'value' =>
$user->getName(),
534 'expire' => $remember ? $extendedExpiry : $normalExpiry
537 'value' => $remember ?
$user->getToken() :
'',
538 'expire' => $remember ? $extendedExpiry : -31536000,
541 'value' => $secure ?
'true' :
'',
543 'expire' => $secure ? $remember ? $defaults[
'expire'] : 0 : -31536000,
546 foreach ( $expect
as $key =>
$value ) {
547 $actual =
$request->response()->getCookieData( $key );
548 if ( $actual && $actual[
'expire'] > 0 ) {
550 $actual[
'expire'] = round( $actual[
'expire'] -
$time, -2 );
552 $this->assertEquals(
$value, $actual,
"Cookie $key" );
566 $sentResponse = $this->getMockBuilder(
'FauxResponse' )
567 ->setMethods( [
'headersSent',
'setCookie',
'header' ] )->getMock();
568 $sentResponse->expects( $this->
any() )->method(
'headersSent' )
569 ->will( $this->returnValue(
true ) );
570 $sentResponse->expects( $this->never() )->method(
'setCookie' );
571 $sentResponse->expects( $this->never() )->method(
'header' );
573 $sentRequest = $this->getMockBuilder(
'FauxRequest' )
574 ->setMethods( [
'response' ] )->getMock();
575 $sentRequest->expects( $this->
any() )->method(
'response' )
576 ->will( $this->returnValue( $sentResponse ) );
583 'sessionName' =>
'MySessionName',
584 'callUserSetCookiesHook' =>
true,
585 'cookieOptions' => [
'prefix' =>
'x' ],
587 $provider->setLogger(
new \Psr\Log\NullLogger() );
588 $provider->setConfig( $this->
getConfig() );
591 $sessionId =
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
593 $user = static::getTestSysop()->getUser();
599 'provider' => $provider,
605 new \Psr\Log\NullLogger(),
608 TestingAccessWrapper::newFromObject( $backend )->usePhpSessionHandling =
false;
611 $mock = $this->getMockBuilder(
'stdClass' )
612 ->setMethods( [
'onUserSetCookies' ] )->getMock();
613 $mock->expects( $this->never() )->method(
'onUserSetCookies' );
615 $backend->setUser( $anon );
616 $backend->setRememberUser(
true );
617 $backend->setForceHTTPS(
false );
619 $provider->persistSession( $backend,
$request );
620 $this->assertSame( $sessionId,
$request->response()->getCookie(
'MySessionName' ) );
621 $this->assertSame(
'',
$request->response()->getCookie(
'xUserID' ) );
622 $this->assertSame(
null,
$request->response()->getCookie(
'xUserName' ) );
623 $this->assertSame(
'',
$request->response()->getCookie(
'xToken' ) );
624 $this->assertSame(
'',
$request->response()->getCookie(
'forceHTTPS' ) );
625 $this->assertSame( [], $backend->getData() );
630 $mock = $this->getMockBuilder( __CLASS__ )
631 ->setMethods( [
'onUserSetCookies' ] )->getMock();
632 $mock->expects( $this->once() )->method(
'onUserSetCookies' )
633 ->will( $this->returnCallback(
function ( $u, &$sessionData, &$cookies )
use (
$user ) {
634 $this->assertSame(
$user, $u );
635 $this->assertEquals( [
636 'wsUserID' =>
$user->getId(),
637 'wsUserName' =>
$user->getName(),
638 'wsToken' =>
$user->getToken(),
640 $this->assertEquals( [
641 'UserID' =>
$user->getId(),
642 'UserName' =>
$user->getName(),
646 $sessionData[
'foo'] =
'foo!';
647 $cookies[
'bar'] =
'bar!';
651 $backend->setUser(
$user );
652 $backend->setRememberUser(
false );
653 $backend->setForceHTTPS(
false );
654 $backend->setLoggedOutTimestamp( $loggedOut = time() );
656 $provider->persistSession( $backend,
$request );
657 $this->assertSame( $sessionId,
$request->response()->getCookie(
'MySessionName' ) );
658 $this->assertSame( (
string)
$user->getId(),
$request->response()->getCookie(
'xUserID' ) );
659 $this->assertSame(
$user->getName(),
$request->response()->getCookie(
'xUserName' ) );
660 $this->assertSame(
'',
$request->response()->getCookie(
'xToken' ) );
661 $this->assertSame(
'',
$request->response()->getCookie(
'forceHTTPS' ) );
662 $this->assertSame(
'bar!',
$request->response()->getCookie(
'xbar' ) );
663 $this->assertSame( (
string)$loggedOut,
$request->response()->getCookie(
'xLoggedOut' ) );
664 $this->assertEquals( [
665 'wsUserID' =>
$user->getId(),
666 'wsUserName' =>
$user->getName(),
667 'wsToken' =>
$user->getToken(),
669 ], $backend->getData() );
674 $mock = $this->getMockBuilder( __CLASS__ )
675 ->setMethods( [
'onUserSetCookies' ] )->getMock();
676 $mock->expects( $this->once() )->method(
'onUserSetCookies' )
677 ->will( $this->returnCallback(
function ( $u, &$sessionData, &$cookies )
use (
$user ) {
678 $this->assertSame(
$user, $u );
679 $this->assertEquals( [
680 'wsUserID' =>
$user->getId(),
681 'wsUserName' =>
$user->getName(),
682 'wsToken' =>
$user->getToken(),
684 $this->assertEquals( [
685 'UserID' =>
$user->getId(),
686 'UserName' =>
$user->getName(),
687 'Token' =>
$user->getToken(),
690 $sessionData[
'foo'] =
'foo 2!';
691 $cookies[
'bar'] =
'bar 2!';
695 $backend->setUser(
$user );
696 $backend->setRememberUser(
true );
697 $backend->setForceHTTPS(
true );
698 $backend->setLoggedOutTimestamp( 0 );
700 $provider->persistSession( $backend,
$request );
701 $this->assertSame( $sessionId,
$request->response()->getCookie(
'MySessionName' ) );
702 $this->assertSame( (
string)
$user->getId(),
$request->response()->getCookie(
'xUserID' ) );
703 $this->assertSame(
$user->getName(),
$request->response()->getCookie(
'xUserName' ) );
704 $this->assertSame(
$user->getToken(),
$request->response()->getCookie(
'xToken' ) );
705 $this->assertSame(
'true',
$request->response()->getCookie(
'forceHTTPS' ) );
706 $this->assertSame(
'bar 2!',
$request->response()->getCookie(
'xbar' ) );
707 $this->assertSame(
null,
$request->response()->getCookie(
'xLoggedOut' ) );
708 $this->assertEquals( [
709 'wsUserID' =>
$user->getId(),
710 'wsUserName' =>
$user->getName(),
711 'wsToken' =>
$user->getToken(),
713 ], $backend->getData() );
721 'sessionName' =>
'MySessionName',
722 'cookieOptions' => [
'prefix' =>
'x' ],
724 $provider->setLogger(
new \Psr\Log\NullLogger() );
725 $provider->setConfig( $this->
getConfig() );
729 $provider->unpersistSession(
$request );
730 $this->assertSame(
'',
$request->response()->getCookie(
'MySessionName' ) );
731 $this->assertSame(
'',
$request->response()->getCookie(
'xUserID' ) );
732 $this->assertSame(
null,
$request->response()->getCookie(
'xUserName' ) );
733 $this->assertSame(
'',
$request->response()->getCookie(
'xToken' ) );
734 $this->assertSame(
'',
$request->response()->getCookie(
'forceHTTPS' ) );
742 'sessionName' =>
'MySessionName',
743 'cookieOptions' => [
'prefix' =>
'x' ],
745 $provider->setLogger(
new \Psr\Log\NullLogger() );
746 $provider->setConfig( $this->
getConfig() );
750 $t2 = time() - 86400 * 2;
754 $provider->setLoggedOutCookie( $t1,
$request );
755 $this->assertSame( (
string)$t1,
$request->response()->getCookie(
'xLoggedOut' ) );
759 $provider->setLoggedOutCookie( $t2,
$request );
760 $this->assertSame(
null,
$request->response()->getCookie(
'xLoggedOut' ) );
767 $provider->setLoggedOutCookie( $t1,
$request );
768 $this->assertSame(
null,
$request->response()->getCookie(
'xLoggedOut' ) );
781 'sessionName' =>
'MySessionName',
782 'cookieOptions' => [
'prefix' =>
'x' ],
784 $provider->setLogger(
new \Psr\Log\NullLogger() );
785 $provider->setConfig( $this->
getConfig() );
787 $provider = TestingAccessWrapper::newFromObject( $provider );
794 $this->assertSame(
'foo!', $provider->getCookie(
$request,
'Foo',
'x' ) );
795 $this->assertNull( $provider->getCookie(
$request,
'Bar',
'x' ) );
796 $this->assertNull( $provider->getCookie(
$request,
'Baz',
'x' ) );
802 $provider->setLogger(
new \Psr\Log\NullLogger() );
803 $provider->setConfig(
$config );
806 $this->assertSame( 200, $provider->getRememberUserDuration() );
808 $config->set(
'ExtendedLoginCookieExpiration',
null );
810 $this->assertSame( 100, $provider->getRememberUserDuration() );
812 $config->set(
'ExtendedLoginCookieExpiration', 0 );
814 $this->assertSame(
null, $provider->getRememberUserDuration() );
822 $provider->setLogger(
new \Psr\Log\NullLogger() );
823 $provider->setConfig(
$config );
827 $this->assertSame( 200, $provider->getLoginCookieExpiration(
'Token',
true ) );
828 $this->assertSame( 100, $provider->getLoginCookieExpiration(
'User',
true ) );
831 $this->assertSame( 100, $provider->getLoginCookieExpiration(
'UserID',
false ) );
832 $this->assertSame( 100, $provider->getLoginCookieExpiration(
'User',
false ) );
834 $config->set(
'ExtendedLoginCookieExpiration',
null );
836 $this->assertSame( 100, $provider->getLoginCookieExpiration(
'Token',
true ) );
837 $this->assertSame( 100, $provider->getLoginCookieExpiration(
'User',
true ) );
839 $this->assertSame( 100, $provider->getLoginCookieExpiration(
'Token',
false ) );
840 $this->assertSame( 100, $provider->getLoginCookieExpiration(
'User',
false ) );