summaryrefslogtreecommitdiff
blob: f1faab838a19cbb2984e92f839b32634c9b7467b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<?php

namespace MediaWiki\Extensions\OAuth\AuthorizationProvider\Grant;

use DateInterval;
use Exception;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\AuthCodeGrant;
use League\OAuth2\Server\Grant\GrantTypeInterface;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use MediaWiki\Extensions\OAuth\AuthorizationProvider\AuthorizationProvider;
use MediaWiki\Extensions\OAuth\Entity\ClientEntity;
use MediaWiki\Extensions\OAuth\Entity\UserEntity;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class AuthorizationCodeAuthorization extends AuthorizationProvider {

	/**
	 * @inheritDoc
	 */
	public function needsUserApproval() {
		return true;
	}

	/**
	 * @return GrantTypeInterface
	 * @throws Exception
	 */
	protected function getGrant(): GrantTypeInterface {
		$authCodeRepo = $this->getAuthCodeRepo();
		$refreshTokenRepo = $this->getRefreshTokenRepo();
		$grant = new AuthCodeGrant(
			$authCodeRepo, $refreshTokenRepo, new DateInterval( 'PT10M' )
		);
		if ( !$this->config->get( 'OAuth2RequireCodeChallengeForPublicClients' ) ) {
			$grant->disableRequireCodeChallengeForPublicClients();
		}

		return $grant;
	}

	/**
	 * @param ServerRequestInterface $request
	 * @return AuthorizationRequest
	 * @throws OAuthServerException
	 */
	public function init( ServerRequestInterface $request ): AuthorizationRequest {
		$authRequest = $this->server->validateAuthorizationRequest( $request );
		/** @var ClientEntity $client */
		$client = $authRequest->getClient();
		'@phan-var ClientEntity $client';

		if ( !$client->isUsableBy( $this->user ) ) {
			throw OAuthServerException::accessDenied(
				'Client ' . $client->getIdentifier() .
				' is not usable by user with ID ' . $this->user->getId()
			);
		}
		$userEntity = UserEntity::newFromMWUser( $this->user );
		$authRequest->setUser( $userEntity );
		$this->logAuthorizationRequest( __METHOD__, $authRequest );

		$this->logger->info(
			"OAuth2: Starting authorization request for client {client} and user (id) {user} ", [
				'client' => $authRequest->getClient()->getIdentifier(),
				'user' => $authRequest->getUser()->getIdentifier()
			]
		);

		return $authRequest;
	}

	/**
	 * @param AuthorizationRequest $authRequest
	 * @param ResponseInterface $response
	 * @return ResponseInterface
	 */
	public function authorize(
		AuthorizationRequest $authRequest, ResponseInterface $response
	): ResponseInterface {
		$this->logAuthorizationRequest( __METHOD__, $authRequest );
		return $this->server->completeAuthorizationRequest( $authRequest, $response );
	}

	/**
	 * @param string $method
	 * @param AuthorizationRequest $authRequest
	 */
	protected function logAuthorizationRequest( $method, AuthorizationRequest $authRequest ) {
		$this->logger->info(
			"OAuth2: Authorization request, func {func}, for client {client} " .
			"and user (id) {user} using grant \"{grant}\"", [
			'func' => $method,
			'client' => $authRequest->getClient()->getIdentifier(),
			'user' => $authRequest->getUser()->getIdentifier(),
			'grant' => $authRequest->getGrantTypeId()
		] );
	}
}