Ver código fonte

OAuth: Pass request type through provider

Needed to control the behavior of the authorization/registration algorithm without saving data to the session/cookies.
Visman 2 anos atrás
pai
commit
4d837f00c2

+ 1 - 1
app/Controllers/Routing.php

@@ -109,7 +109,7 @@ class Routing
         if (1 === $config->b_oauth_allow) {
             $r->add(
                 $r::PST,
-                '/reglog/redirect',
+                '/reglog/redirect/{type}',
                 'RegLog:redirect',
                 'RegLogRedirect'
             );

+ 1 - 1
app/Models/Pages/Auth.php

@@ -128,7 +128,7 @@ class Auth extends Page
         $save               = $v->save ?? true;
         $redirect           = $v->redirect ?? $this->c->Router->validate($ref, 'Index');
         $this->form         = $this->formLogin($username, (bool) $save, $redirect);
-        $this->formOAuth    = $this->reglogForm();
+        $this->formOAuth    = $this->reglogForm('auth');
 
         return $this;
     }

+ 1 - 1
app/Models/Pages/Profile/OAuth.php

@@ -45,7 +45,7 @@ class OAuth extends Profile
             ]
         );
         $this->form            = $this->formList($args);
-        $this->formOAuth       = $this->reglogForm();
+        $this->formOAuth       = $this->reglogForm('add');
         $this->actionBtns      = $this->btns('edit');
         $this->profileIdSuffix = '-oauth';
 

+ 3 - 3
app/Models/Pages/RegLog.php

@@ -21,7 +21,7 @@ class RegLog extends Page
     /**
      * Обрабатывает нажатие одной из кнопок провайдеров
      */
-    public function redirect(): Page
+    public function redirect(array $args): Page
     {
         if (
             1 !== $this->c->config->b_oauth_allow
@@ -38,7 +38,7 @@ class RegLog extends Page
             $rules[$name] = 'string';
         }
 
-        $v = $this->c->Validator->reset()->addRules($rules);
+        $v = $this->c->Validator->reset()->addRules($rules)->addArguments(['token' => $args]);
 
         if (
             ! $v->validation($_POST)
@@ -47,7 +47,7 @@ class RegLog extends Page
             return $this->c->Message->message('Bad request');
         }
 
-        return $this->c->Redirect->url($this->c->providers->init()->get(\array_key_first($form))->linkAuth);
+        return $this->c->Redirect->url($this->c->providers->init()->get(\array_key_first($form))->linkAuth($args['type']));
     }
 
     /**

+ 5 - 3
app/Models/Pages/RegLogTrait.php

@@ -15,7 +15,7 @@ use function \ForkBB\__;
 
 trait RegLogTrait
 {
-    protected function reglogForm(): array
+    protected function reglogForm(string $type): array
     {
         if (
             1 !== $this->c->config->b_oauth_allow
@@ -35,10 +35,12 @@ trait RegLogTrait
             ];
         }
 
+        $args = ['type' => $type];
+
         return [
-            'action' => $this->c->Router->link('RegLogRedirect'),
+            'action' => $this->c->Router->link('RegLogRedirect', $args),
             'hidden' => [
-                'token' => $this->c->Csrf->create('RegLogRedirect'),
+                'token' => $this->c->Csrf->create('RegLogRedirect', $args),
             ],
             'sets'   => [],
             'btns'   => $btns,

+ 1 - 1
app/Models/Pages/Register.php

@@ -98,7 +98,7 @@ class Register extends Page
         $this->titles       = 'Register';
         $this->robots       = 'noindex';
         $this->form         = $this->formReg($v);
-        $this->formOAuth    = $this->reglogForm();
+        $this->formOAuth    = $this->reglogForm('reg');
 
         return $this;
     }

+ 19 - 3
app/Models/Provider/Driver.php

@@ -12,6 +12,7 @@ namespace ForkBB\Models\Provider;
 
 use ForkBB\Core\Container;
 use ForkBB\Models\Model;
+use InvalidArgumentException;
 use RuntimeException;
 
 abstract class Driver extends Model
@@ -79,12 +80,18 @@ abstract class Driver extends Model
     /**
      * Формирует ссылку авторизации на сервере провайдера
      */
-    protected function getlinkAuth(): string
+    public function linkAuth(string $type): string
     {
+        if ('' == $type) {
+            throw new InvalidArgumentException('Expected non-empty type');
+        } elseif (0 !== \preg_match('%[^a-zA-Z]%', $type)) {
+            throw new InvalidArgumentException('Invalid characters in type');
+        }
+
         $params = [
             'response_type' => 'code',
             'scope'         => $this->scope,
-            'state'         => $this->c->Csrf->createHash($this->origName, ['ip' => $this->c->user->ip]),
+            'state'         => $type . '_' . $this->c->Csrf->createHash($this->origName, ['ip' => $this->c->user->ip, 'type' => $type]),
             'client_id'     => $this->client_id,
             'redirect_uri'  => $this->linkCallback,
         ];
@@ -94,10 +101,19 @@ abstract class Driver extends Model
 
     /**
      * Проверяет правильность state
+     * Запоминает stateType
      */
     protected function verifyState(string $state): bool
     {
-        return $this->c->Csrf->verify($state, $this->origName, ['ip' => $this->c->user->ip]);
+        $state = \explode('_', $state, 2);
+
+        if (2 !== \count($state)) {
+            return false;
+        }
+
+        $this->stateType = $state[0];
+
+        return $this->c->Csrf->verify($state[1], $this->origName, ['ip' => $this->c->user->ip, 'type' => $state[0]]);
     }
 
     /**