diff --git a/Web/Presenters/VKAPIPresenter.php b/Web/Presenters/VKAPIPresenter.php
index 1247d83d..e906ce50 100644
--- a/Web/Presenters/VKAPIPresenter.php
+++ b/Web/Presenters/VKAPIPresenter.php
@@ -318,4 +318,42 @@ final class VKAPIPresenter extends OpenVKPresenter
header("Content-Length: $size");
exit($payload);
}
+
+ function renderOAuthLogin() {
+ $this->assertUserLoggedIn();
+
+ $client = $this->queryParam("client_name");
+ $postmsg = $this->queryParam("prefers_postMessage") ?? '0';
+ $stale = $this->queryParam("accepts_stale") ?? '0';
+ $origin = NULL;
+ $url = $this->queryParam("redirect_uri");
+ if(is_null($url) || is_null($client))
+ exit("Error: redirect_uri and client_name params are required.");
+
+ if($url != "about:blank") {
+ if(!filter_var($url, FILTER_VALIDATE_URL))
+ exit("Error: Invalid URL passed to redirect_uri.");
+
+ $parsedUrl = (object) parse_url($url);
+ if($parsedUrl->scheme != 'https' && $parsedUrl->scheme != 'http')
+ exit("Error: redirect_uri should either point to about:blank or to a web resource.");
+
+ $origin = "$parsedUrl->scheme://$parsedUrl->host";
+ if(!is_null($parsedUrl->port ?? NULL))
+ $origin .= ":$parsedUrl->port";
+
+ $url .= strpos($url, '?') === false ? '?' : '&';
+ } else {
+ $url .= "#";
+ if($postmsg == '1') {
+ exit("Error: prefers_postMessage can only be set if redirect_uri is not about:blank");
+ }
+ }
+
+ $this->template->clientName = $client;
+ $this->template->usePostMessage = $postmsg == '1';
+ $this->template->acceptsStale = $stale == '1';
+ $this->template->origin = $origin;
+ $this->template->redirectUri = $url;
+ }
}
diff --git a/Web/Presenters/templates/VKAPI/OAuthLogin.xml b/Web/Presenters/templates/VKAPI/OAuthLogin.xml
new file mode 100644
index 00000000..40cf10d5
--- /dev/null
+++ b/Web/Presenters/templates/VKAPI/OAuthLogin.xml
@@ -0,0 +1,193 @@
+
+
+
+
+ Получение доступа | OpenVK
+
+
+
+
+
+
+
+
+ {_app},
+
+ {if is_null($origin)}
+ {tr("identifies_itself_as", $clientName)}{else}
+ {tr("located_at_url", $origin)}{/if}, {_wants_your_token}.
+
+
+
+ {_app_will_have_access_to}
+ {_oauth_scope_all|noescape}.
+
+
+
+
+
+
+ {script "js/node_modules/msgpack-lite/dist/msgpack.min.js"}
+ {script "js/al_api.js"}
+
+
+
diff --git a/Web/routes.yml b/Web/routes.yml
index d4496f03..ac0189ac 100644
--- a/Web/routes.yml
+++ b/Web/routes.yml
@@ -373,6 +373,8 @@ routes:
handler: "VKAPI->route"
- url: "/token"
handler: "VKAPI->tokenLogin"
+ - url: "/authorize"
+ handler: "VKAPI->OAuthLogin"
- url: "/admin/sandbox"
handler: "About->sandbox"
- url: "/admin/chandler/groups"
diff --git a/locales/en.strings b/locales/en.strings
index 697c95b5..e44313e9 100644
--- a/locales/en.strings
+++ b/locales/en.strings
@@ -775,6 +775,15 @@
"disable_2fa" = "Turn off 2FA";
"viewing" = "View";
+/* OAuth */
+"identifies_itself_as" = "that identifies itself as $1";
+"located_at_url" = "located at $1";
+"wants_your_token" = "wants to access your account";
+"app_will_have_access_to" = "App will have access to:";
+"oauth_scope_all" = "profile information, status, list of friends, photos, wall posts, audios, videos, notifications, fishing rod handle, messages, gifts, your e-mail, polls, communities, discussions, notes, payment method, likes and comments";
+"oauth_grant" = "Allow";
+"oauth_deny" = "Deny";
+
/* Sorting */
"sort_randomly" = "Sort randomly";
diff --git a/locales/ru.strings b/locales/ru.strings
index b88d8d05..1220387f 100644
--- a/locales/ru.strings
+++ b/locales/ru.strings
@@ -737,6 +737,15 @@
"disable_2fa" = "Отключить 2FA";
"viewing" = "Просмотреть";
+/* OAuth */
+"identifies_itself_as" = "идентифицирующее себя как $1";
+"located_at_url" = "располагающееся по адресу $1";
+"wants_your_token" = "запрашивает доступ к вашему аккаунту";
+"app_will_have_access_to" = "Приложению будут доступны:";
+"oauth_scope_all" = "информация страницы, обновление статуса, список друзей, фотографии, публикация записей, аудиозаписи, видео, уведомления, сообщения, подарки, ваш адрес электронной почты, опросы, группы, обсуждения, заметки, голоса, лайки и комментарии";
+"oauth_grant" = "Разрешить";
+"oauth_deny" = "Отмена";
+
/* Sorting */
"sort_randomly" = "Сортировать случайно";