Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 24 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
SsoHookHandler | |
0.00% |
0 / 24 |
|
0.00% |
0 / 4 |
156 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onSetupAfterCache | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
onGetUserPermissionsErrors | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
30 | |||
onApiCheckCanExecute | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\CentralAuth\Hooks\Handlers; |
4 | |
5 | use MediaWiki\Api\Hook\ApiCheckCanExecuteHook; |
6 | use MediaWiki\Extension\CentralAuth\SharedDomainUtils; |
7 | use MediaWiki\Hook\SetupAfterCacheHook; |
8 | use MediaWiki\Permissions\Hook\GetUserPermissionsErrorsHook; |
9 | |
10 | /** |
11 | * Ensure that the SSO domain cannot be used for anything that is unrelated to its purpose. |
12 | */ |
13 | class SsoHookHandler implements |
14 | SetupAfterCacheHook, |
15 | GetUserPermissionsErrorsHook, |
16 | ApiCheckCanExecuteHook |
17 | { |
18 | |
19 | private SharedDomainUtils $sharedDomainUtils; |
20 | |
21 | public function __construct( |
22 | SharedDomainUtils $sharedDomainUtils |
23 | ) { |
24 | $this->sharedDomainUtils = $sharedDomainUtils; |
25 | } |
26 | |
27 | /** @inheritDoc */ |
28 | public function onSetupAfterCache() { |
29 | if ( $this->sharedDomainUtils->isSharedDomain() ) { |
30 | // FIXME The REST API does not provide a hook for disabling APIs. No rest APIs |
31 | // should be needed for login and signup so we can just throw unconditionally, |
32 | // but this should be improved in the future. |
33 | // FIXME should not log a production error |
34 | if ( !in_array( MW_ENTRY_POINT, [ 'index', 'api', 'load' ], true ) ) { |
35 | throw new \RuntimeException( MW_ENTRY_POINT . ' endpoint is not allowed on the SSO domain' ); |
36 | } |
37 | } |
38 | } |
39 | |
40 | /** @inheritDoc */ |
41 | public function onGetUserPermissionsErrors( $title, $user, $action, &$result ) { |
42 | if ( $this->sharedDomainUtils->isSharedDomain() ) { |
43 | if ( !$title->isSpecialPage() ) { |
44 | $result = wfMessage( 'badaccess-group0' ); |
45 | return false; |
46 | } |
47 | // FIXME this should be an extension attribute eventually |
48 | $allowlist = [ 'Userlogin', 'Userlogout', 'CreateAccount', 'PasswordReset', 'Captcha' ]; |
49 | foreach ( $allowlist as $name ) { |
50 | if ( $title->isSpecial( $name ) ) { |
51 | return true; |
52 | } |
53 | } |
54 | $result = wfMessage( 'badaccess-group0' ); |
55 | return false; |
56 | } |
57 | } |
58 | |
59 | /** @inheritDoc */ |
60 | public function onApiCheckCanExecute( $module, $user, &$message ) { |
61 | if ( $this->sharedDomainUtils->isSharedDomain() ) { |
62 | // FIXME this should be an extension attribute eventually |
63 | $allowlist = [ |
64 | // needed for allowing any query API, even if we only want meta modules; it can be |
65 | // used to check page existence (which is unwanted functionality on the SSO domain), |
66 | // which is unfortunate but permissions will still be checked, so it's not a risk. |
67 | 'query', |
68 | // allow login/signup directly via the API + help for those APIs |
69 | 'clientlogin', 'createaccount', 'authmanagerinfo', 'paraminfo', 'help', |
70 | // APIs used during web login |
71 | 'validatepassword', 'userinfo', 'webauthn', 'fancycaptchareload', |
72 | // generic meta APIs, there's a good chance something somewhere will use them |
73 | 'siteinfo', 'globaluserinfo', 'tokens', |
74 | ]; |
75 | |
76 | if ( !in_array( $module->getModuleName(), $allowlist ) ) { |
77 | $message = 'apierror-moduledisabled'; |
78 | return false; |
79 | } |
80 | } |
81 | } |
82 | |
83 | } |