Merge pull request #1521 from nextcloud/enh/noid/authorize-deny-popup

confirmation popup
master
Maxence Lange 2022-11-21 15:31:44 -01:00 zatwierdzone przez GitHub
commit 72be817000
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
6 zmienionych plików z 210 dodań i 11 usunięć

Wyświetl plik

@ -70,6 +70,7 @@ return [
['name' => 'OAuth#nodeinfo2', 'url' => '/.well-known/nodeinfo/2.0', 'verb' => 'GET'],
['name' => 'OAuth#apps', 'url' => '/api/v1/apps', 'verb' => 'POST'],
['name' => 'OAuth#authorize', 'url' => '/oauth/authorize', 'verb' => 'GET'],
['name' => 'OAuth#authorizing', 'url' => '/oauth/authorize', 'verb' => 'POST'],
['name' => 'OAuth#token', 'url' => '/oauth/token', 'verb' => 'POST'],
// Api for 3rd party

Wyświetl plik

@ -45,6 +45,8 @@ use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUserSession;
@ -59,6 +61,7 @@ class OAuthController extends Controller {
private ClientService $clientService;
private ConfigService $configService;
private LoggerInterface $logger;
private IInitialState $initialState;
public function __construct(
IRequest $request,
@ -69,7 +72,8 @@ class OAuthController extends Controller {
CacheActorService $cacheActorService,
ClientService $clientService,
ConfigService $configService,
LoggerInterface $logger
LoggerInterface $logger,
IInitialState $initialState
) {
parent::__construct(Application::APP_NAME, $request);
@ -81,6 +85,7 @@ class OAuthController extends Controller {
$this->clientService = $clientService;
$this->configService = $configService;
$this->logger = $logger;
$this->initialState = $initialState;
$body = file_get_contents('php://input');
$logger->debug('[OAuthController] input: ' . $body);
@ -173,13 +178,47 @@ class OAuthController extends Controller {
string $redirect_uri,
string $response_type,
string $scope = 'read'
): Response {
$user = $this->userSession->getUser();
// check actor exists
$this->accountService->getActorFromUserId($user->getUID());
if ($response_type !== 'code') {
throw new ClientNotFoundException('invalid response type');
}
// check client exists in db
$client = $this->clientService->getFromClientId($client_id);
$this->initialState->provideInitialState('appName', $client->getAppName());
return new TemplateResponse(Application::APP_NAME, 'oauth2', [
'request' =>
[
'clientId' => $client_id,
'redirectUri' => $redirect_uri,
'responseType' => $response_type,
'scope' => $scope
]
]);
}
/**
* @NoAdminRequired
*/
public function authorizing(
string $client_id,
string $redirect_uri,
string $response_type,
string $scope = 'read'
): DataResponse {
try {
$user = $this->userSession->getUser();
$account = $this->accountService->getActorFromUserId($user->getUID());
if ($response_type !== 'code') {
return new DataResponse(['error' => 'invalid_type'], Http::STATUS_BAD_REQUEST);
throw new ClientNotFoundException('invalid response type');
}
$client = $this->clientService->getFromClientId($client_id);
@ -205,18 +244,12 @@ class OAuthController extends Controller {
// TODO : finalize result if no redirect_url
return new DataResponse(
[
'code' => $code,
// 'access_token' => '',
// "token_type" => "Bearer",
// "scope" => "read write follow push",
// "created_at" => 1573979017
], Http::STATUS_OK
['code' => $code], Http::STATUS_OK
);
} catch (Exception $e) {
$this->logger->notice($e->getMessage() . ' ' . get_class($e));
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_UNAUTHORIZED);
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
}

38
src/oauth.js 100644
Wyświetl plik

@ -0,0 +1,38 @@
/**
* @copyright 2022 Carl Schwan <carl@carlschwan.eu>
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import Vue from 'vue'
import OAuth2Authorize from './views/OAuth2Authorize.vue'
// CSP config for webpack dynamic chunk loading
// eslint-disable-next-line
__webpack_nonce__ = btoa(OC.requestToken)
// Correct the root of the app for chunk loading
// OC.linkTo matches the apps folders
// eslint-disable-next-line
__webpack_public_path__ = OC.linkTo('social', 'js/')
Vue.prototype.t = t
Vue.prototype.n = n
Vue.prototype.OC = OC
Vue.prototype.OCA = OCA
new Vue({
render: h => h(OAuth2Authorize),
}).$mount('#social-oauth2')

Wyświetl plik

@ -0,0 +1,98 @@
<!--
- @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<template>
<div class="wrapper">
<form class="guest-box" method="post">
<h1>{{ t('social', 'Authorization required') }}</h1>
<p>
{{ t('social', '{appDisplayName} would like permission to access your account. It is a third party application.', {appDisplayName: appName}) }}
<b>{{ t('social', 'If you do not trust it, then you should not authorize it.') }}</b>
</p>
<input type="hidden"
name="requesttoken"
:value="OC.requestToken">
<div class="button-row">
<NcButton type="primary" nativeType="submit">
{{ t('social', 'Authorize') }}
</NcButton>
<NcButton type="error" :href="homeUrl">
{{ t('social', 'Deny') }}
</NcButton>
</div>
</form>
</div>
</template>
<script>
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import { loadState } from '@nextcloud/initial-state'
import { generateUrl } from '@nextcloud/router'
export default {
name: 'OAuth2Authorize',
components: {
NcButton,
},
data() {
return {
appName: loadState('social', 'appName'),
}
},
computed: {
homeUrl() {
return generateUrl('/apps/social/')
},
},
}
</script>
<style lang="scss" scopped>
.wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
}
.guest-box {
color: var(--color-main-text);
background-color: var(--color-main-background);
padding: 1rem;
border-radius: var(--border-radius-large);
box-shadow: 0 0 10px var(--color-box-shadow);
display: inline-block;
max-width: 600px;
h1 {
font-weight: bold;
text-align: center;
font-size: 20px;
margin-bottom: 12px;
line-height: 140%;
}
.button-row {
display: flex;
gap: 1rem;
flex-direction: row;
margin-top: 1rem;
justify-content: end;
}
}
</style>

Wyświetl plik

@ -0,0 +1,28 @@
<?php
/**
* @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
*
* @author Jonas Sulzer <jonas@violoncello.ch>
* @author Julius Härtl <jus@bitgrid.net>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
\OCP\Util::addScript('social', 'social-oauth');
?>
<div id="social-oauth2"></div>

Wyświetl plik

@ -8,7 +8,8 @@ webpackConfig.entry = {
social: path.join(__dirname, 'src', 'main.js'),
ostatus: path.join(__dirname, 'src', 'ostatus.js'),
profilePage: path.join(__dirname, 'src', 'profile.js'),
dashboard: path.join(__dirname, 'src', 'dashboard.js'),
dashboard: path.join(__dirname, 'src', 'dashboard.js'),
oauth: path.join(__dirname, 'src', 'oauth.js'),
}
module.exports = webpackConfig