Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5967550
CentralAuthTokenSessionProvider.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
CentralAuthTokenSessionProvider.php
View Options
<?php
use
MediaWiki\Extension\CentralAuth\CentralAuthSessionManager
;
use
MediaWiki\Extension\CentralAuth\CentralAuthTokenManager
;
use
MediaWiki\Extension\CentralAuth\User\CentralAuthUser
;
use
MediaWiki\Request\WebRequest
;
use
MediaWiki\Session\SessionBackend
;
use
MediaWiki\Session\SessionInfo
;
use
MediaWiki\Session\SessionProvider
;
use
MediaWiki\Session\UserInfo
;
use
MediaWiki\User\User
;
use
MediaWiki\User\UserIdentityLookup
;
use
MediaWiki\User\UserNameUtils
;
use
Wikimedia\LightweightObjectStore\ExpirationAwareness
;
/**
* Base class for token based CentralAuth SessionProviders for use with different kinds of APIs.
*
* This base class provides functionality for looking at a token from the request,
* and checking that it corresponds to an existing token generated by
* CentralAuthTokenProvider.
* If the token is present but invalid, a CentralAuthTokenSessionProvider returns a
* bogus SessionInfo to prevent other SessionProviders from establishing a session.
*/
abstract
class
CentralAuthTokenSessionProvider
extends
SessionProvider
{
private
UserIdentityLookup
$userIdentityLookup
;
private
CentralAuthSessionManager
$sessionManager
;
protected
CentralAuthTokenManager
$tokenManager
;
/**
* @param UserIdentityLookup $userIdentityLookup
* @param CentralAuthSessionManager $sessionManager
* @param CentralAuthTokenManager $tokenManager
*/
public
function
__construct
(
UserIdentityLookup
$userIdentityLookup
,
CentralAuthSessionManager
$sessionManager
,
CentralAuthTokenManager
$tokenManager
)
{
parent
::
__construct
();
$this
->
userIdentityLookup
=
$userIdentityLookup
;
$this
->
sessionManager
=
$sessionManager
;
$this
->
tokenManager
=
$tokenManager
;
}
/**
* Returns a bogus session, which can be used to prevent other SessionProviders
* from attemption to establish a session.
*
* May be overridden by subclasses to somehow cause error handling ot be triggered later.
*
* Per default, it just returns null.
*
* @param string $code Error code
* @param string|array $error Error message key, or key+parameters
* @return SessionInfo|null
*/
protected
function
makeBogusSessionInfo
(
$code
,
$error
)
{
// Then return an appropriate SessionInfo
$id
=
$this
->
hashToSessionId
(
'bogus'
);
return
new
SessionInfo
(
SessionInfo
::
MAX_PRIORITY
,
[
'provider'
=>
$this
,
'id'
=>
$id
,
'userInfo'
=>
UserInfo
::
newAnonymous
(),
'persisted'
=>
false
,
'metadata'
=>
[
'error-code'
=>
$code
,
'error'
=>
$error
,
],
]
);
}
/**
* @param WebRequest $request
* @return mixed `null` indicates that no token was provided, `false` indicates an invalid token,
* any other value is detokenized data
*/
abstract
protected
function
getTokenDataFromRequest
(
WebRequest
$request
);
/** @inheritDoc */
public
function
provideSessionInfo
(
WebRequest
$request
)
{
$data
=
$this
->
getTokenDataFromRequest
(
$request
);
if
(
$data
===
null
)
{
return
null
;
}
$this
->
logger
->
debug
(
__METHOD__
.
': Found a token!'
);
if
(
!
is_array
(
$data
)
||
!
isset
(
$data
[
'userName'
]
)
||
!
isset
(
$data
[
'token'
]
)
||
!
isset
(
$data
[
'origin'
]
)
||
!
isset
(
$data
[
'originSessionId'
]
)
)
{
$this
->
logger
->
info
(
__METHOD__
.
': centralauthtoken is invalid'
);
return
$this
->
makeBogusSessionInfo
(
'badtoken'
,
'apierror-centralauth-badtoken'
);
}
$userName
=
$data
[
'userName'
];
$authToken
=
$data
[
'token'
];
// Clean up username
$userName
=
$this
->
userNameUtils
->
getCanonical
(
$userName
);
if
(
!
$userName
)
{
$this
->
logger
->
info
(
__METHOD__
.
': invalid username'
);
return
$this
->
makeBogusSessionInfo
(
'badtoken'
,
'apierror-centralauth-badtoken'
);
}
if
(
!
$this
->
userNameUtils
->
isUsable
(
$userName
)
)
{
$this
->
logger
->
info
(
__METHOD__
.
': unusable username'
);
return
$this
->
makeBogusSessionInfo
(
'badusername'
,
[
'apierror-centralauth-badusername'
,
wfEscapeWikiText
(
$userName
)
]
);
}
// Try the central user
$centralUser
=
CentralAuthUser
::
getInstanceByName
(
$userName
);
// Skip if they're being renamed
if
(
$centralUser
->
renameInProgress
()
)
{
$this
->
logger
->
info
(
__METHOD__
.
': rename in progress'
);
return
$this
->
makeBogusSessionInfo
(
'renameinprogress'
,
'apierror-centralauth-renameinprogress'
);
}
if
(
!
$centralUser
->
exists
()
)
{
$this
->
logger
->
info
(
__METHOD__
.
': global account doesn
\'
t exist'
);
return
$this
->
makeBogusSessionInfo
(
'badtoken'
,
'apierror-centralauth-badtoken'
);
}
if
(
!
$centralUser
->
isAttached
()
)
{
$userIdentity
=
$this
->
userIdentityLookup
->
getUserIdentityByName
(
$userName
);
if
(
$userIdentity
&&
$userIdentity
->
isRegistered
()
)
{
$this
->
logger
->
info
(
__METHOD__
.
': not attached and local account exists'
);
return
$this
->
makeBogusSessionInfo
(
'badtoken'
,
'apierror-centralauth-badtoken'
);
}
}
$key
=
$this
->
sessionManager
->
makeSessionKey
(
'api-token-blacklist'
,
(
string
)
$centralUser
->
getId
()
);
$sessionStore
=
$this
->
sessionManager
->
getSessionStore
();
if
(
$sessionStore
->
get
(
$key
)
)
{
$this
->
logger
->
info
(
__METHOD__
.
': user is blacklisted'
);
return
$this
->
makeBogusSessionInfo
(
'badtoken'
,
'apierror-centralauth-badtoken'
);
}
if
(
$centralUser
->
authenticateWithToken
(
$authToken
)
!=
'ok'
)
{
$this
->
logger
->
info
(
__METHOD__
.
': token mismatch'
);
return
$this
->
makeBogusSessionInfo
(
'badtoken'
,
'apierror-centralauth-badtoken'
);
}
$this
->
logger
->
debug
(
__METHOD__
.
': logged in from session'
);
$info
=
[
'userInfo'
=>
UserInfo
::
newFromName
(
$userName
,
true
),
'provider'
=>
$this
,
'id'
=>
$this
->
hashToSessionId
(
implode
(
"
\n
"
,
$data
)
),
'persisted'
=>
true
,
'forceUse'
=>
true
,
];
return
new
SessionInfo
(
SessionInfo
::
MAX_PRIORITY
,
$info
);
}
public
function
persistsSessionId
()
{
return
false
;
}
public
function
canChangeUser
()
{
return
false
;
}
/** @inheritDoc */
public
function
persistSession
(
SessionBackend
$session
,
WebRequest
$request
)
{
// Nothing to do
}
/** @inheritDoc */
public
function
unpersistSession
(
WebRequest
$request
)
{
// Nothing to do
}
/** @inheritDoc */
public
function
invalidateSessionsForUser
(
User
$user
)
{
$centralUser
=
CentralAuthUser
::
getPrimaryInstance
(
$user
);
if
(
$centralUser
->
exists
()
&&
(
$centralUser
->
isAttached
()
||
!
$user
->
isRegistered
()
)
)
{
$centralUser
->
resetAuthToken
();
}
}
/** @inheritDoc */
public
function
preventSessionsForUser
(
$username
)
{
$username
=
$this
->
userNameUtils
->
getCanonical
(
$username
,
UserNameUtils
::
RIGOR_VALID
);
if
(
!
$username
)
{
return
;
}
$centralUser
=
CentralAuthUser
::
getInstanceByName
(
$username
);
if
(
!
$centralUser
->
exists
()
)
{
return
;
}
// Assume blacklisting for a day will be enough because we assume by
// then CentralAuth itself will have been instructed to more
// permanently block the user.
$sessionStore
=
$this
->
sessionManager
->
getSessionStore
();
$key
=
$this
->
sessionManager
->
makeSessionKey
(
'api-token-blacklist'
,
(
string
)
$centralUser
->
getId
()
);
$sessionStore
->
set
(
$key
,
true
,
ExpirationAwareness
::
TTL_DAY
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, Oct 3, 12:28 (3 d, 1 h ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
79/62/df84f8657ccb44e1f527b898662f
Default Alt Text
CentralAuthTokenSessionProvider.php (6 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment