1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-16 03:42:41 +01:00
phorge-phorge/src/applications/conduit/controller/PhabricatorConduitTokenEditController.php

101 lines
2.6 KiB
PHP
Raw Normal View History

Add Conduit Tokens to make authentication in Conduit somewhat more sane Summary: Ref T5955. Summary of intended changes: **Improve Granularity of Authorization**: Currently, users have one Conduit Certificate. This isn't very flexible, and means that you can't ever generate an API token with limited permissions or IP block controls (see T6706). This moves toward a world where you can generate multiple tokens, revoke them individually, and assign disparate privileges to them. **Standardize Token Management**: This moves Conduit to work the same way that sessions, OAuth authorizations, and temporary tokens already work, instead of being this crazy bizarre mess. **Make Authentication Faster**: Authentication currently requires a handshake (conduit.connect) to establish a session, like the web UI. This is unnecessary from a security point of view and puts an extra round trip in front of all Conduit activity. Essentially no other API anywhere works like this. **Make Authentication Simpler**: The handshake is complex, and involves deriving hashes. The session is also complex, and creates issues like T4377. Handshake and session management require different inputs. **Make Token Management Simpler**: The certificate is this huge long thing right now, which is not necessary from a security perspective. There are separate Arcanist handshake tokens, but they have a different set of issues. We can move forward to a token management world where neither of these problems exist. **Lower Protocol Barrier**: The simplest possible API client is very complex right now. It should be `curl`. Simplifying authentication is a necessary step toward this. **Unblock T2783**: T2783 is blocked on nodes in the cluster making authenticated API calls to other nodes. This provides a simpler way forward than the handshake mess (or enormous-hack-mess) which would currently be required. Test Plan: - Generated tokens. - Generated tokens for a bot account. - Terminated tokens (and for a bot account). - Terminated all tokens (and for a bot account). - Ran GC and saw it reap all the expired tokens. NOTE: These tokens can not actually be used to authenticate yet! {F249658} Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5955 Differential Revision: https://secure.phabricator.com/D10985
2014-12-15 20:14:23 +01:00
<?php
final class PhabricatorConduitTokenEditController
extends PhabricatorConduitController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
if ($id) {
$token = id(new PhabricatorConduitTokenQuery())
->setViewer($viewer)
->withIDs(array($id))
->withExpired(false)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$token) {
return new Aphront404Response();
}
$object = $token->getObject();
$is_new = false;
$title = pht('View API Token');
} else {
$object = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withPHIDs(array($request->getStr('objectPHID')))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$object) {
return new Aphront404Response();
}
$token = PhabricatorConduitToken::initializeNewToken(
$object->getPHID(),
PhabricatorConduitToken::TYPE_STANDARD);
$is_new = true;
$title = pht('Generate API Token');
$submit_button = pht('Generate Token');
}
if ($viewer->getPHID() == $object->getPHID()) {
$panel_uri = '/settings/panel/apitokens/';
} else {
$panel_uri = '/settings/'.$object->getID().'/panel/apitokens/';
}
id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
$viewer,
$request,
$panel_uri);
if ($request->isFormPost()) {
$token->save();
if ($is_new) {
$token_uri = '/conduit/token/edit/'.$token->getID().'/';
} else {
$token_uri = $panel_uri;
}
return id(new AphrontRedirectResponse())->setURI($token_uri);
}
$dialog = $this->newDialog()
->setTitle($title)
->addHiddenInput('objectPHID', $object->getPHID());
if ($is_new) {
$dialog
->appendParagraph(pht('Generate a new API token?'))
->addSubmitButton($submit_button)
->addCancelButton($panel_uri);
} else {
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Token'))
->setValue($token->getToken()));
$dialog
->appendForm($form)
->addCancelButton($panel_uri, pht('Done'));
}
return $dialog;
}
}