feat: oauth resource(ResourceScopeMiddleware.php)

This commit is contained in:
FoskyM 2023-10-02 05:30:13 +08:00
parent 940a989fb4
commit 95e195a5de
No known key found for this signature in database
GPG key ID: 42C0ED6994AD7E9C
4 changed files with 76 additions and 23 deletions

View file

@ -12,6 +12,7 @@
namespace FoskyM\OAuthCenter; namespace FoskyM\OAuthCenter;
use Flarum\Extend; use Flarum\Extend;
use Flarum\Http\Middleware\AuthenticateWithHeader;
use Flarum\Http\Middleware\CheckCsrfToken; use Flarum\Http\Middleware\CheckCsrfToken;
use FoskyM\OAuthCenter\Middlewares\ResourceScopeMiddleware; use FoskyM\OAuthCenter\Middlewares\ResourceScopeMiddleware;
use FoskyM\OAuthCenter\Middlewares\UnsetCsrfMiddleware; use FoskyM\OAuthCenter\Middlewares\UnsetCsrfMiddleware;
@ -41,14 +42,17 @@ return [
->get('/oauth-scopes', 'oauth.scopes.list', Api\Controller\ListScopeController::class) ->get('/oauth-scopes', 'oauth.scopes.list', Api\Controller\ListScopeController::class)
->post('/oauth-scopes', 'oauth.scopes.create', Api\Controller\CreateScopeController::class) ->post('/oauth-scopes', 'oauth.scopes.create', Api\Controller\CreateScopeController::class)
->patch('/oauth-scopes/{id}', 'oauth.scopes.update', Api\Controller\UpdateScopeController::class) ->patch('/oauth-scopes/{id}', 'oauth.scopes.update', Api\Controller\UpdateScopeController::class)
->delete('/oauth-scopes/{id}', 'oauth.scopes.delete', Api\Controller\DeleteScopeController::class), ->delete('/oauth-scopes/{id}', 'oauth.scopes.delete', Api\Controller\DeleteScopeController::class)
->get('/user', 'user.show', Controllers\ApiUserController::class),
(new Extend\Settings) (new Extend\Settings)
->serializeToForum('foskym-oauth-center.allow_implicit', 'foskym-oauth-center.allow_implicit', 'boolval') ->serializeToForum('foskym-oauth-center.allow_implicit', 'foskym-oauth-center.allow_implicit', 'boolval')
->serializeToForum('foskym-oauth-center.enforce_state', 'foskym-oauth-center.enforce_state', 'boolval') ->serializeToForum('foskym-oauth-center.enforce_state', 'foskym-oauth-center.enforce_state', 'boolval')
->serializeToForum('foskym-oauth-center.require_exact_redirect_uri', 'foskym-oauth-center.require_exact_redirect_uri', 'boolval'), ->serializeToForum('foskym-oauth-center.require_exact_redirect_uri', 'foskym-oauth-center.require_exact_redirect_uri', 'boolval'),
(new Extend\Middleware('api'))
->insertAfter(AuthenticateWithHeader::class, ResourceScopeMiddleware::class),
(new Extend\Middleware('forum')) (new Extend\Middleware('forum'))
->insertBefore(CheckCsrfToken::class, UnsetCsrfMiddleware::class), ->insertBefore(CheckCsrfToken::class, UnsetCsrfMiddleware::class),
(new Extend\Middleware('api'))->add(ResourceScopeMiddleware::class),
]; ];

View file

@ -0,0 +1,49 @@
<?php
/*
* This file is part of foskym/flarum-oauth-center.
*
* Copyright (c) 2023 FoskyM.
*
* For the full copyright and license information, please view the LICENSE.md
* file that was distributed with this source code.
*/
namespace FoskyM\OAuthCenter\Controllers;
use Flarum\User\User;
use Flarum\Http\RequestUtil;
use FoskyM\OAuthCenter\OAuth;
use Illuminate\Support\Arr;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Laminas\Diactoros\Response\JsonResponse;
use Flarum\Settings\SettingsRepositoryInterface;
use Flarum\Group\Group;
class ApiUserController implements RequestHandlerInterface
{
protected $settings;
public function __construct(SettingsRepositoryInterface $settings)
{
$this->settings = $settings;
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$actor = RequestUtil::getActor($request);
$actor = $actor->toArray();
$data = [
'id' => $actor['id'],
'username' => $actor['username'],
'nickname' => $actor['nickname'],
'avatar_url' => $actor['avatar_url'],
'email' => $actor['email'],
'is_email_confirmed' => $actor['is_email_confirmed'],
'joined_at' => $actor['joined_at'],
'last_seen_at' => $actor['last_seen_at'],
'discussion_count' => $actor['discussion_count'],
'comment_count' => $actor['comment_count'],
];
return new JsonResponse($data);
}
}

View file

@ -5,6 +5,7 @@ namespace FoskyM\OAuthCenter\Middlewares;
use Flarum\Foundation\ErrorHandling\ExceptionHandler\IlluminateValidationExceptionHandler; use Flarum\Foundation\ErrorHandling\ExceptionHandler\IlluminateValidationExceptionHandler;
use Flarum\Foundation\ErrorHandling\JsonApiFormatter; use Flarum\Foundation\ErrorHandling\JsonApiFormatter;
use Flarum\Settings\SettingsRepositoryInterface; use Flarum\Settings\SettingsRepositoryInterface;
use Flarum\User\User;
use FoskyM\OAuthCenter\OAuth; use FoskyM\OAuthCenter\OAuth;
use FoskyM\OAuthCenter\Storage; use FoskyM\OAuthCenter\Storage;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
@ -15,11 +16,8 @@ use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
use Flarum\Http\RequestUtil; use Flarum\Http\RequestUtil;
use Flarum\Api\JsonApiResponse;
use Tobscure\JsonApi\Document;
use Tobscure\JsonApi\Exception\Handler\ResponseBag;
use FoskyM\OAuthCenter\Models\Scope; use FoskyM\OAuthCenter\Models\Scope;
class ResourceScopeMiddleware implements MiddlewareInterface class ResourceScopeMiddleware implements MiddlewareInterface
{ {
protected $settings; protected $settings;
@ -29,31 +27,29 @@ class ResourceScopeMiddleware implements MiddlewareInterface
} }
public function process(Request $request, RequestHandlerInterface $handler): Response public function process(Request $request, RequestHandlerInterface $handler): Response
{ {
$path = $request->getUri()->getPath(); if (!$request->getAttribute('originalUri')) {
return $handler->handle($request);
}
$path = $request->getAttribute('originalUri')->getPath();
$token = Arr::get($request->getQueryParams(), 'access_token', ''); $token = Arr::get($request->getQueryParams(), 'access_token', '');
if ($token !== '' && $scope = Scope::get_path_scope($path)) { if ($token !== '' && $scope = Scope::get_path_scope($path)) {
if (strtolower($request->getMethod()) === strtolower($scope->method)) { if (strtolower($request->getMethod()) === strtolower($scope->method)) {
try { try {
$oauth = new OAuth($this->settings); $oauth = new OAuth($this->settings);
$server = $oauth->server(); $server = $oauth->server();
$request = $oauth->request(); $oauth_request = $oauth->request()::createFromGlobals();
if (!$server->verifyResourceRequest($request::createFromGlobals(), null, $scope->scope)) {
if (!$server->verifyResourceRequest($oauth_request, null, $scope->scope)) {
return new JsonResponse(json_decode($server->getResponse()->getResponseBody(), true)); return new JsonResponse(json_decode($server->getResponse()->getResponseBody(), true));
} }
/*$error = new ResponseBag('422', [
[
'status' => '422',
'code' => 'validation_error',
'source' => [
'pointer' => $path,
],
'detail' => 'Yikes! The access token don\'t has the scope.',
],
]);
$document = new Document();
$document->setErrors($error->getErrors());
return new JsonApiResponse($document, $error->getStatus());*/ $token = $server->getAccessTokenData($oauth_request);
$actor = User::find($token['user_id']);
$request = RequestUtil::withActor($request, $actor);
$request = $request->withAttribute('bypassCsrfToken', true);
$request = $request->withoutAttribute('session');
} catch (ValidationException $exception) { } catch (ValidationException $exception) {
$handler = resolve(IlluminateValidationExceptionHandler::class); $handler = resolve(IlluminateValidationExceptionHandler::class);

View file

@ -36,9 +36,13 @@ class OAuth
{ {
return new Request; return new Request;
} }
public function storage(): Storage
{
return new Storage;
}
public function server(): Server public function server(): Server
{ {
$storage = new Storage; $storage = new Storage;
$server = new Server($storage, array( $server = new Server($storage, array(
'allow_implicit' => $this->settings->get('foskym-oauth-center.allow_implicit') == "1", 'allow_implicit' => $this->settings->get('foskym-oauth-center.allow_implicit') == "1",