RVRNEXT-2 add controller and view for oauth
This commit is contained in:
parent
89c7d3b0ea
commit
35b7db81b2
124
src/Controller/OAuthLoginController.php
Normal file
124
src/Controller/OAuthLoginController.php
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?php namespace RVR\Controller;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
use RVR\PersistentData\Model\OAuthToken;
|
||||||
|
use RVR\Repository\OAuthTokenRepository;
|
||||||
|
use RVR\Repository\UserRepository;
|
||||||
|
use RVR\PersistentData\Model\User;
|
||||||
|
use SokoWeb\Interfaces\Request\IRequest;
|
||||||
|
use SokoWeb\Interfaces\Response\IContent;
|
||||||
|
use SokoWeb\Interfaces\Response\IRedirect;
|
||||||
|
use SokoWeb\Response\Redirect;
|
||||||
|
use SokoWeb\PersistentData\PersistentDataManager;
|
||||||
|
use SokoWeb\Response\HtmlContent;
|
||||||
|
use SokoWeb\Response\JsonContent;
|
||||||
|
|
||||||
|
class OAuthLoginController
|
||||||
|
{
|
||||||
|
private IRequest $request;
|
||||||
|
|
||||||
|
private PersistentDataManager $pdm;
|
||||||
|
|
||||||
|
public function __construct(IRequest $request)
|
||||||
|
{
|
||||||
|
$this->request = $request;
|
||||||
|
$this->pdm = new PersistentDataManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function startOauth()
|
||||||
|
{
|
||||||
|
$redirectUri = $this->request->query('redirect_uri');
|
||||||
|
$state = $this->request->query('state');
|
||||||
|
$nonce = $this->request->query('nonce');
|
||||||
|
|
||||||
|
if (!$redirectUri || !$state) {
|
||||||
|
return new HtmlContent('oauth/oauth_error', ['error' => 'An invalid request was made. Please start authentication again.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->request->session()->set('oauth_state', [
|
||||||
|
'redirect_uri' => $redirectUri,
|
||||||
|
'state' => $state,
|
||||||
|
'nonce' => $nonce === null ? '' : $nonce
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->request->session()->set('redirect_after_login', \Container::$routeCollection->getRoute('oauth-finish')->generateLink());
|
||||||
|
|
||||||
|
return new Redirect(\Container::$routeCollection->getRoute('login')->generateLink(), IRedirect::TEMPORARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function finishOauth()
|
||||||
|
{
|
||||||
|
$oauthState = $this->request->session()->get('oauth_state');
|
||||||
|
if ($oauthState === null) {
|
||||||
|
return new HtmlContent('oauth/oauth_error', ['error' => 'An invalid request was made. Please start authentication again.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->request->session()->delete('oauth_state');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ?User $user
|
||||||
|
*/
|
||||||
|
$user = $this->request->user();
|
||||||
|
if ($user === null) {
|
||||||
|
return new HtmlContent('oauth/oauth_error', ['error' => 'You are not logged in. Please start authentication again.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$code = bin2hex(random_bytes(16));
|
||||||
|
|
||||||
|
$token = new OAuthToken();
|
||||||
|
$token->setNonce($oauthState['nonce']);
|
||||||
|
$token->setUser($user);
|
||||||
|
$token->setCode($code);
|
||||||
|
$token->setCreatedDate(new DateTime());
|
||||||
|
$token->setExpiresDate(new DateTime('+5 minutes'));
|
||||||
|
$this->pdm->saveToDb($token);
|
||||||
|
|
||||||
|
$redirectUri = $oauthState['redirect_uri'];
|
||||||
|
$additionalUriParams = [
|
||||||
|
'state' => $oauthState['state'],
|
||||||
|
'code' => $code
|
||||||
|
];
|
||||||
|
$and = (strpos($redirectUri, '?') !== false) ? '&' : '?';
|
||||||
|
$finalRedirectUri = $redirectUri . $and . http_build_query($additionalUriParams);
|
||||||
|
|
||||||
|
return new Redirect($finalRedirectUri, IRedirect::TEMPORARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToken(): ?IContent
|
||||||
|
{
|
||||||
|
$oAuthTokenRepository = new OAuthTokenRepository();
|
||||||
|
$userRepository = new UserRepository();
|
||||||
|
$token = $oAuthTokenRepository->getByCode($this->request->query('code'));
|
||||||
|
|
||||||
|
if ($token === null || $token->getExpiresDate() < new DateTime()) {
|
||||||
|
return new JsonContent([
|
||||||
|
'error' => 'The provided code is invalid.'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $userRepository->getById($token->getUserId());
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
'iss' => $_ENV['APP_URL'],
|
||||||
|
'iat' => (int)$token->getCreatedDate()->format('U'),
|
||||||
|
'nbf' => (int)$token->getCreatedDate()->format('U'),
|
||||||
|
'exp' => (int)$token->getExpiresDate()->format('U'),
|
||||||
|
'nonce' => $token->getNonce(),
|
||||||
|
'sub' => $user->getId(),
|
||||||
|
'email' => $user->getEmail()
|
||||||
|
];
|
||||||
|
$privateKey = file_get_contents(ROOT . '/' . $_ENV['JWT_RSA_PRIVATE_KEY']);
|
||||||
|
$jwt = JWT::encode($payload, $privateKey, 'RS256');
|
||||||
|
|
||||||
|
return new JsonContent([
|
||||||
|
'id_token' => $jwt
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJwtPublicKey(): IContent
|
||||||
|
{
|
||||||
|
$publicKey = file_get_contents(ROOT . '/' . $_ENV['JWT_RSA_PUBLIC_KEY']);
|
||||||
|
return new JsonContent(['pubkey' => $publicKey]);
|
||||||
|
}
|
||||||
|
}
|
8
views/oauth/oauth_error.php
Normal file
8
views/oauth/oauth_error.php
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@extends(templates/layout_normal)
|
||||||
|
|
||||||
|
@section(main)
|
||||||
|
<h2>OAuth error</h2>
|
||||||
|
<div class="box">
|
||||||
|
<p class="error justify"><?= $error ?></p>
|
||||||
|
</div>
|
||||||
|
@endsection
|
Loading…
Reference in New Issue
Block a user