Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
AuthorizationProvider
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 12
240
0.00% covered (danger)
0.00%
0 / 1
 factory
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 setUser
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 needsUserApproval
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getGrant
n/a
0 / 0
n/a
0 / 0
0
 getGrantSingleton
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 decorateAuthServer
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 getRefreshTokenRepo
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getAuthCodeRepo
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getGrantExpirationInterval
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getRefreshTokenTTL
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getClientIdFromRequest
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 parseExpiration
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace MediaWiki\Extension\OAuth\AuthorizationProvider;
4
5use DateInterval;
6use Exception;
7use League\OAuth2\Server\AuthorizationServer;
8use League\OAuth2\Server\Grant\GrantTypeInterface;
9use MediaWiki\Config\Config;
10use MediaWiki\Extension\OAuth\AuthorizationServerFactory;
11use MediaWiki\Extension\OAuth\Repository\AuthCodeRepository;
12use MediaWiki\Extension\OAuth\Repository\RefreshTokenRepository;
13use MediaWiki\Logger\LoggerFactory;
14use MediaWiki\MediaWikiServices;
15use MediaWiki\User\User;
16use Psr\Http\Message\ServerRequestInterface;
17use Psr\Log\LoggerInterface;
18
19abstract class AuthorizationProvider implements IAuthorizationProvider {
20    /**
21     * @var AuthorizationServer
22     */
23    protected $server;
24
25    /**
26     * @var Config|null
27     */
28    protected $config;
29
30    /**
31     * @var User
32     */
33    protected $user;
34
35    /**
36     * @var LoggerInterface
37     */
38    protected $logger;
39
40    /**
41     * @var GrantTypeInterface
42     */
43    protected $grant;
44
45    /**
46     * @return AuthorizationProvider
47     * @throws Exception
48     */
49    public static function factory() {
50        $services = MediaWikiServices::getInstance();
51        $config = $services->getConfigFactory()->makeConfig( 'mwoauth' );
52        $serverFactory = AuthorizationServerFactory::factory();
53        $logger = LoggerFactory::getInstance( 'OAuth' );
54
55        // @phan-suppress-next-line PhanTypeInstantiateAbstractStatic
56        return new static( $config, $serverFactory->getAuthorizationServer(), $logger );
57    }
58
59    /**
60     * @param Config $config
61     * @param AuthorizationServer $server
62     * @param LoggerInterface $logger
63     * @throws Exception
64     */
65    public function __construct( $config, $server, $logger ) {
66        $this->config = $config;
67        $this->server = $server;
68        $this->logger = $logger;
69
70        $this->decorateAuthServer();
71    }
72
73    /**
74     * @inheritDoc
75     */
76    public function setUser( User $user ) {
77        $this->user = $user;
78    }
79
80    /**
81     * @inheritDoc
82     */
83    public function needsUserApproval() {
84        return false;
85    }
86
87    /**
88     * @return GrantTypeInterface
89     */
90    abstract protected function getGrant(): GrantTypeInterface;
91
92    /**
93     * @return GrantTypeInterface
94     */
95    protected function getGrantSingleton() {
96        if ( !$this->grant ) {
97            $this->grant = $this->getGrant();
98        }
99
100        return $this->grant;
101    }
102
103    /**
104     * @throws Exception
105     */
106    protected function decorateAuthServer() {
107        $grant = $this->getGrantSingleton();
108        $grant->setRefreshTokenTTL( $this->getRefreshTokenTTL() );
109        $this->server->setDefaultScope( '#default' );
110        $this->server->enableGrantType(
111            $grant,
112            $this->getGrantExpirationInterval()
113        );
114    }
115
116    /**
117     * @return RefreshTokenRepository
118     */
119    protected function getRefreshTokenRepo() {
120        return RefreshTokenRepository::factory();
121    }
122
123    /**
124     * @return AuthCodeRepository
125     */
126    protected function getAuthCodeRepo() {
127        return AuthCodeRepository::factory();
128    }
129
130    /**
131     * @return DateInterval
132     * @throws Exception
133     */
134    protected function getGrantExpirationInterval() {
135        $intervalSpec = $this->parseExpiration( $this->config->get( 'OAuth2GrantExpirationInterval' ) );
136        return new DateInterval( $intervalSpec );
137    }
138
139    /**
140     * @return DateInterval
141     * @throws Exception
142     */
143    protected function getRefreshTokenTTL() {
144        $intervalSpec = $this->parseExpiration( $this->config->get( 'OAuth2RefreshTokenTTL' ) );
145        return new DateInterval( $intervalSpec );
146    }
147
148    /**
149     * @param ServerRequestInterface $request
150     * @param string $default
151     * @return mixed|string
152     */
153    protected function getClientIdFromRequest( ServerRequestInterface $request, $default = '' ) {
154        $params = (array)$request->getParsedBody();
155
156        return $params['client_id'] ?? $default;
157    }
158
159    private function parseExpiration( $expiration ) {
160        if ( $expiration === false || $expiration === 'infinity' ) {
161            // Effectively non-expiring tokens
162            $expiration = 'P1000Y';
163        }
164
165        return $expiration;
166    }
167}