This commit is contained in:
Diogo Peralta Cordeiro 2022-01-16 04:31:04 +00:00
parent cb16b627b4
commit 29f53bb698
Signed by: diogo
GPG Key ID: 18D2D35001FBFAB0
4 changed files with 91 additions and 8 deletions

View File

@ -6,6 +6,10 @@ trikoder_oauth2:
encryption_key: '%env(string:OAUTH2_ENCRYPTION_KEY)%' # (Optional) Change this
grant_types:
authorization_code:
enable: true
resource_server:
public_key: '%kernel.project_dir%/var/oauth/public.key'

View File

@ -48,7 +48,6 @@ use App\Core\DB\DB;
use App\Core\I18n\I18n;
use App\Core\Queue\Queue;
use App\Core\Router\Router;
use App\Entity\LocalUser;
use App\Kernel;
use App\Security\EmailVerifier;
use App\Util\Common;
@ -57,6 +56,7 @@ use App\Util\Formatting;
use App\Util\HTML;
use Doctrine\ORM\EntityManagerInterface;
use HtmlSanitizer\SanitizerInterface;
use Nyholm\Psr7\Response;
use Psr\Log\LoggerInterface;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
@ -84,6 +84,7 @@ use SymfonyCasts\Bundle\VerifyEmail\VerifyEmailHelperInterface;
use Trikoder\Bundle\OAuth2Bundle\Event\AuthorizationRequestResolveEvent;
use Trikoder\Bundle\OAuth2Bundle\Event\UserResolveEvent;
use Trikoder\Bundle\OAuth2Bundle\OAuth2Events;
use Trikoder\Bundle\OAuth2Bundle\OAuth2Grants;
use Twig\Environment;
/**
@ -277,7 +278,7 @@ class GNUsocial implements EventSubscriberInterface
Log::debug('cenas: ', [$event, $userProvider, $userPasswordEncoder]);
$user = $userProvider->loadUserByUsername($event->getUsername());
if (null === $user) {
if (\is_null($user)) {
return;
}
@ -290,9 +291,51 @@ class GNUsocial implements EventSubscriberInterface
public function authRequestResolve(AuthorizationRequestResolveEvent $event): void
{
// TODO: if using 3rd party clients, make sure the user approves access
$event->resolveAuthorization(true);
$event->setUser(LocalUser::getById(1));
$request = $this->request;
// only handle post requests for logged-in users:
// get requests will be intercepted and shown the login form
// other verbs we will handle as an authorization denied
// and this implementation ensures a user is set at this point already
if ($request->getMethod() !== 'POST' && \is_null($event->getUser())) {
$event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_DENIED);
return;
}
if (!$request->request->has('action')) {
// 1. successful login, goes to grant page
$content = $this->twig->render('security/grant.html.twig', [
'scopes' => $event->getScopes(),
'client' => $event->getClient(),
'grant' => OAuth2Grants::AUTHORIZATION_CODE,
// very simple way to ensure user gets to this point in the
// flow when granting or denying is to pre-add their credentials
'email' => $request->request->get('email'),
'password' => $request->request->get('password'),
]);
$response = new Response(200, [], $content);
$event->setResponse($response);
} else {
// 2. grant operation, either grants or denies
if ($request->request->get('action') == OAuth2Grants::AUTHORIZATION_CODE) {
$event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED);
} else {
$event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_DENIED);
}
}
if (\is_null($event->getUser())) {
$event->setResponse(new Response(302, [
'Location' => Router::url('security_login', [
'returnUrl' => $request->getUri(),
]),
]));
return;
}
$event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED);
}
/**

View File

@ -157,7 +157,10 @@ class Authenticator extends AbstractFormLoginAuthenticator implements Authentica
$nickname,
);
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
// TODO: Fix the Open Redirect security flaw here.
$targetPath = $request->request->get('returnUrl');
if ($targetPath ??= $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
@ -178,8 +181,8 @@ class Authenticator extends AbstractFormLoginAuthenticator implements Authentica
);
}
protected function getLoginUrl()
protected function getLoginUrl(int $type = Router::ABSOLUTE_PATH): string
{
return Router::url(self::LOGIN_ROUTE);
return Router::url(self::LOGIN_ROUTE, type: $type);
}
}

View File

@ -0,0 +1,33 @@
<form method="post">
{% if app.user %}
<div class="mb-3">
You are logged in as {{ app.user.username }}, <a href="{{ path('api_logout') }}">Logout</a>
</div>
{% endif %}
<h1 class="h3 mb-3 font-weight-normal">Grant Permissions</h1>
<input type="hidden" name="_csrf_token"
value="{{ csrf_token('authenticate') }}"
>
<input type="hidden" name="email"
value="{{ email }}"
>
<input type="hidden" name="password"
value="{{ password }}"
>
<p>Grant the following permissions:</p>
<ul>
{% for scope in scopes %}
<li>{{ scope }}: {{ scope }}</li>
{% endfor %}
</ul>
<button class="btn btn-lg btn-primary" type="submit" name="action" value="{{ grant }}">
Grant
</button>
<button class="btn btn-lg btn-primary" type="submit" name="action" value="Deny">
Deny
</button>
</form>