mirror of
https://github.com/openvk/openvk
synced 2024-11-11 01:19:53 +03:00
feat(OAuth): add oauth flow
This commit is contained in:
parent
0b80c0a6a8
commit
2bdb4f03d0
5 changed files with 251 additions and 0 deletions
|
@ -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("<b>Error:</b> redirect_uri and client_name params are required.");
|
||||
|
||||
if($url != "about:blank") {
|
||||
if(!filter_var($url, FILTER_VALIDATE_URL))
|
||||
exit("<b>Error:</b> Invalid URL passed to redirect_uri.");
|
||||
|
||||
$parsedUrl = (object) parse_url($url);
|
||||
if($parsedUrl->scheme != 'https' && $parsedUrl->scheme != 'http')
|
||||
exit("<b>Error:</b> 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("<b>Error:</b> 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;
|
||||
}
|
||||
}
|
||||
|
|
193
Web/Presenters/templates/VKAPI/OAuthLogin.xml
Normal file
193
Web/Presenters/templates/VKAPI/OAuthLogin.xml
Normal file
|
@ -0,0 +1,193 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Получение доступа | OpenVK</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: sans-serif;
|
||||
background-color: #ebedf0;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 10px #d4d6d8;
|
||||
padding: 13px 0;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
header > div {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-width: 620px;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#ovkUser a:not(#pfpLink) {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#ovkUser img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 100%;
|
||||
vertical-align: middle;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
#ovkLogo a {
|
||||
display: flex;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
background: #606060;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 21px;
|
||||
font-weight: 600;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
body > div {
|
||||
width: 100%;
|
||||
max-width: 620px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
main {
|
||||
border: 1px solid #e1e3e6;
|
||||
background-color: #fff;
|
||||
padding: 16px;
|
||||
border-radius: 18px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
#authHeading, #authExplainer {
|
||||
color: #818c99;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
:is(#authHeading, #authExplainer) b {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#authButtons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#authButtons a {
|
||||
color: #818c99;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#authButtons a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#authButtons button {
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
border: none;
|
||||
background-color: #606060;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
padding: 7px;
|
||||
border-radius: 7px;
|
||||
font-size: 15px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div>
|
||||
<div style="width: 85px;">
|
||||
</div>
|
||||
<div id="ovkLogo">
|
||||
<a href="/" target="_blank">O</a>
|
||||
</div>
|
||||
<div id="ovkUser">
|
||||
<a href="/logout?hash={rawurlencode($csrfToken)}">{_header_log_out}</a>
|
||||
<a id="pfpLink" href="/id0" target="_blank">
|
||||
<img src="{$thisUser->getAvatarUrl('miniscule')}" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div>
|
||||
<main>
|
||||
<div id="authHeading">
|
||||
{_app},
|
||||
<b>
|
||||
{if is_null($origin)}
|
||||
{tr("identifies_itself_as", $clientName)}{else}
|
||||
{tr("located_at_url", $origin)}{/if}</b>, {_wants_your_token}.
|
||||
</div>
|
||||
|
||||
<div id="authExplainer">
|
||||
<b>{_app_will_have_access_to}</b><br/>
|
||||
{_oauth_scope_all|noescape}.
|
||||
</div>
|
||||
|
||||
<div id="authButtons">
|
||||
<button id="authAllow">{_oauth_grant}</button>
|
||||
<a id="authDeny" href="javascript:void(0)">{_oauth_deny}</a>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
{script "js/node_modules/msgpack-lite/dist/msgpack.min.js"}
|
||||
{script "js/al_api.js"}
|
||||
<script>
|
||||
//<![CDATA[
|
||||
let clientName = {$clientName};
|
||||
let usePostMessage = {$usePostMessage} && window.opener != null;
|
||||
let acceptsStale = {$acceptsStale};
|
||||
let origin = {$origin};
|
||||
let redirectUri = {$redirectUri};
|
||||
|
||||
document.querySelector("#authDeny").addEventListener("click", () => {
|
||||
if (usePostMessage) {
|
||||
window.opener.postMessage({
|
||||
error: 'access_denied',
|
||||
error_reason: 'user_denied',
|
||||
error_description: 'User denied your request'
|
||||
}, origin);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.href = redirectUri + 'error=access_denied&error_reason=user_denied&error_description=User%20denied%20your%20request';
|
||||
});
|
||||
|
||||
document.querySelector("#authAllow").addEventListener("click", async () => {
|
||||
let response = await API.Apps.getRegularToken(clientName, acceptsStale);
|
||||
let ret = {
|
||||
access_token: response.token,
|
||||
expires_in: 0,
|
||||
user_id: {$thisUser->getId()},
|
||||
is_stale: response.is_stale
|
||||
};
|
||||
|
||||
if (usePostMessage) {
|
||||
window.opener.postMessage(ret, origin);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.href = redirectUri + (new URLSearchParams(ret)).toString();
|
||||
});
|
||||
//]]>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -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"
|
||||
|
|
|
@ -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, <b>your e-mail</b>, polls, communities, discussions, notes, <b>payment method</b>, likes and comments";
|
||||
"oauth_grant" = "Allow";
|
||||
"oauth_deny" = "Deny";
|
||||
|
||||
/* Sorting */
|
||||
|
||||
"sort_randomly" = "Sort randomly";
|
||||
|
|
|
@ -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" = "информация страницы, обновление статуса, список друзей, фотографии, публикация записей, аудиозаписи, видео, уведомления, сообщения, подарки, <b>ваш адрес электронной почты</b>, опросы, группы, обсуждения, заметки, <b>голоса</b>, лайки и комментарии";
|
||||
"oauth_grant" = "Разрешить";
|
||||
"oauth_deny" = "Отмена";
|
||||
|
||||
/* Sorting */
|
||||
|
||||
"sort_randomly" = "Сортировать случайно";
|
||||
|
|
Loading…
Reference in a new issue