Commit 8de2384f authored by Mat's avatar Mat

User: remplace token_key par un tableau sérialisé pouvant contenir plusieurs tokens

* il faut alors vérifier lorsqu'on génère un token, qu'il n'y en n'a pas déjà un pour cette offre
* et il faut que le security.provider fasse une requête custom pour voir si le token est bon
parent 89739faa
...@@ -13,7 +13,8 @@ security: ...@@ -13,7 +13,8 @@ security:
my_tokenkey_provider: #2 my_tokenkey_provider: #2
entity: entity:
class: PotageBundle:User class: PotageBundle:User
property: tokenKey #property: tokenKey
# je ne peux me référer à une simple propriété puisque c'est un tableau qui peut contenir plusieurs tokens
firewalls: firewalls:
main: main:
......
...@@ -49,9 +49,10 @@ class User extends BaseUser ...@@ -49,9 +49,10 @@ class User extends BaseUser
private $utilisateur; private $utilisateur;
/** /**
* @ORM\Column(type="string", unique=true, length=50) * @ORM\Column(type="array", unique=false, length=255, nullable=true)
*/ */
private $tokenKey; private $tokenKey;
/** /**
* User constructor. * User constructor.
...@@ -60,7 +61,7 @@ class User extends BaseUser ...@@ -60,7 +61,7 @@ class User extends BaseUser
{ {
parent::__construct(); parent::__construct();
$this->tokenKey = bin2hex(random_bytes(20)); $this->tokenKey = array();
} }
/** /**
...@@ -82,7 +83,7 @@ class User extends BaseUser ...@@ -82,7 +83,7 @@ class User extends BaseUser
* *
* @return User * @return User
*/ */
public function setUtilisateur(\PotageBundle\Entity\Utilisateur $utilisateur = null) public function setUtilisateur(Utilisateur $utilisateur = null)
{ {
$this->utilisateur = $utilisateur; $this->utilisateur = $utilisateur;
...@@ -109,25 +110,23 @@ class User extends BaseUser ...@@ -109,25 +110,23 @@ class User extends BaseUser
return parent::getUsername() . ' ( ' . parent::getEmail() . ' )'; return parent::getUsername() . ' ( ' . parent::getEmail() . ' )';
} }
/** /**
* Set tokenKey * @return mixed
*
* @return User
*/ */
public function setTokenKey() public function getTokenKey()
{ {
$this->tokenKey = bin2hex(random_bytes(20)); return $this->tokenKey;
return $this;
} }
/** /**
* Get tokenKey * @param mixed $tokenKey
* * @return User
* @return string
*/ */
public function getTokenKey() public function addTokenKey($tokenKey)
{ {
return $this->tokenKey; $this->tokenKey[] = $tokenKey;
return $this;
} }
} }
<?php <?php
namespace PotageBundle\Repository; namespace PotageBundle\Repository;
use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
/** /**
* UserRepository * UserRepository
...@@ -8,7 +10,7 @@ namespace PotageBundle\Repository; ...@@ -8,7 +10,7 @@ namespace PotageBundle\Repository;
* This class was generated by the Doctrine ORM. Add your own custom * This class was generated by the Doctrine ORM. Add your own custom
* repository methods below. * repository methods below.
*/ */
class UserRepository extends \Doctrine\ORM\EntityRepository class UserRepository extends \Doctrine\ORM\EntityRepository implements UserLoaderInterface
{ {
/** /**
* @param $id_utilisateur * @param $id_utilisateur
...@@ -23,4 +25,22 @@ class UserRepository extends \Doctrine\ORM\EntityRepository ...@@ -23,4 +25,22 @@ class UserRepository extends \Doctrine\ORM\EntityRepository
->setParameter(':id', $id_utilisateur); ->setParameter(':id', $id_utilisateur);
return $qb->getQuery()->getOneOrNullResult(); return $qb->getQuery()->getOneOrNullResult();
} }
/**
* Dans security, je ne peux me référer à une propriété, puisque token_key est un array sérialisé
* cfr. https://symfony.com/doc/3.4/security/entity_provider.html#using-a-custom-query-to-load-the-user
*
* @param $tokenkey
* @return UserInterface|null
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function loadUserByUsername($tokenkey)
{
return $this->createQueryBuilder('u')
->where('u.tokenKey LIKE :tokenkey')
->setParameter('tokenkey', '%'.$tokenkey.'%')
->getQuery()
->getOneOrNullResult();
}
} }
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
namespace PotageBundle\Security; namespace PotageBundle\Security;
use PotageBundle\Services\LettreToken;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
...@@ -16,19 +15,6 @@ use Symfony\Component\Security\Guard\AbstractGuardAuthenticator; ...@@ -16,19 +15,6 @@ use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
class TokenAuthenticator extends AbstractGuardAuthenticator class TokenAuthenticator extends AbstractGuardAuthenticator
{ {
private $lettreToken;
/**
* TokenAuthenticator constructor.
*
* @param LettreToken $lettreToken
*/
public function __construct(LettreToken $lettreToken)
{
$this->lettreToken = $lettreToken;
}
/** /**
* Called on every request to decide if this authenticator should be * Called on every request to decide if this authenticator should be
* used for the request. Returning false will cause this authenticator * used for the request. Returning false will cause this authenticator
...@@ -95,11 +81,8 @@ class TokenAuthenticator extends AbstractGuardAuthenticator ...@@ -95,11 +81,8 @@ class TokenAuthenticator extends AbstractGuardAuthenticator
*/ */
public function getCredentials(Request $request) public function getCredentials(Request $request)
{ {
$tokenEncoded = $request->query->get('token');
$tokenDecoded = $this->lettreToken->decodePotageAccess($tokenEncoded);
return array( return array(
'token_key' => $tokenDecoded['token_key'], 'token_key' => $request->query->get('token'),
); );
} }
......
...@@ -55,14 +55,43 @@ class LettreToken ...@@ -55,14 +55,43 @@ class LettreToken
->findOneByUtilisateur($id_utilisateur); //dump($user); ->findOneByUtilisateur($id_utilisateur); //dump($user);
if ($user !== null) { if ($user !== null) {
/**
* Vérifie d'abord qu'aucun token pour cette offre n'existe pour cet utilisateur.
* Pour cela on va parcourir le tableau, récupérer l'offre, et la retourner si elle existe
*/
$newOffre = $lettre->getOffre()->getId();
$userTokenKeys = $user->getTokenKey();
foreach ($userTokenKeys as $uTokenKey)
{
$uOffre = intval($this->decodePotageAccess($uTokenKey)['offre_id']);
if ($uOffre === $newOffre)
{
return $uTokenKey;
}
}
/**
* Génère un nouveau tokenKey
*/
$newKey = bin2hex(random_bytes(15));
// TODO ici une recette secrète, hors dépôt GIT !!! $token = $newKey
$token = $user->getTokenKey()
.'_'. $lettre->getOffre()->getId() .'_'. $lettre->getOffre()->getId()
.'_'. $lettre->getOffre()->getReference(); .'_'. $lettre->getOffre()->getReference();
$tokenKey = base64_encode($token);
return base64_encode($token); /**
* Persiste le nouveau token dans le tableau token_key du user
*/
$em = $this->container->get('doctrine')->getManager();
$user->addTokenKey($tokenKey);
$em->persist($user);
$em->flush();
return $tokenKey;
} else { } else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment