O JWT deve ser armazenado em localStorage ou cookie? [duplicado]

99

Com o propósito de proteger a API REST usando JWT, de acordo com alguns materiais (como este guia e esta pergunta ), o JWT pode ser armazenado em localStorage ou Cookies . Com base no meu entendimento:

  • localStorage está sujeito a XSS e geralmente não é recomendado armazenar nenhuma informação sensível nele.
  • Com os Cookies , podemos aplicar o sinalizador "httpOnly" que atenua o risco de XSS. No entanto, se quisermos ler o JWT de Cookies no backend, estaremos sujeitos ao CSRF.

Portanto, com base na premissa acima, será melhor armazenarmos JWT em Cookies. Em cada solicitação ao servidor, o JWT será lido dos cookies e adicionado no cabeçalho de autorização usando o esquema do portador. O servidor pode então verificar o JWT no cabeçalho da solicitação (em vez de lê-lo dos cookies).

Meu entendimento está correto? Em caso afirmativo, a abordagem acima tem alguma preocupação com a segurança? Ou, na verdade, podemos simplesmente usar o localStorage em primeiro lugar?

pkid169
fonte
@ lrn2prgrm como não se deve usar (sem estado) JWT e semântica (stateful) sessão juntos.
ozanmuyes

Respostas:

56

Eu gosto do método XSRF Double Submit Cookies mencionado no artigo que @ pkid169 disse, mas há uma coisa que esse artigo não diz a você. Você ainda não está protegido contra XSS porque o que o invasor pode fazer é injetar um script que lê seu cookie CSRF (que não é HttpOnly) e, em seguida, fazer uma solicitação para um de seus endpoints de API usando este token CSRF com o cookie JWT sendo enviado automaticamente.

Portanto, na realidade, você ainda é suscetível a XSS, mas o invasor não pode roubar seu token JWT para uso posterior, mas ainda pode fazer solicitações em nome de seus usuários usando XSS.

Quer você armazene seu JWT em um localStorage ou armazene seu token XSRF em um cookie não apenas http, ambos podem ser capturados facilmente pelo XSS. Até mesmo seu JWT no cookie HttpOnly pode ser capturado por um ataque XSS avançado.

Portanto, além do método Double Submit Cookies, você deve sempre seguir as melhores práticas contra XSS, incluindo conteúdo de escape. Isso significa remover qualquer código executável que faria com que o navegador fizesse algo que você não deseja. Normalmente, isso significa remover // <! [CDATA [tags e atributos HTML que fazem com que o JavaScript seja avaliado.

Iman Sedighi
fonte
11
Você pode esclarecer como um cookie JWT no HttpOnly pode ser capturado? Ele pode ser usado pelo XSRF se o token XSRF estiver comprometido pelo XSS, mas ele pode realmente ser capturado?
Jacek Gorgoń
1
Eu sei que este é um post antigo, mas gostaria de fazer algumas perguntas ... Isso significa que scripts bem elaborados podem ler localStorage e cookie? Em caso afirmativo, é seguro presumir que um JWT pode ser roubado, não importa onde o armazenemos em um navegador? Então, eu sinto que confiar apenas em um JWT é muito arriscado.
Hiroki
2
"Até mesmo seu cookie JWT em HttpOnly pode ser capturado por um ataque XSS avançado." é falso. Postagem original editada para corrigir isso.
java-addict301
"Até o seu cookie JWT em HttpOnly pode ser capturado por um ataque XSS avançado" Posso imaginar que alguém pegue o cookie enviando-o para seu próprio servidor. Para isso, ele pode usar fetch com o valor adequado do sinalizador de credenciais. O principal problema aqui é a proteção CORS, mas em algumas circunstâncias acho que é possível.
bartnikiewi.cz
"injetar script que lê seu cookie CSRF (que não é HttpOnly)" A implementação padrão Html.AntiForgeryToken()no ASP.NET MVC usa um cookie HttpOnly para o token CSRF. Acho que você ainda é suscetível a certos XSS, mas achei que valeria a pena mencionar.
Lovethenakedgun
21

Uma postagem oportuna de Stormpath elaborou bastante meus pontos e respondeu à minha pergunta.

TL; DR

Armazene o JWT em cookies e, em seguida, passe o JWT no cabeçalho de autorização em cada solicitação, como mencionei, ou, como o artigo sugere, conte com o back-end para evitar CSRF (por exemplo, usando xsrfTokenno caso de Angular).

pkid169
fonte
2
Olá, não tenho certeza se isso está correto, mas existem algumas desvantagens específicas de usar cookies para armazenar jwt quando você está implementando CrossOrigin para seus controladores, que é uma cena em que meu aplicativo de servidor está localizado em um lugar diferente e estamos chamando o api dele em nosso aplicativo cliente que está localizado, digamos, em outra cidade? Não é por isso que muitos provedores de serviços da web se abstêm de usar cookies?
valik
CrossOrigin não significa localizações físicas. Refere-se a solicitações provenientes de outros domínios. No .net core, ao decidir usar o CORS, você especifica quais domínios vai permitir; quais cabeçalhos você permitirá, etc.
Brian Allan West,
11
  • Não armazene seu token em LocalStorage ou SessionStorage, porque tal token pode ser lido em javascript e, portanto, é vulnerável a ataques XSS.
  • Não armazene seu token no Cookie. Cookie (com sinalizador HttpOnly) é uma opção melhor - é propenso a XSS, mas é vulnerável a ataques CSRF

Em vez disso, no login, você pode entregar dois tokens: token de acesso e token de atualização. O token de acesso deve ser armazenado na memória Javascript e o token de atualização deve ser armazenado no cookie HttpOnly. O token de atualização é usado apenas e apenas para criar novos tokens de acesso - nada mais.

Quando o usuário abre uma nova aba, ou na atualização do site, você precisa realizar a solicitação para criar um novo token de acesso, baseado no token de atualização que está armazenado no Cookie.

Também recomendo fortemente a leitura deste artigo: https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/

devstrutor
fonte
5
Por que a complexidade adicional quando você pode apenas tratar o token de atualização como um token de acesso? Como é que esta abordagem mais segura dado que marca a minha token de acesso como secure, samesite: strict, http-only?
Charming Robot
não é mais seguro
Chris Hawkes,
2

Para ajudar a prevenir ataques CSRF que tiram vantagem de cookies existentes, você pode definir seu cookie com a SameSitediretiva. Defina-o como laxou strict.

Este ainda é um rascunho e em 2019 não é totalmente compatível com todos os navegadores atuais , mas dependendo da sensibilidade de seus dados e / ou seu controle sobre os navegadores que seus usuários usam, pode ser uma opção viável. Definir a diretiva com SameSite=laxpermitirá "navegações de nível superior que usam um método HTTP 'seguro' ...".

Ian Hunter
fonte