Merge branch 'Xbird/JsonAuth' into 'main'
Add json token login See merge request gamexperience/vision!53
This commit is contained in:
1
.env
1
.env
@@ -2,6 +2,7 @@ APP_ENV=prod
|
|||||||
DEFAULT_LOCALE=en
|
DEFAULT_LOCALE=en
|
||||||
APP_SECRET=CHANGEME
|
APP_SECRET=CHANGEME
|
||||||
TZ=America/New_York
|
TZ=America/New_York
|
||||||
|
LOGIN_JSON_AES_KEY=
|
||||||
###> symfony/lock ###
|
###> symfony/lock ###
|
||||||
# Choose one of the stores below
|
# Choose one of the stores below
|
||||||
# postgresql+advisory://db_user:db_password@localhost/db_name
|
# postgresql+advisory://db_user:db_password@localhost/db_name
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -101,6 +101,21 @@ This is a web panel to allow roleplay server to have an common interface for all
|
|||||||
php bin/console cache:clear
|
php bin/console cache:clear
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Login with json token
|
||||||
|
|
||||||
|
|
||||||
|
you need to encode a json string like this :
|
||||||
|
```php
|
||||||
|
openssl_encrypt('{"email":"test@test.fr"}', 'aes-256-cbc', 'LOGIN_JSON_AES_KEY', 0)
|
||||||
|
```
|
||||||
|
and then use the token with url :
|
||||||
|
|
||||||
|
/login/json?token=YOUR_ENCRYPTED_TOKEN_HERE
|
||||||
|
|
||||||
|
If the email exist on user list, the user is connected, if not, and error page is displayed
|
||||||
|
|
||||||
|
You need to setup the decryption key by env : LOGIN_JSON_AES_KEY
|
||||||
|
|
||||||
## Scalability
|
## Scalability
|
||||||
|
|
||||||
Vision is ready to be used in scaled architecture :
|
Vision is ready to be used in scaled architecture :
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ security:
|
|||||||
lazy: true
|
lazy: true
|
||||||
provider: app_user_provider
|
provider: app_user_provider
|
||||||
switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }
|
switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }
|
||||||
custom_authenticator: App\Security\FormAuthenticator
|
custom_authenticator:
|
||||||
|
- App\Security\FormAuthenticator
|
||||||
|
- App\Security\JsonAesAuthenticator
|
||||||
user_checker: App\Security\UserChecker
|
user_checker: App\Security\UserChecker
|
||||||
login_throttling:
|
login_throttling:
|
||||||
max_attempts: 3
|
max_attempts: 3
|
||||||
|
|||||||
@@ -138,4 +138,15 @@ class SecurityController extends AbstractController
|
|||||||
{
|
{
|
||||||
throw new \LogicException('Something goes wrong if you see this');
|
throw new \LogicException('Something goes wrong if you see this');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/login/json", name="app_login_json")
|
||||||
|
*/
|
||||||
|
public function loginJson()
|
||||||
|
{
|
||||||
|
|
||||||
|
return $this->render(
|
||||||
|
'security/json.html.twig'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
71
src/Security/JsonAesAuthenticator.php
Normal file
71
src/Security/JsonAesAuthenticator.php
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Security;
|
||||||
|
|
||||||
|
use App\Repository\UserRepository;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
|
use Symfony\Component\Security\Http\Util\TargetPathTrait;
|
||||||
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
|
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||||
|
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
||||||
|
|
||||||
|
class JsonAesAuthenticator extends AbstractAuthenticator
|
||||||
|
{
|
||||||
|
use TargetPathTrait;
|
||||||
|
|
||||||
|
private UserRepository $userRepository;
|
||||||
|
private UrlGeneratorInterface $urlGenerator;
|
||||||
|
|
||||||
|
public function __construct(UrlGeneratorInterface $urlGenerator, UserRepository $userRepository)
|
||||||
|
{
|
||||||
|
$this->urlGenerator = $urlGenerator;
|
||||||
|
$this->userRepository = $userRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function supports(Request $request): ?bool
|
||||||
|
{
|
||||||
|
return ($request->attributes->get('_route') == 'app_login_json')
|
||||||
|
&& $request->query->has('token')
|
||||||
|
&& null != $_ENV['LOGIN_JSON_AES_KEY']
|
||||||
|
&& !empty($_ENV['LOGIN_JSON_AES_KEY']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authenticate(Request $request): Passport
|
||||||
|
{
|
||||||
|
|
||||||
|
$apiToken = $request->query->get('token');
|
||||||
|
if (null === $apiToken) {
|
||||||
|
throw new AccessDeniedHttpException('No API token provided');
|
||||||
|
}
|
||||||
|
|
||||||
|
$tokenDecoded = openssl_decrypt($apiToken, 'aes-256-cbc', $_ENV['LOGIN_JSON_AES_KEY'], 0);
|
||||||
|
$tokenInfos = json_decode($tokenDecoded);
|
||||||
|
|
||||||
|
return new SelfValidatingPassport(new UserBadge($tokenInfos->email, function (string $userIdentifier) {
|
||||||
|
return $this->userRepository->findOneBy(['email' => $userIdentifier]);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||||
|
{
|
||||||
|
|
||||||
|
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
|
||||||
|
return new RedirectResponse($targetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RedirectResponse($this->urlGenerator->generate('home'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||||
|
{
|
||||||
|
return new RedirectResponse($this->urlGenerator->generate('app_login_json'));
|
||||||
|
}
|
||||||
|
}
|
||||||
29
templates/security/json.html.twig
Normal file
29
templates/security/json.html.twig
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}{% trans %}title_login{% endtrans %}{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
<!-- [ auth-signin ] start -->
|
||||||
|
<div class="auth-wrapper">
|
||||||
|
<div class="auth-content">
|
||||||
|
<div class="card">
|
||||||
|
<div class="row align-items-center text-center">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="card-body">
|
||||||
|
<img src="{{ asset('img/vision_long_2100x250.svg') }}" alt="" class="img-fluid mb-4">
|
||||||
|
<h4 class="mb-3 f-w-400">{% trans %}title_login{% endtrans %}</h4>
|
||||||
|
|
||||||
|
<p>{% trans %}text_login_json_fail{% endtrans %}</p>
|
||||||
|
|
||||||
|
<p class="mb-0 text-muted">{% trans %}no_account{% endtrans %} ? <a href="{{ path('app_register') }}" class="f-w-400">{% trans %}button_register{% endtrans %}</a></p>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- [ auth-signin ] end -->
|
||||||
|
{% endblock %}
|
||||||
@@ -619,6 +619,7 @@ subtitle_administration_watchdog: View entities modifications
|
|||||||
subtitle_administration: The BOSS
|
subtitle_administration: The BOSS
|
||||||
subtitle_home: Homepage
|
subtitle_home: Homepage
|
||||||
subtitle_management: Administration of your group
|
subtitle_management: Administration of your group
|
||||||
|
text_login_json_fail: Automatic login failed, contact your administrator
|
||||||
text_reset_password_explanation: If an account is linked to this address, you will receive an email with a reset link
|
text_reset_password_explanation: If an account is linked to this address, you will receive an email with a reset link
|
||||||
title_accessorySentence: Accessory penalty
|
title_accessorySentence: Accessory penalty
|
||||||
title_actions: Actions
|
title_actions: Actions
|
||||||
|
|||||||
@@ -618,6 +618,7 @@ subtitle_administration_watchdog: Voir les modifications des entités
|
|||||||
subtitle_administration: Les BOSS
|
subtitle_administration: Les BOSS
|
||||||
subtitle_home: Accueil
|
subtitle_home: Accueil
|
||||||
subtitle_management: Gestion de votre groupe
|
subtitle_management: Gestion de votre groupe
|
||||||
|
text_login_json_fail: La connexion automatique à échouée, merci de contacter l'équipe technique
|
||||||
text_reset_password_explanation: Si un compte est lié à cette adresse, vous allez recevoir un email avec un lien de réinitialisation
|
text_reset_password_explanation: Si un compte est lié à cette adresse, vous allez recevoir un email avec un lien de réinitialisation
|
||||||
title_accessorySentence: Peine Accessoire
|
title_accessorySentence: Peine Accessoire
|
||||||
title_actions: Actions
|
title_actions: Actions
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"version": "0.2.18"
|
"version": "0.2.19"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user