Usando o JWT como sessão do PHP para resolver problemas de segurança e escalabilidade

Joao M
ByJG
Published in
4 min readJun 24, 2017

Quando desenvolvemos nossas aplicações em PHP e queremos garantir que os dados persistam entre diferentes requisições do mesmo usuário nós, frequentemente, utilizamos do Session (session_start, $_SESSION, etc). Por exemplo, um dado que normalmente guardamos é o ID do usuário que efetuou o login — se não existe ID, não está logado, se existe ID, está logado e sabemos quem efetuou o login.

Como funciona a sessão?

A Session do PHP é uma forma conveniente e (relativamente) segura para o programador armazenar e recuperar essas informações entre diversas requisições do usuário. Quando criamos uma nova sessão em PHP, ele automaticamente faz as seguintes coisas:

  1. Aloca no servidor um espaço para armazenar os dados
  2. Devolve para quem solicitou a página a “chave” desse espaço como o Cookie “PHPSESSID”

Então, o browser, nas próximas requisições passa para o servidor esse cookie. O PHP de posse dessa chave recupera os dados armazenados e disponibiliza para o servidor.

Problemas na utilização da Sessão Padrão

Apesar de ser conveniente e fácil utilizar a Sessão Padrão do PHP baseado cookie ele apresenta alguns problemas:

Problemas de Escalablidade

Se precisarmos adicionar mais servidores para suprir uma demanda alta de acesso a utilização da sessão se torna um problema. Isso por que ela está originalmente armazenada no próprio servidor e se um usuário ora vai para um servidor ora para outro, pode ser que ele não consiga ler a sessão ou ter dados armazenados em duplicidade. Existem formas de contornar esse problema como:

  • afinidade de sessão
  • centralizar a sessão (memcached, redis, database, etc)

Mas ambas as soluções adicionam mais uma complexidade na configuração da infraestrutura e manutenção dos pontos de falha adicionados.

Problemas de Segurança

Esse é o mais grave. Como o Cookie é armazenado no lado do cliente significa que ele pode ser lido bem como alterado pelo cliente. Dessa forma, se o cliente quiser deliberadamente alterar o valor do seu Session ID local, eventualmente ele pode ter acesso a alguma sessão válida do seu servidor e com isso “herdar” todas as permissões do usuário. Se por acaso conseguir a sessão do administrador ele pode, literalmente, fazer tudo no sistema.

Como funciona o JWT e como pode resolver esses problemas?

Para entender o que é o Json Web Token ou simplesmente JWT precisamos entender o que é um Token.

Segundo o paper apresentado no evento FOAF-GALWAY temos [1]:

O conceito por trás de uma autenticação baseada em token é simples. Permite que os usuários entrem o login e senha de forma a obter um token que permite que eles tenha acesso a um recurso específico sem ter que utilizar o seu usuário e senha novamente. Uma vez que o seu token foi obtido, o usuário pode fornecer o token ao servidor remoto o qual proverá acesso ao recurso específico por um período de tempo.

Um Token JWT (note que Token JWT é redundante) tem os seguintes elementos:

  1. Mensagem — A mensagem que o servidor devolveu ao cliente.
  2. Payload — contém informações sobre origem, data, validade, etc.
  3. Assinatura — A assinatura é gerada com base em uma chave secreta e tem o objetivo de garantir a autenticidade da mensagem.

O Fluxo é basicamente o seguinte:

Com isso não precisamos armazenar os dados em nenhum servidor, simplesmente passamos para o cliente e esperamos que ele a devolva. Se a mensagem chegar de volta intacta então o acesso está garantido.

Como o Token pode ter a sua origem, validade e integridade validados através da chave secreta, podemos confiar no Token.

Usando o JWT como “replacement” da sessão do PHP

Existem várias formas de se utilizar o JWT em sua aplicação. Entretanto para sistemas legados isso passa a ser um problema pois nem sempre é fácil mexer no seu código fonte sem um grande refactoring.

Como a sessão é largamente utilizada, um bom “entrypoint” para usar o JWT seria justamente fazer a substituição da sessão padrão do PHP pela sessão que usa JWT. E utilizar o Token ao invés do Session do PHP original resolve o problema de segurança e o problema de escalabidade relatado anteriormente.

Pensando nisso, desenvolvi uma biblioteca opensource em PHP chamada “jwt-session” (github) que faz exatamente isso.

Basta adicionar ao seu projeto com o Composer:

composer require "byjg/jwt-session"

E adicionar as seguintes linhas no inicio do seu projeto:

<?php
$handler = new \ByJG\Session\JwtSession('your.domain.com', 'your super secret key');
$handler->replaceSessionHandler(true);

Pronto!! As suas sessões agora estão baseadas no JWT.

Informação muito importante: Apesar do JWT ser seguro e garantir a origem, autenticidade e validade, ele não impede que a mensagem seja lida por qualquer pessoa. Assim, não armazene na sessão dados confidenciais, pois qualquer pessoa poderá le-los.

--

--

Joao M
ByJG
Editor for

Engenheiro e arquiteto de Software desde 1987 mexendo com computadores :)