Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
88.89% covered (warning)
88.89%
16 / 18
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
CentralAuthApiSessionProvider
88.89% covered (warning)
88.89%
16 / 18
33.33% covered (danger)
33.33%
1 / 3
9.11
0.00% covered (danger)
0.00%
0 / 1
 getTokenDataFromRequest
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
5.03
 makeBogusSessionInfo
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 provideSessionInfo
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
3.33
1<?php
2
3use MediaWiki\Api\ApiUsageException;
4use MediaWiki\Extension\CentralAuth\Config\CAMainConfigNames;
5use MediaWiki\Request\WebRequest;
6use MediaWiki\Session\SessionInfo;
7
8/**
9 * Session provider for CentralAuth API centralauthtoken
10 *
11 * This session provider looks for the 'centralauthtoken' request parameter,
12 * and checks that it corresponds to an existing token set up by
13 * ApiCentralAuthToken. If the parameter is present but invalid, it returns a
14 * bogus SessionInfo and hooks ApiBeforeMain to throw an appropriate exception
15 * later when MediaWiki is ready to handle it.
16 *
17 * @see \MediaWiki\Extension\CentralAuth\Api\ApiCentralAuthToken
18 */
19class CentralAuthApiSessionProvider extends CentralAuthTokenSessionProvider {
20
21    /** @inheritDoc */
22    protected function getTokenDataFromRequest( WebRequest $request ) {
23        // Only applied to api.php and unit tests
24        if ( !defined( 'MW_API' ) && !defined( 'MW_PHPUNIT_TEST' ) ) {
25            return null;
26        }
27
28        $oneTimeToken = $request->getVal( 'centralauthtoken' );
29        if ( $oneTimeToken === null ) {
30            return null;
31        }
32
33        $timeout = $this->getConfig()->get( CAMainConfigNames::CentralAuthTokenSessionTimeout );
34
35        if ( $request->getMethod() === 'OPTIONS' ) {
36            // Do not delete the tokenized data on OPTIONS requests, as they are generated automatically
37            // by the browser as part of the CORS preflight mechanism, with the same URL as the real
38            // GET/POST request (including the 'centralauthtoken' parameter). Deleting it here would cause
39            // the subsequent real request to fail. There is no way to avoid that.
40            // https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests
41            return $this->tokenManager->detokenize( $oneTimeToken, 'api-token', [ 'timeout' => $timeout ] );
42        } else {
43            return $this->tokenManager->detokenizeAndDelete( $oneTimeToken, 'api-token', [ 'timeout' => $timeout ] );
44        }
45    }
46
47    /**
48     * Throw an exception, later
49     *
50     * @param string $code Error code
51     * @param string|array $error Error message key, or key+parameters
52     * @return SessionInfo
53     */
54    protected function makeBogusSessionInfo( $code, $error ) {
55        // Schedule the throwing of the exception for later when the API
56        // is ready to catch it.
57        $exception = ApiUsageException::newWithMessage( null, $error, $code );
58        /** @return never */
59        $excepClosure = static function () use ( $exception ) {
60            throw $exception;
61        };
62        $this->getHookContainer()->register( 'ApiBeforeMain', $excepClosure );
63
64        return parent::makeBogusSessionInfo( $code, $error );
65    }
66
67    /** @inheritDoc */
68    public function provideSessionInfo( WebRequest $request ) {
69        // Only applied to api.php and unit tests
70        if ( !defined( 'MW_API' ) && !defined( 'MW_PHPUNIT_TEST' ) ) {
71            return null;
72        }
73
74        return parent::provideSessionInfo( $request );
75    }
76
77}