Page MenuHomePhabricator

D595.id.diff
No OneTemporary

D595.id.diff

diff --git a/bin/controllers/mfa/PhoneController.php b/bin/controllers/mfa/PhoneController.php
--- a/bin/controllers/mfa/PhoneController.php
+++ b/bin/controllers/mfa/PhoneController.php
@@ -209,11 +209,99 @@
$payload = new twofactor\sms\Message($phone->content, 'Your authentication code is: ' . $twofactor->secret);
if ($instance->deliver($payload)) {
- $this->response->setBody('Redirect...')->getHeaders()->redirect(url('twofactor', 'check', $phone->_id, ['returnto' => $_GET['returnto']?? '/']));
+ $this->response->setBody('Redirect...')->getHeaders()->redirect(url(['mfa', 'phone'], 'verify', $phone->_id, ['returnto' => $_GET['returnto']?? '/']));
}
else {
throw new PublicException('SMS Delivery error', 500);
}
}
+ /**
+ * This method verifies the response from a SMS verification attempt. This method
+ * is invoked after the user requested a challenge to attempt to verify that
+ * the message has arrived.
+ *
+ * @param ProviderModel $provider
+ * @param type $_secret
+ * @return type
+ * @throws HTTPMethodException
+ * @throws PublicException
+ * @throws ValidationException
+ */
+ public function verify(ProviderModel$provider, $_secret = null)
+ {
+
+
+ if ($provider->type != ProviderModel::TYPE_PHONE) {
+ throw new PublicException('Invalid provider', 400);
+ }
+
+ try {
+ if (!$this->request->isPost() && !$_secret) { throw new HTTPMethodException('Not posted'); }
+ if ($provider->expires !== null && $provider->expires < time()) { throw new PublicException('This provider has already expired', 403); }
+
+ sleep(2);
+
+ $secret = db()->table('authentication\challenge')->get('provider', $provider)->where('secret', $_secret?: $_POST['secret'])->where('expires', '>', time())->first(true);
+ if ($secret->secret != ($_secret?: $_POST['secret'])) { throw new ValidationException('Invalid secret', 0, ['Invalid secret']); }
+
+ /*
+ * Check if the passport was already recorded. If this is the case, the
+ * user cannot confirm this as their own.
+ */
+ $exists = db()->table('passport')
+ ->get('canonical', $provider->canonical)
+ ->where('user', '!=', $provider->user)
+ ->first();
+
+ if ($provider->expires && $provider->passport && $exists) {
+ throw new PublicException('The provider is already reserved for another user', 403);
+ }
+
+ /*
+ * Since the user managed to successfully authenticate this provider, we
+ * assume that the user wishes to use this for further authentication.
+ */
+ $preferred = db()->table('authentication\provider')->get('user', $provider->user)->where('preferred', true)->first();
+
+ if ($preferred && $preferred->_id != $provider->_id) {
+ $preferred->preferred = false;
+ $preferred->store();
+ }
+
+ $provider->preferred = true;
+ $provider->store();
+
+ /*
+ * If the provider happened to not be verified yet, we will continue and
+ * do so now.
+ */
+ if ($provider->expires) {
+ $provider->expires = null;
+ $provider->store();
+ }
+
+ /*
+ * If the passport was flagged to be expiring, then we remove the flag.
+ * This happens unless the passport was already expired.
+ */
+ if ($provider->passport && $provider->passport->expires && $provider->passport->expires > time()) {
+ $provider->passport->expires = null;
+ $provider->passport->store();
+ }
+
+ $secret->cleared = time();
+ $secret->store();
+
+
+ $this->response->setBody('Redirect')->getHeaders()->redirect($_GET['returnto']?? url());
+ return;
+ }
+ catch (HTTPMethodException $ex) {
+
+ }
+
+ $this->view->set('provider', $provider);
+ }
+
}
diff --git a/bin/templates/mfa/phone/verify.php b/bin/templates/mfa/phone/verify.php
new file mode 100644
--- /dev/null
+++ b/bin/templates/mfa/phone/verify.php
@@ -0,0 +1,43 @@
+
+<div class="spacer large"></div>
+
+<div class="row l5">
+ <div class="span l2">
+ <h1 class="text:grey-300">Enter the two factor token you received</h1>
+ <p>
+ <small>
+ This section requires an additional and higher authentication than the
+ current one. Please select a way to verify your identity further.
+ </small>
+ </p>
+ <p>
+ <small>
+ You have not been logged out. This is just to prevent changes to the
+ account to be made without your consent.
+ </small>
+ </p>
+ </div>
+ <div class="span l3">
+ <div>
+ <div class="material soft unpadded">
+ <form method="POST" action="<?= url('twofactor', 'challenge', $provider->_id, ['returnto' => $_GET['returnto']]) ?>">
+ <div class="padded">
+ <h2>Enter the token</h2>
+ <p>
+ <small>
+ Please enter the token into the box below.
+ </small>
+ </p>
+ <input type="text" name="secret" class="frm-ctrl">
+ </div>
+ <div class="form-footer">
+ <div class="padded align-right">
+ <input type="submit" class="button">
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+ <div class="spacer medium"></div>
+ </div>
+</div>

File Metadata

Mime Type
text/plain
Expires
Apr 12 2021, 3:49 AM (9 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5847
Default Alt Text
D595.id.diff (4 KB)

Event Timeline