2023-04-11 17:45:08 +02:00
|
|
|
<?php namespace RVR\Controller;
|
|
|
|
|
|
|
|
use DateTime;
|
|
|
|
use RVR\PersistentData\Model\OAuthToken;
|
|
|
|
use RVR\PersistentData\Model\User;
|
2023-04-12 00:02:47 +02:00
|
|
|
use RVR\Repository\OAuthClientRepository;
|
2023-04-11 17:45:08 +02:00
|
|
|
use SokoWeb\Interfaces\Authorization\ISecured;
|
|
|
|
use SokoWeb\Interfaces\Request\IRequest;
|
|
|
|
use SokoWeb\Interfaces\Response\IRedirect;
|
|
|
|
use SokoWeb\Response\Redirect;
|
|
|
|
use SokoWeb\PersistentData\PersistentDataManager;
|
|
|
|
use SokoWeb\Response\HtmlContent;
|
|
|
|
|
|
|
|
class OAuthAuthController implements ISecured
|
|
|
|
{
|
|
|
|
private IRequest $request;
|
|
|
|
|
|
|
|
private PersistentDataManager $pdm;
|
|
|
|
|
2023-04-12 00:02:47 +02:00
|
|
|
private OAuthClientRepository $oAuthClientRepository;
|
|
|
|
|
2023-04-11 17:45:08 +02:00
|
|
|
public function __construct(IRequest $request)
|
|
|
|
{
|
|
|
|
$this->request = $request;
|
|
|
|
$this->pdm = new PersistentDataManager();
|
2023-04-12 00:02:47 +02:00
|
|
|
$this->oAuthClientRepository = new OAuthClientRepository();
|
2023-04-11 17:45:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function authorize(): bool
|
|
|
|
{
|
|
|
|
return $this->request->user() !== null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function auth()
|
|
|
|
{
|
|
|
|
$redirectUri = $this->request->query('redirect_uri');
|
2023-04-12 00:02:47 +02:00
|
|
|
$clientId = $this->request->query('client_id');
|
2023-04-11 17:45:08 +02:00
|
|
|
$scope = $this->request->query('scope') ? $this->request->query('scope'): '';
|
|
|
|
$state = $this->request->query('state');
|
|
|
|
$nonce = $this->request->query('nonce') ? $this->request->query('nonce'): '';
|
|
|
|
|
2023-04-12 00:02:47 +02:00
|
|
|
if (!$clientId || !$redirectUri || !$state) {
|
2023-04-11 17:45:08 +02:00
|
|
|
return new HtmlContent('oauth/oauth_error', ['error' => 'An invalid request was made. Please start authentication again.']);
|
|
|
|
}
|
|
|
|
|
2023-04-12 00:02:47 +02:00
|
|
|
$client = $this->oAuthClientRepository->getByClientId($clientId);
|
|
|
|
if ($client === null) {
|
|
|
|
return new HtmlContent('oauth/oauth_error', ['error' => 'Client is not authorized.']);
|
|
|
|
}
|
|
|
|
|
|
|
|
$redirectUriParsed = parse_url($redirectUri);
|
2023-04-12 02:03:15 +02:00
|
|
|
$redirectUriBase = $redirectUriParsed['scheme'] . '://' . $redirectUriParsed['host'] . $redirectUriParsed['path'];
|
2023-04-12 00:02:47 +02:00
|
|
|
$redirectUriQuery = [];
|
|
|
|
if (isset($redirectUriParsed['query'])) {
|
|
|
|
parse_str($redirectUriParsed['query'], $redirectUriQuery);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!in_array($redirectUriBase, $client->getRedirectUrisArray())) {
|
|
|
|
return new HtmlContent('oauth/oauth_error', ['error' => 'Redirect URI \'' . $redirectUriBase .'\' is not allowed for this client.']);
|
|
|
|
}
|
2023-04-11 17:45:08 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var ?User $user
|
|
|
|
*/
|
|
|
|
$user = $this->request->user();
|
|
|
|
$code = bin2hex(random_bytes(16));
|
|
|
|
$accessToken = bin2hex(random_bytes(16));
|
|
|
|
|
|
|
|
$token = new OAuthToken();
|
|
|
|
$token->setNonce($nonce);
|
|
|
|
$token->setScope($scope);
|
|
|
|
$token->setUser($user);
|
|
|
|
$token->setCode($code);
|
|
|
|
$token->setAccessToken($accessToken);
|
|
|
|
$token->setCreatedDate(new DateTime());
|
|
|
|
$token->setExpiresDate(new DateTime('+5 minutes'));
|
|
|
|
$this->pdm->saveToDb($token);
|
|
|
|
|
2023-04-12 00:02:47 +02:00
|
|
|
$redirectUriQuery = array_merge($redirectUriQuery, [
|
2023-04-11 17:45:08 +02:00
|
|
|
'state' => $state,
|
|
|
|
'code' => $code
|
2023-04-12 00:02:47 +02:00
|
|
|
]);
|
|
|
|
$finalRedirectUri = $redirectUriBase . '?' . http_build_query($redirectUriQuery);
|
2023-04-11 17:45:08 +02:00
|
|
|
|
|
|
|
return new Redirect($finalRedirectUri, IRedirect::TEMPORARY);
|
|
|
|
}
|
|
|
|
}
|