diff options
Diffstat (limited to 'routes/auth.php')
| -rw-r--r-- | routes/auth.php | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/routes/auth.php b/routes/auth.php index b44d76a..2dbe6f1 100644 --- a/routes/auth.php +++ b/routes/auth.php @@ -1,10 +1,82 @@ <?php +use Digitigrade\GlobalConfig; use Digitigrade\HttpResponseStatus\BadRequest; +use Digitigrade\HttpResponseStatus\Forbidden; +use Digitigrade\Job\ExpireInboundAuthToken; use Digitigrade\Job\RequestOutboundAuthToken; use Digitigrade\Model\Instance; use Digitigrade\Router; +Router::getInstance()->mount('/auth/main', function (array $args) { + if (!isset($_GET['phase'])) { + throw new BadRequest('you need to specify the `phase` GET parameter'); + } + switch ($_GET['phase']) { + + case 'dialback': + // send a secret to the dialback address! + if (!isset($_GET['target'])) { + throw new BadRequest('you need to specify the `target` GET parameter'); + } + $domain = explode('/', $_GET['target'])[2]; + $instance = Instance::findByDomain($domain); + if ($instance == null) { + throw new RuntimeException("i can't find your instance information, sorry"); + } + + $instance->auth->secret = random_printable_bytes(); + $instance->auth->save(); + // TODO: schedule a job to throw away the secret after some time if it's not used? + + $data = http_build_query([ + 'origin' => GlobalConfig::getInstance()->getCanonicalHost(), + 'secret' => $instance->auth->secret + ]); + $context = stream_context_create(['http' => [ + 'method' => 'POST', + 'header' => 'Content-Type: application/x-www-form-urlencoded', + 'content' => $data + ]]); + // TODO: (maybe?) put this in a job instead of doing it right away? + file_get_contents($_GET['target'], context: $context); + + http_response_code(202); // "Accepted" + break; + + case 'token': + // verify the secret, if it's good, issue a token + if (!isset($_GET['secret'])) { + throw new BadRequest('you need to specify the `secret` GET parameter'); + } + $instance = Instance::findByDialbackSecret($_GET['secret']); + if ($instance == null) { + throw new Forbidden('the provided secret is invalid!'); + } + + $instance->auth->secret = null; // it's been used now + $instance->auth->inboundToken = random_printable_bytes(); + $instance->auth->save(); + + $expiry = new \DateTimeImmutable('1 day'); // this seems like a reasonable length of time? + (new ExpireInboundAuthToken( + $instance->domain, + $instance->auth->inboundToken, + $expiry + ))->submit(); + + json_response([ + 'token' => $instance->auth->inboundToken, + 'expires' => $expiry->format('c') + ]); + + break; + + default: + throw new BadRequest('invalid phase'); + } +}); + Router::getInstance()->mount('/auth/dialback', function (array $args) { // just respond to the dialback challenge! if (!isset($_POST['origin'], $_POST['secret'])) { @@ -19,4 +91,5 @@ Router::getInstance()->mount('/auth/dialback', function (array $args) { } (new RequestOutboundAuthToken($instance->domain, $_POST['secret']))->submit(); + http_response_code(202); // "Accepted" });
\ No newline at end of file |
