summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'OAuth/src/Rest/Handler/Resource.php')
-rw-r--r--OAuth/src/Rest/Handler/Resource.php153
1 files changed, 153 insertions, 0 deletions
diff --git a/OAuth/src/Rest/Handler/Resource.php b/OAuth/src/Rest/Handler/Resource.php
new file mode 100644
index 00000000..2b283b4d
--- /dev/null
+++ b/OAuth/src/Rest/Handler/Resource.php
@@ -0,0 +1,153 @@
+<?php
+
+namespace MediaWiki\Extensions\OAuth\Rest\Handler;
+
+use FormatJson;
+use GuzzleHttp\Psr7\ServerRequest;
+use MediaWiki\Extensions\OAuth\Backend\MWOAuthException;
+use MediaWiki\Extensions\OAuth\ResourceServer;
+use MediaWiki\Extensions\OAuth\Response;
+use MediaWiki\Extensions\OAuth\UserStatementProvider;
+use MediaWiki\Rest\Handler;
+use MediaWiki\Rest\HttpException;
+use MWException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Wikimedia\ParamValidator\ParamValidator;
+
+/**
+ * Handles the oauth2/resource/profile and oauth2/resource/scope endpoints, which return
+ * information about the user and the grants of the application, respectively.
+ */
+class Resource extends Handler {
+ const TYPE_PROFILE = 'profile';
+
+ /** @var ResourceServer */
+ protected $resourceServer;
+
+ /**
+ * @return static
+ */
+ public static function factory() {
+ return new static(
+ ResourceServer::factory()
+ );
+ }
+
+ /**
+ * @param ResourceServer $resourceServer
+ */
+ protected function __construct( $resourceServer ) {
+ $this->resourceServer = $resourceServer;
+ }
+
+ /**
+ * All access controls are handled over OAuth2
+ *
+ * @return bool
+ */
+ public function needsReadAccess() {
+ return false;
+ }
+
+ /**
+ * @return bool
+ */
+ public function needsWriteAccess() {
+ return false;
+ }
+
+ /**
+ * @return ResponseInterface
+ */
+ public function execute() {
+ $response = new Response();
+ $request = ServerRequest::fromGlobals()->withHeader(
+ 'authorization',
+ $this->getRequest()->getHeader( 'authorization' )
+ );
+
+ $callback = [ $this, 'doExecuteProtected' ];
+ return $this->resourceServer->verify( $request, $response, $callback );
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ * @param ResponseInterface $response
+ * @throws HttpException
+ * @return ResponseInterface
+ * @throws MWOAuthException
+ */
+ public function doExecuteProtected( $request, $response ) {
+ $type = $this->getRequest()->getPathParam( 'type' );
+
+ switch ( $type ) {
+ case 'profile':
+ return $this->getProfile( $response );
+ case 'scopes':
+ return $this->getScopes( $response );
+ }
+
+ throw new HttpException( 'Invalid resource type', 400 );
+ }
+
+ /**
+ * Return appropriate profile info based on approved scopes
+ *
+ * @param ResponseInterface $response
+ * @return ResponseInterface
+ * @throws HttpException
+ * @throws MWOAuthException
+ */
+ private function getProfile( $response ) {
+ // Intersection between approved and requested scopes
+ $scopes = array_keys( $this->resourceServer->getScopes() );
+ $userStatementProvider = UserStatementProvider::factory(
+ $this->resourceServer->getUser(),
+ $this->resourceServer->getClient(),
+ $scopes
+ );
+
+ try {
+ $profile = $userStatementProvider->getUserProfile();
+ } catch ( MWException $ex ) {
+ throw new HttpException( $ex->getMessage(), $ex->getCode() );
+ }
+
+ return $this->respond( $response, $profile );
+ }
+
+ /**
+ * Get all available scopes client application can use
+ *
+ * @param ResponseInterface $response
+ * @return ResponseInterface
+ * @throws MWOAuthException
+ */
+ private function getScopes( $response ) {
+ $grants = $this->resourceServer->getClient()->getGrants();
+ return $this->respond( $response, [
+ 'scopes' => $grants
+ ] );
+ }
+
+ /**
+ * @param ResponseInterface $response
+ * @param array $data
+ * @return ResponseInterface
+ */
+ private function respond( $response, $data = [] ) {
+ $response->getBody()->write( FormatJson::encode( $data ) );
+ return $response;
+ }
+
+ public function getParamSettings() {
+ return [
+ 'type' => [
+ self::PARAM_SOURCE => 'path',
+ ParamValidator::PARAM_TYPE => [ 'profile', 'scopes' ],
+ ParamValidator::PARAM_REQUIRED => true,
+ ],
+ ];
+ }
+}