aboutsummaryrefslogtreecommitdiffhomepage
path: root/routes/auth.php
diff options
context:
space:
mode:
Diffstat (limited to 'routes/auth.php')
-rw-r--r--routes/auth.php73
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