diff --git a/resources/sql/autopatches/20150209.oauthclient.trust.sql b/resources/sql/autopatches/20150209.oauthclient.trust.sql new file mode 100644 index 0000000000..5b4b8e4adf --- /dev/null +++ b/resources/sql/autopatches/20150209.oauthclient.trust.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_oauth_server.oauth_server_oauthserverclient + ADD isTrusted TINYINT(1) NOT NULL DEFAULT '0' AFTER creatorPHID; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 748fb09904..18630a93d1 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1353,6 +1353,8 @@ phutil_register_library_map(array( 'PhabricatorAuthManagementRecoverWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRecoverWorkflow.php', 'PhabricatorAuthManagementRefreshWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php', 'PhabricatorAuthManagementStripWorkflow' => 'applications/auth/management/PhabricatorAuthManagementStripWorkflow.php', + 'PhabricatorAuthManagementTrustOAuthClientWorkflow' => 'applications/auth/management/PhabricatorAuthManagementTrustOAuthClientWorkflow.php', + 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php', 'PhabricatorAuthManagementWorkflow' => 'applications/auth/management/PhabricatorAuthManagementWorkflow.php', 'PhabricatorAuthNeedsApprovalController' => 'applications/auth/controller/PhabricatorAuthNeedsApprovalController.php', 'PhabricatorAuthNeedsMultiFactorController' => 'applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php', @@ -4557,6 +4559,8 @@ phutil_register_library_map(array( 'PhabricatorAuthManagementRecoverWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementRefreshWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementStripWorkflow' => 'PhabricatorAuthManagementWorkflow', + 'PhabricatorAuthManagementTrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow', + 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorAuthNeedsApprovalController' => 'PhabricatorAuthController', 'PhabricatorAuthNeedsMultiFactorController' => 'PhabricatorAuthController', diff --git a/src/applications/auth/management/PhabricatorAuthManagementTrustOAuthClientWorkflow.php b/src/applications/auth/management/PhabricatorAuthManagementTrustOAuthClientWorkflow.php new file mode 100644 index 0000000000..4a13c09a21 --- /dev/null +++ b/src/applications/auth/management/PhabricatorAuthManagementTrustOAuthClientWorkflow.php @@ -0,0 +1,62 @@ +setName('trust-oauth-client') + ->setExamples('**trust-oauth-client** [--id client_id]') + ->setSynopsis( + pht( + 'Set Phabricator to trust an OAuth client. Phabricator '. + 'redirects to trusted OAuth clients that users have authorized '. + 'without user intervention.')) + ->setArguments( + array( + array( + 'name' => 'id', + 'param' => 'id', + 'help' => pht('The id of the OAuth client.'), + ),)); + } + + public function execute(PhutilArgumentParser $args) { + $id = $args->getArg('id'); + + if (!$id) { + throw new PhutilArgumentUsageException( + pht( + 'Specify an OAuth client id with --id.')); + } + + $client = id(new PhabricatorOAuthServerClientQuery()) + ->setViewer($this->getViewer()) + ->withIDs(array($id)) + ->executeOne(); + + if (!$client) { + throw new PhutilArgumentUsageException( + pht( + 'Failed to find an OAuth client with id %s.', $id)); + } + + if ($client->getIsTrusted()) { + throw new PhutilArgumentUsageException( + pht( + 'Phabricator already trusts OAuth client "%s".', + $client->getName())); + } + + $client->setIsTrusted(1); + $client->save(); + + $console = PhutilConsole::getConsole(); + $console->writeOut( + "%s\n", + pht( + 'Updated; Phabricator trusts OAuth client %s.', + $client->getName())); + } + +} diff --git a/src/applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php b/src/applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php new file mode 100644 index 0000000000..beecf450be --- /dev/null +++ b/src/applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php @@ -0,0 +1,62 @@ +setName('untrust-oauth-client') + ->setExamples('**untrust-oauth-client** [--id client_id]') + ->setSynopsis( + pht( + 'Set Phabricator to not trust an OAuth client. Phabricator '. + 'redirects to trusted OAuth clients that users have authorized '. + 'without user intervention.')) + ->setArguments( + array( + array( + 'name' => 'id', + 'param' => 'id', + 'help' => pht('The id of the OAuth client.'), + ),)); + } + + public function execute(PhutilArgumentParser $args) { + $id = $args->getArg('id'); + + if (!$id) { + throw new PhutilArgumentUsageException( + pht( + 'Specify an OAuth client id with --id.')); + } + + $client = id(new PhabricatorOAuthServerClientQuery()) + ->setViewer($this->getViewer()) + ->withIDs(array($id)) + ->executeOne(); + + if (!$client) { + throw new PhutilArgumentUsageException( + pht( + 'Failed to find an OAuth client with id %s.', $id)); + } + + if (!$client->getIsTrusted()) { + throw new PhutilArgumentUsageException( + pht( + 'Phabricator already does not trust OAuth client "%s".', + $client->getName())); + } + + $client->setIsTrusted(0); + $client->save(); + + $console = PhutilConsole::getConsole(); + $console->writeOut( + "%s\n", + pht( + 'Updated; Phabricator does not trust OAuth client %s.', + $client->getName())); + } + +} diff --git a/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php b/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php index c95aaaa823..07e0e45425 100644 --- a/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php +++ b/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php @@ -182,6 +182,12 @@ final class PhabricatorOAuthServerAuthController 'state' => $state, )); + if ($client->getIsTrusted()) { + return id(new AphrontRedirectResponse()) + ->setIsExternal(true) + ->setURI((string)$full_uri); + } + // TODO: It would be nice to give the user more options here, like // reviewing permissions, canceling the authorization, or aborting // the workflow. diff --git a/src/applications/oauthserver/storage/PhabricatorOAuthServerClient.php b/src/applications/oauthserver/storage/PhabricatorOAuthServerClient.php index bbc4264bb1..79de173bad 100644 --- a/src/applications/oauthserver/storage/PhabricatorOAuthServerClient.php +++ b/src/applications/oauthserver/storage/PhabricatorOAuthServerClient.php @@ -10,6 +10,7 @@ final class PhabricatorOAuthServerClient protected $name; protected $redirectURI; protected $creatorPHID; + protected $isTrusted = 0; protected $viewPolicy; protected $editPolicy; @@ -40,6 +41,7 @@ final class PhabricatorOAuthServerClient 'name' => 'text255', 'secret' => 'text32', 'redirectURI' => 'text255', + 'isTrusted' => 'bool', ), self::CONFIG_KEY_SCHEMA => array( 'key_phid' => null,