Nel 2025 vendere online è più semplice che mai grazie all’enorme diffusione del Social Commerce, ma allo stesso tempo è diventato più rischioso se non costruisci una strategia digitale solida e sostenibile.
Innanzitutto andiamo a definire il concetto di JWT, acronimo di Json Web Token.
Il JWT è un JSON-based open standard (RFC 7519 – JSON Web Token (JWT)) per creare access token, decisamente utili per architetture API-REST in cui le comunicazioni sono stateless cioè il server non conosce nulla del client e tutte le informazioni devono risedere nel client.
Per esempio, a seguito di una login eseguita correttamente, il server può generare e restituire al client un token che contiene l’informazione “logged as admin”. Il client, nelle chiamate successive, potrà utilizzare (cioè inviare) questo token per indicare al server di essere loggato con privilegi di admin.
I token sono firmati con la chiave del server che potrà quindi verificarne la legittimità e integrità.
I token sono particolarmente compatti quindi utilizzabili in particolare nei contesti di single sign-on (SSO).
Ormai siamo abituati che nell’ecosistema di Symfony si trova quasi sempre il bundle corretto per le proprie esigenze.
Anche questa volta le aspettative non vengono tradite: sembra che il bundle LexikJWTAuthenticationBundle sia proprio fatto apposta per le nostre esigenze.
Tralasciamo le solite indicazioni di installazione che sono ben specificate nella documentazione e che non presentano nulla di particolare o difficile e veniamo al sodo.
Implementiamo quindi il meccanismo base di autenticazione a dei servizi Web API REST/Json avvalendoci di questo bundle e del comodissimo firewall Guard di Symfony.
Per questa semplice guida andremo a soffermarci solo sulla parte server-side che è il motore del sistema.
...
/**
* @Route("/api")
*/
class DefaultController extends Controller
{
/**
* @Route(path="/token-authentication", name="api_token_authentication")
*/
public function tokenAuthentication(Request $request)
{
$username = $request->request->get('username');
$password = $request->request->get('password');
$user = $this->getDoctrine()->getRepository('FooUserBundle:User')
->findOneBy(['username' => $username]);
if (!$user) {
throw $this->createNotFoundException(sprintf('Utente %s non trovato.', $username));
}
$userChecker = new UserChecker();
$userChecker->checkPreAuth($user);
if (!$this->get('security.password_encoder')->isPasswordValid($user, $password)) {
throw $this->createAccessDeniedException(sprintf
('Dati di accesso per l\'utente %s non validi.', $username));
}
$userChecker->checkPostAuth($concorrente);
// Use LexikJWTAuthenticationBundle to create JWT token that hold only information about user name
$token = $this->get('lexik_jwt_authentication.jwt_encoder')->encode(['username' => $user->getUsername()]);
// Return genereted token
return new JsonResponse(['token' => $token]);
}
Come vedete non è nulla di particolare, a fronte di uno username e password cerchiamo l’utente e se è valido, creiamo un token contenente lo username. Il token è creato dal servizio offerto dal bundle appena installato.
curl -X POST http://localhost:8000/api/token-authentication -d _username=johndoe -d _password=test
… per ottenere in risposta il token.
{
"token" : "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXUyJ9.eyJleHAiOjE0MzQ3Mjc1MzYsInVzZX
JuYW1lIjoia29ybGVvbiIsImlhdCI6IjE0MzQ2NDExMzYifQ.nh0L_wuJy6ZKIQWh6OrW5hdL
kviTs1_bau2GqYdDCB0Yqy_RplkFghsuqMpsFls8zKEErdX5TYCOR7muX0aQvQxGQ4mpBkvMDhJ4-
pE4ct2obeMTr_s4X8nC00rBYPofrOONUOR4utbzvbd4d2xT_tj4TdR_0tsr91Y7VskCRFnoXAnNT-qQb7ci7HIBTbutb9zVStOFejrb4aLbr7Fl4byeIEYgp2Gd7gY"
}
...
class JwtAuthenticator extends AbstractGuardAuthenticator
{
private $em;
private $jwtEncoder;
public function __construct(EntityManager $em, JWTEncoder $jwtEncoder)
{
$this->em = $em;
$this->jwtEncoder = $jwtEncoder;
}
public function start(Request $request, AuthenticationException $authException = null)
{
return new JsonResponse('Auth header required', 401);
}
public function getCredentials(Request $request)
{
if (!$request->headers->has('Authorization')) {
return null;
}
$extractor = new AuthorizationHeaderTokenExtractor('Bearer');
$token = $extractor->extract($request);
if (!$token) {
return null;
}
return $token;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$data = $this->jwtEncoder->decode($credentials);
if (!$data){
return null;
}
$username = $data['username'];
$user = $this->em->getRepository('FooUserBundle:User')
->findOneBy(['username' => $username]);
if (!$user){
return null;
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
return true;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
return new JsonResponse([
'message' => $exception->getMessage()
], 401);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
return;
}
public function supportsRememberMe()
{
return false;
}
}
Da notare che questo firewall entra in funzione solo per chiamate che presentano l’header “Authorization” che deve contenere il token precedentemente generato.
Inoltre il firewall non verifica le credenziali, dà per scontato che il token sia già di per sé, nella sua interezza e validità, l’elemento che garantisce l’autenticazione.
Quindi, in estrema sintesi, se il token è valido, il firewall si preoccupa solo di estrarne lo username e, da qui, eventualmente, caricare l’utente o i servizi necessari per gestire la chiamata.
Ricordiamoci infine di registrare il firewall in security.yml:
security:
firewalls:
api:
pattern: ^/api
anonymous: ~
guard:
authenticators:
- api.jwt_token_authenticator
access_control:
- { path: ^/api/token-authentication, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: [ROLE_USER] }
Nel 2025 vendere online è più semplice che mai grazie all’enorme diffusione del Social Commerce, ma allo stesso tempo è diventato più rischioso se non costruisci una strategia digitale solida e sostenibile.
Perché ChatGPT cita alcuni brand e non altri? Semplice: l'AI non ha opinioni proprie, ma si basa su informazioni pubbliche.
Hai investito in un sito web professionale, magari anche bello da vedere… ma i contatti non arrivano, le vendite sono ferme e la tua presenza online sembra un po’ troppo silenziosa. Ti suona familiare?
© 2024 WEB AGENCY MILANO FUTURAWEB SRL – VIA GIUSEPPE FRUA, 19 – 20146 MILANO / P.I. 03585460961 / REA 1686213 / CS 10000€ IV / PRIVACY