diff options
| author | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
|---|---|---|
| committer | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
| commit | 4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch) | |
| tree | 5c07151ae61276d334e88f6309c30d439a85c12e /lib/classes/JsonApi/Middlewares | |
| parent | da0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff) | |
| parent | 97a188592c679890a25c37ab78463add76a52ff7 (diff) | |
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/classes/JsonApi/Middlewares')
3 files changed, 35 insertions, 150 deletions
diff --git a/lib/classes/JsonApi/Middlewares/Auth/OAuth1Strategy.php b/lib/classes/JsonApi/Middlewares/Auth/OAuth1Strategy.php deleted file mode 100644 index 113ee09..0000000 --- a/lib/classes/JsonApi/Middlewares/Auth/OAuth1Strategy.php +++ /dev/null @@ -1,114 +0,0 @@ -<?php - -namespace JsonApi\Middlewares\Auth; - -use Psr\Http\Message\ResponseInterface as Response; -use Psr\Http\Message\ServerRequestInterface as Request; - -class OAuth1Strategy implements Strategy -{ - /** @var callable */ - protected $authenticator; - - /** @var Request */ - protected $request; - - /** @var ?\User */ - protected $user; - - /** - * @param callable $authenticator - */ - public function __construct(Request $request, $authenticator) - { - $this->request = $request; - $this->authenticator = $authenticator; - - \OAuthStore::instance('PDO', ['conn' => \DBManager::get()]); - } - - public function check() - { - return !is_null($this->user()); - } - - public function user() - { - if (!is_null($this->user)) { - return $this->user; - } - - $this->user = $this->detect(); - - return $this->user; - } - - public function addChallenge(Response $response) - { - return $response; //->withHeader('WWW-Authenticate', sprintf('Basic realm="%s"', 'Stud.IP JSON-API')); - } - - private function detect(): ?\User - { - if (!\OAuthRequestVerifier::requestIsSigned()) { - return null; - } - - $uri = (string) $this->request->getUri(); - $method = $this->request->getMethod(); - - if ('GET' === strtoupper(($method))) { - $parameters = (array) $this->request->getQueryParams(); - } elseif ('POST' === strtoupper(($method))) { - $parameters = (array) $this->request->getParsedBody(); - } else { - $parameters = []; - } - $parameters = $this->getParamsFromAuthorizationHeader($this->request, $parameters); - - $req = new \OAuthRequestVerifier($uri, $method, $parameters); - - // Check oauth timestamp and deny access if timestamp is outdated - if ($req->getParam('oauth_timestamp') < strtotime('-6 hours')) { - return null; - } - - $result = $req->verifyExtended('access'); - - $query = 'SELECT user_id FROM api_oauth_user_mapping WHERE oauth_id = ?'; - $statement = \DBManager::get()->prepare($query); - $statement->execute([$result['user_id']]); - - if (!$userId = $statement->fetchColumn()) { - return null; - } - - /** @var \User */ - return \User::find($userId); - } - - private function getParamsFromAuthorizationHeader(Request $request, array $params): array - { - if ($request->hasHeader('Authorization')) { - $auth = $request->getHeaderLine('Authorization'); - if (0 == strncasecmp($auth, 'OAuth', 4)) { - foreach (explode(',', substr($auth, 6)) as $v) { - if (!strpos($v, '=')) { - continue; - } - $v = trim($v); - list($name, $value) = explode('=', $v, 2); - if (!empty($value) && '"' == $value[0] && '"' == substr($value, -1)) { - $value = substr(substr($value, 1), 0, -1); - } - - if (0 != strcasecmp($name, 'realm')) { - $params[$name] = $value; - } - } - } - } - - return $params; - } -} diff --git a/lib/classes/JsonApi/Middlewares/Authentication.php b/lib/classes/JsonApi/Middlewares/Authentication.php index de92e15..bbcfef1 100644 --- a/lib/classes/JsonApi/Middlewares/Authentication.php +++ b/lib/classes/JsonApi/Middlewares/Authentication.php @@ -15,22 +15,21 @@ class Authentication // $user = $request->getAttribute(Authentication::USER_KEY); const USER_KEY = 'studip-user'; - // a callable accepting two arguments username and password and - // returning either null or a Stud.IP user object - /** @var callable */ - private $authenticator; - /** * Der Konstruktor. * - * @param callable $authenticator ein Callable, das den Nutzernamen und + * @param \Closure $authenticator eine Closure, die den Nutzernamen und * das Passwort als Argumente erhält und * damit entweder einen Stud.IP-User-Objekt * oder null zurückgibt + * @param array $excluded_strategies */ - public function __construct($authenticator) - { - $this->authenticator = $authenticator; + public function __construct( + // a callable accepting two arguments username and password and + // returning either null or a Stud.IP user object + private readonly \Closure $authenticator, + private readonly array $excluded_strategies = [] + ) { } /** @@ -45,12 +44,7 @@ class Authentication */ public function __invoke(Request $request, RequestHandler $handler) { - $guards = [ - new Auth\SessionStrategy(), - new Auth\HttpBasicAuthStrategy($request, $this->authenticator), - new Auth\OAuth2Strategy($request, $this->authenticator), - new Auth\OAuth1Strategy($request, $this->authenticator), - ]; + $guards = $this->getGuards($request); foreach ($guards as $guard) { if ($guard->check()) { @@ -101,4 +95,24 @@ class Authentication return $request->withAttribute(self::USER_KEY, $user); } + + /** + * @param Request $request + * + * @return array + */ + protected function getGuards(Request $request): array + { + $guards = [ + 'session' => new Auth\SessionStrategy(), + 'basic' => new Auth\HttpBasicAuthStrategy($request, $this->authenticator), + 'oauth2' => new Auth\OAuth2Strategy($request, $this->authenticator), + ]; + + foreach ($this->excluded_strategies as $strategy) { + unset($guards[$strategy]); + } + + return $guards; + } } diff --git a/lib/classes/JsonApi/Middlewares/StudipMockNavigation.php b/lib/classes/JsonApi/Middlewares/StudipMockNavigation.php index 34225d4..0883809 100644 --- a/lib/classes/JsonApi/Middlewares/StudipMockNavigation.php +++ b/lib/classes/JsonApi/Middlewares/StudipMockNavigation.php @@ -18,53 +18,38 @@ class DummyNavigation extends \Navigation implements \ArrayAccess /** * ArrayAccess: Check whether the given offset exists. - * - * @todo Add bool return type when Stud.IP requires PHP8 minimal */ - #[ReturnTypeWillChange] - public function offsetExists($offset) + public function offsetExists($offset): bool { return true; } /** * ArrayAccess: Get the value at the given offset. - * - * @todo Add mixed return type when Stud.IP requires PHP8 minimal */ - #[\ReturnTypeWillChange] - public function offsetGet($offset) + public function offsetGet($offset): mixed { return $this; } /** * ArrayAccess: Set the value at the given offset. - * - * @todo Add void return type when Stud.IP requires PHP8 minimal */ - #[\ReturnTypeWillChange] - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { } /** * ArrayAccess: Delete the value at the given offset. - * - * @todo Add void return type when Stud.IP requires PHP8 minimal */ - #[\ReturnTypeWillChange] - public function offsetUnset($offset) + public function offsetUnset($offset): void { } /** - * IteratorAggregate: Create interator for request parameters. - * - * @todo Add \Traversable return type when Stud.IP requires PHP8 minimal + * IteratorAggregate: Create iterator for request parameters. */ - #[\ReturnTypeWillChange] - public function getIterator() + public function getIterator(): \Traversable { return new \ArrayIterator(); } |
