Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1431219
AuthenticationHandler.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
AuthenticationHandler.php
View Options
<?php
namespace
MediaWiki\Extension\OAuth\Rest\Handler
;
use
League\OAuth2\Server\Exception\OAuthServerException
;
use
LogicException
;
use
MediaWiki\Config\Config
;
use
MediaWiki\Context\RequestContext
;
use
MediaWiki\Extension\OAuth\AuthorizationProvider\AccessToken
as
AccessTokenProvider
;
use
MediaWiki\Extension\OAuth\AuthorizationProvider\Grant\AuthorizationCodeAuthorization
;
use
MediaWiki\Extension\OAuth\Backend\Utils
;
use
MediaWiki\Extension\OAuth\Response
;
use
MediaWiki\MediaWikiServices
;
use
MediaWiki\Message\Message
;
use
MediaWiki\Rest\Handler
;
use
MediaWiki\Rest\HttpException
;
use
MediaWiki\Rest\LocalizedHttpException
;
use
MediaWiki\Rest\Response
as
RestResponse
;
use
MediaWiki\Rest\StringStream
;
use
MediaWiki\Rest\Validator\Validator
;
use
MediaWiki\Title\Title
;
use
MediaWiki\User\User
;
use
Psr\Http\Message\ResponseInterface
;
abstract
class
AuthenticationHandler
extends
Handler
{
/**
* @var User
*/
protected
$user
;
/**
* @var Config
*/
protected
$config
;
/**
* @var OAuthServerException|null
*/
protected
$queuedError
;
/**
* @return AuthenticationHandler
*/
public
static
function
factory
()
{
$centralId
=
Utils
::
getCentralIdFromLocalUser
(
RequestContext
::
getMain
()->
getUser
()
);
$user
=
$centralId
?
Utils
::
getLocalUserFromCentralId
(
$centralId
)
:
User
::
newFromId
(
0
);
$config
=
MediaWikiServices
::
getInstance
()->
getConfigFactory
()->
makeConfig
(
'mwoauth'
);
// @phan-suppress-next-line PhanTypeInstantiateAbstractStatic
return
new
static
(
$user
,
$config
);
}
/**
* @param User $user
* @param Config $config
*/
protected
function
__construct
(
User
$user
,
Config
$config
)
{
$this
->
user
=
$user
;
$this
->
config
=
$config
;
}
/**
* We do not want any permission checks
*
* @return bool
*/
public
function
needsReadAccess
()
{
return
false
;
}
/**
* We do not want any permission checks
*
* @return bool
*/
public
function
needsWriteAccess
()
{
return
false
;
}
/**
* @throws HttpException
* @return AccessTokenProvider|AuthorizationCodeAuthorization
*/
protected
function
getAuthorizationProvider
()
{
$grantType
=
$this
->
getGrantType
();
$class
=
$this
->
getGrantClass
(
$grantType
);
if
(
!
$class
||
!
is_callable
(
[
$class
,
'factory'
]
)
)
{
throw
new
LogicException
(
'Could not find grant class factory'
);
}
/** @var AccessTokenProvider|AuthorizationCodeAuthorization $authProvider */
$authProvider
=
$class
::
factory
();
'@phan-var AccessTokenProvider|AuthorizationCodeAuthorization $authProvider'
;
return
$authProvider
;
}
public
function
validate
(
Validator
$restValidator
)
{
try
{
parent
::
validate
(
$restValidator
);
}
catch
(
HttpException
$exception
)
{
if
(
$exception
instanceof
LocalizedHttpException
)
{
$formatted
=
$this
->
getResponseFactory
()->
formatMessage
(
$exception
->
getMessageValue
()
);
$message
=
$formatted
[
'messageTranslations'
][
'en'
]
??
reset
(
$formatted
[
'messageTranslations'
]
);
}
else
{
$message
=
$exception
->
getMessage
();
}
// Catch and store any validation errors, so they can be thrown
// during the execution, and get caught by appropriate error handling code
$type
=
$exception
->
getErrorData
()[
'error'
]
??
'parameter-validation-failed'
;
if
(
$type
===
'parameter-validation-failed'
)
{
$missingParam
=
$exception
->
getErrorData
()[
'name'
]
??
''
;
$this
->
queueError
(
new
OAuthServerException
(
// OAuthServerException::invalidRequest() but with more useful text
'Invalid request: '
.
$message
,
3
,
'invalid_request'
,
400
,
$missingParam
?
\sprintf
(
'Check the `%s` parameter'
,
$missingParam
)
:
null
)
);
return
;
}
$this
->
queueError
(
OAuthServerException
::
serverError
(
$message
)
);
}
}
/**
* @param OAuthServerException $ex
*/
protected
function
queueError
(
OAuthServerException
$ex
)
{
// If already set, do not override, since we cannot throw more than one error,
// and it will probably be more useful to throw first error that occurred
if
(
!
$this
->
queuedError
)
{
$this
->
queuedError
=
$ex
;
}
}
/**
* @param array $query
* @return string
*/
protected
function
getQueryParamsCgi
(
$query
=
[]
)
{
$queryParams
=
$this
->
getRequest
()->
getQueryParams
();
unset
(
$queryParams
[
'title'
]
);
$queryParams
=
array_merge
(
$queryParams
,
$query
);
return
wfArrayToCgi
(
$queryParams
);
}
/**
* @param OAuthServerException $exception
* @param Response|null $response
* @return ResponseInterface|RestResponse
*/
protected
function
errorResponse
(
$exception
,
$response
=
null
)
{
$response
??=
new
Response
();
$response
=
$exception
->
generateHttpResponse
(
$response
);
if
(
$exception
->
hasRedirect
()
||
$this
->
getRequest
()->
getMethod
()
===
'POST'
)
{
return
$response
;
}
$context
=
RequestContext
::
getMain
();
// T379504: Set dummy context title
$context
->
setTitle
(
Title
::
makeTitle
(
NS_SPECIAL
,
'Api/Rest'
)
);
$out
=
$context
->
getOutput
();
$out
->
showErrorPage
(
'mwoauth-error'
,
$this
->
getLocalizedErrorMessage
(
$exception
)
);
ob_start
();
$out
->
output
();
$html
=
ob_get_clean
();
$response
=
$this
->
getResponseFactory
()->
create
();
$stream
=
new
StringStream
(
$html
);
$response
->
setStatus
(
$exception
->
getHttpStatusCode
()
);
$response
->
setHeader
(
'Content-Type'
,
'text/html'
);
$response
->
setBody
(
$stream
);
return
$response
;
}
private
function
getLocalizedErrorMessage
(
OAuthServerException
$exception
):
Message
{
$type
=
$exception
->
getErrorType
();
$map
=
[
'invalid_client'
=>
'mwoauth-oauth2-error-invalid-client'
,
'invalid_request'
=>
'mwoauth-oauth2-error-invalid-request'
,
'unauthorized_client'
=>
'mwoauth-oauth2-error-unauthorized-client'
,
'access_denied'
=>
'mwoauth-oauth2-error-access-denied'
,
'unsupported_response_type'
=>
'mwoauth-oauth2-error-unsupported-response-type'
,
'invalid_scope'
=>
'mwoauth-oauth2-error-invalid-scope'
,
'temporarily_unavailable'
=>
'mwoauth-oauth2-error-temporarily-unavailable'
,
// 'server_error' is passed through to the catch-all handler below
];
$msg
=
isset
(
$map
[
$type
]
)
?
wfMessage
(
$map
[
$type
]
)
:
wfMessage
(
'mwoauth-oauth2-error-server-error'
,
$exception
->
getMessage
()
);
if
(
$exception
->
getHint
()
)
{
return
wfMessage
(
'mwoauth-oauth2-error-serverexception-withhint'
,
$msg
,
$exception
->
getHint
()
);
}
else
{
return
$msg
;
}
}
/** @inheritDoc */
protected
function
detectExtraneousBodyFields
(
Validator
$restValidator
)
{
// Ignore unexpected parameters per https://datatracker.ietf.org/doc/html/rfc6749#section-3.1
// and https://datatracker.ietf.org/doc/html/rfc6749#section-3.2 :
// "The authorization server MUST ignore unrecognized request parameters."
}
/**
* @return string
*/
abstract
protected
function
getGrantType
();
/**
* @param string $grantType
* @return string|false
*/
abstract
protected
function
getGrantClass
(
$grantType
);
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 20:12 (1 d, 2 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
84/51/a117901380d40deed68b6f9425a7
Default Alt Text
AuthenticationHandler.php (6 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment