<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jailson Anjos</title>
    <description>The latest articles on DEV Community by Jailson Anjos (@jairocket).</description>
    <link>https://dev.to/jairocket</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F882205%2F740fe87e-32a5-4323-9486-96fc1209b818.png</url>
      <title>DEV Community: Jailson Anjos</title>
      <link>https://dev.to/jairocket</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jairocket"/>
    <language>en</language>
    <item>
      <title>Autenticações com JavaScript Web Tokens</title>
      <dc:creator>Jailson Anjos</dc:creator>
      <pubDate>Mon, 14 Nov 2022 14:07:20 +0000</pubDate>
      <link>https://dev.to/jairocket/autenticacoes-usando-jwt-3627</link>
      <guid>https://dev.to/jairocket/autenticacoes-usando-jwt-3627</guid>
      <description>&lt;p&gt;Esse artigo foi publicado originalmente em 07 de setembro de 2021, no meu perfil do Linkedin. Pouco mais de um ano depois, após realizar algumas melhorias no código, resolvi publicar uma versão atualizada. Neste texto, você vai encontrar um exemplo de implementação de controle de acesso de dados utilizando &lt;em&gt;jwt&lt;/em&gt;, tanto pela ótica do &lt;em&gt;frontend&lt;/em&gt;, quanto do &lt;em&gt;backend&lt;/em&gt;, utilizando &lt;em&gt;Reactjs&lt;/em&gt; e &lt;em&gt;Nodejs&lt;/em&gt;, respectivamente. Para melhor compreensão, é preciso conhecer noções básicas do protocolo para requisições &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Messages"&gt;HTTP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Como é fácil de imaginar, o controle de acesso a determinadas informações é essencial no processo de desenvolvimento web e mobile. É preciso garantir que as informações sejam acessadas apenas pelas pessoas autorizadas. Uma das ferramentas utilizadas para alcançar este objetivo é o &lt;em&gt;Javascript Web Token&lt;/em&gt;, ou &lt;em&gt;jwt&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;em&gt;jwt&lt;/em&gt; provê um meio de troca de informações entre o cliente e o servidor de forma segura, por meio da assinatura de um &lt;em&gt;token&lt;/em&gt;, usando pares de chaves públicas/privadas. Esse processo permite certificar que a parte que possui a chave privada é quem assinou o &lt;em&gt;token&lt;/em&gt;. Para informações mais aprofundadas, acesse aqui &lt;a href="https://jwt.io/introduction"&gt;https://jwt.io/introduction&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;Descrevo abaixo os procedimentos que realizei para implementar esta funcionalidade no meu projeto de rede social para amantes de vinhos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autenticação por meio da assinatura do &lt;em&gt;token&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Para fazer login, é preciso fazer uma requisição &lt;em&gt;POST&lt;/em&gt; com as credenciais da pessoa (email e password, neste caso). O servidor verifica no banco de dados se as credenciais estão corretas. Em caso positivo, um &lt;em&gt;token&lt;/em&gt; é assinado e enviado para o cliente, com validade de 20 minutos. O &lt;em&gt;token&lt;/em&gt; recebido é salvo no navegador como &lt;em&gt;&lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Cookies"&gt;cookie&lt;/a&gt;&lt;/em&gt; e redireciona para a rota na qual serão mostradas as informações solicitadas.&lt;/p&gt;

&lt;p&gt;A função "handleSubmit", do componente , é chamada quando clicamos em "Enviar", após preenchermos email e senha:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FormEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useNavigate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Cookie&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;js-cookie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormEvent&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3333/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;Cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/dashboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;E-mail não cadastrado!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setEmailError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Senha incorreta!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setPasswordError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No &lt;em&gt;backend&lt;/em&gt;, mais precisamente no &lt;em&gt;&lt;a href="https://www.devmedia.com.br/introducao-ao-padrao-mvc/29308"&gt;controller&lt;/a&gt;&lt;/em&gt; do usuário, a assinatura do &lt;em&gt;token&lt;/em&gt; é realizada pelo método &lt;em&gt;"userLogger"&lt;/em&gt;. Para tanto, em primeiro lugar, o método &lt;em&gt;"validationResult"&lt;/em&gt; da biblioteca &lt;em&gt;&lt;a href="https://www.npmjs.com/package/express-validator"&gt;"express-validator"&lt;/a&gt;&lt;/em&gt; verifica se os dados recebidos pela requisição &lt;em&gt;POST&lt;/em&gt; estão no formato correto. Após, se existe alguma pessoa cadastrada no banco de dados com as credenciais informadas. Havendo sucesso nestas validações, o &lt;em&gt;token&lt;/em&gt; é assinado e enviado como resposta, junto com os dados solicitados pelo cliente. Se estas validações falharem, uma mensagem de erro é enviada para o cliente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;validationResult&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-validator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bcryptjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../database/models&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;userLogger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errorsList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errorsList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mail&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compareSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;))){&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;avatar_picture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;avatar_picture&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;20m&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Login Inválido&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Validação do &lt;em&gt;token&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Para acessar as informações privadas, é preciso que o servidor verifique se o &lt;em&gt;token&lt;/em&gt; é válido. Para tanto, é necessário incluir o &lt;em&gt;token&lt;/em&gt; - que está salvo como cookie neste caso - nos headers da requisição &lt;em&gt;GET&lt;/em&gt; pela qual se pretende se obter as informações.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useNavigate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Cookies&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;js-cookie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Dashboard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setParameter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;avatar_picture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;background_picture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;brotherhoods&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBrotherhoods&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEvents&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useNavigate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3333/dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
     &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nx"&gt;setBrotherhoods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;brotherhoods&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nx"&gt;setEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Antes de consultar e retornar as informações requisitadas, um &lt;a href="https://www.redhat.com/pt-br/topics/middleware/what-is-middleware"&gt;&lt;em&gt;middleware&lt;/em&gt;&lt;/a&gt; é responsável por verificar se o &lt;em&gt;token&lt;/em&gt; recebido no &lt;em&gt;headers&lt;/em&gt; da requisição é válido. Em caso negativo, o acesso às informações é negado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
         &lt;span class="na"&gt;mensagem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sessão expirada. Por favor, logue novamente&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Renderização da informação privada na interface do cliente
&lt;/h2&gt;

&lt;p&gt;Utilizando os hooks &lt;em&gt;useState&lt;/em&gt; e &lt;em&gt;useEffect&lt;/em&gt; a informação recebida como resposta da requisição é atribuída a variáveis e enviadas aos respectivos componentes como propriedades para que possam ser renderizados.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BrotherhoodsSection&lt;/span&gt; &lt;span class="nx"&gt;brotherhoods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;brotherhoods&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;EventsSection&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste artigo te convidei a acompanhar todo o processo de assinatura e validação de um &lt;em&gt;JavaScript Web Token&lt;/em&gt;, desde a requisição do cliente até a resposta do servidor. Podemos resumir o fluxo da seguinte forma:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cliente faz requisição, enviando suas credenciais;&lt;/li&gt;
&lt;li&gt;Servidor recebe requisição, confere as credenciais e, em caso de sucesso, assina um novo &lt;em&gt;token&lt;/em&gt; e o devolve ao cliente;&lt;/li&gt;
&lt;li&gt;No nosso exemplo, o &lt;em&gt;token&lt;/em&gt; é recebido pelo cliente e salvo como &lt;em&gt;cookie&lt;/em&gt; no navegador;&lt;/li&gt;
&lt;li&gt;Quando o precisa acessar informações protegidas, o cliente busca o &lt;em&gt;cookie&lt;/em&gt; no navegador e o envia nos headers da requisição ao servidor;&lt;/li&gt;
&lt;li&gt;Servidor valida se o token é válido e se foi assinado pelo cliente que está requisitando a informação. Em caso positivo, os dados solicitados são enviados, caso contrário, é enviada uma mensagem solicitando que um novo login seja realizado, reiniciando o ciclo.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Se você chegou até aqui, agradeço sua atenção! Você implementaria esta funcionalidade de forma diferente? Conhece uma maneira de tornar esse código mais eficiente? Tem alguma dúvida? Adoraria obter o seu feedback.&lt;/p&gt;

&lt;p&gt;Até a próxima!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>jwt</category>
      <category>node</category>
      <category>react</category>
    </item>
    <item>
      <title>Começando com Jest e React Testing Library</title>
      <dc:creator>Jailson Anjos</dc:creator>
      <pubDate>Fri, 24 Jun 2022 16:31:00 +0000</pubDate>
      <link>https://dev.to/jairocket/comecando-com-jest-e-react-testing-library-10ck</link>
      <guid>https://dev.to/jairocket/comecando-com-jest-e-react-testing-library-10ck</guid>
      <description>&lt;p&gt;A fase de testes é essencial no processo de desenvolvimento de software. Este momento é fundamental para verificar se o produto, de fato, atende às especificações estabelecidas. Além disto, permite identificar e corrigir comportamentos inesperados que poderiam comprometer a qualidade e a confiabilidade da aplicação.&lt;/p&gt;

&lt;p&gt;Quando começamos a programar, o processo de testagem acontece de forma orgânica. Por exemplo, ao criarmos um botão que ao ser clicado muda de cor, após escrevermos o código para tanto, é natural querermos executar manualmente o programa e verificarmos o seu funcionamento. Todavia, em projetos maiores, não seria prático testar todas as funcionalidades desta forma. Testes automatizados reduzem custos, aumentam a produtividade, a eficiência e a eficácia do time. Além disso, possibilitam implementar novas funcionalidades sem “quebrar” o código antigo. Desenvolvedores que trabalham com &lt;em&gt;React&lt;/em&gt; têm à disposição o &lt;strong&gt;Jest&lt;/strong&gt; e a &lt;strong&gt;React Testing Library (RTL)&lt;/strong&gt; para testar suas aplicações.&lt;/p&gt;

&lt;p&gt;A lógica por trás do uso destas ferramentas é simular a execução das funcionalidades da aplicação e conferir se a resposta é igual à esperada. Ao testarmos manualmente um botão de cor A que muda para cor B quando clicado, provavelmente, seguiríamos esta sequência de ações:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Abrir a página;&lt;/li&gt;
&lt;li&gt;Procurar pelo botão de cor A;&lt;/li&gt;
&lt;li&gt;Clicar no botão;&lt;/li&gt;
&lt;li&gt;Conferir se o botão mudou para a cor B.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O teste automatizado para verificar o funcionamento de um botão azul, com o texto “Troca a Cor”, presente no componente &lt;code&gt;&amp;lt; Page /&amp;gt;&lt;/code&gt;, que ao ser clicado deva mudar para a cor vermelha, poderia ser escrito assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/user-event&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Deve trocar a cor de azul para vermelha quando clicado&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;//Abrir a página&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//Encontrar o botão com o nome “Troca a Cor”&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;colorButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Troca a Cor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;//Clicar no botão&lt;/span&gt;
  &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;colorButton&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//Verificar se o botão assumiu a cor vermelha&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;colorButton&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveStyle&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como observado, é possível estabelecer um paralelo entre o teste automatizado e o teste realizado de forma manual, o que facilita a compreensão de cada passo realizado. &lt;/p&gt;

&lt;h3&gt;
  
  
  Dissecando o código
&lt;/h3&gt;

&lt;p&gt;Quem entendeu o exemplo acima observando os comentários pode pular esta seção.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Para abrir a página, utilizamos a função &lt;em&gt;"render()"&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Para procurar pelo botão, poderíamos utilizar a query &lt;em&gt;“getByRole”&lt;/em&gt;, informando que a &lt;em&gt;“role”&lt;/em&gt;, ou papel desempenhado, é de um botão;
&lt;/li&gt;
&lt;li&gt;Para clicar no botão, poderíamos utilizar a biblioteca &lt;em&gt;“&lt;a href="https://github.com/testing-library/user-event"&gt;userEvent&lt;/a&gt;”&lt;/em&gt;, que simula interações com a interface;&lt;/li&gt;
&lt;li&gt;Para verificar se o botão mudou de cor, utilizamos o &lt;em&gt;expect()&lt;/em&gt;, para verificar se a propriedade &lt;em&gt;“background color”&lt;/em&gt; do &lt;em&gt;CSS&lt;/em&gt; aplicado é a cor B.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Este exemplo é simples e, naturalmente, conforme a complexidade do código aumenta, funcionalidades mais sofisticadas disponíveis no &lt;em&gt;Jest&lt;/em&gt; e na &lt;em&gt;RTL&lt;/em&gt; serão necessárias para que os testes sejam realizados de forma adequada. Contudo, objetivo deste artigo não é exaurir todas as possibilidades de uso destas tecnologias, mas ajudar iniciantes a compreender um pouco do funcionamento destas ferramentas fundamentais para garantir a qualidade do código e das próprias interfaces construídas em &lt;em&gt;React&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sim, mas o que é o &lt;em&gt;Jest&lt;/em&gt;?
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;&lt;a href="https://jestjs.io/pt-BR/docs/getting-started"&gt;Jest&lt;/a&gt;&lt;/em&gt; é um &lt;em&gt;framework&lt;/em&gt; para testes em &lt;em&gt;JavaScript&lt;/em&gt; e responsável por localizar, executar e informar se os testes passaram ou falharam. Pode ser utilizado em aplicações em &lt;em&gt;React&lt;/em&gt;, &lt;em&gt;Vue&lt;/em&gt;, &lt;em&gt;Node&lt;/em&gt;, &lt;em&gt;Typescript&lt;/em&gt;, &lt;em&gt;Angular&lt;/em&gt;, etc.&lt;br&gt;
Por meio do comando &lt;em&gt;“expect()”&lt;/em&gt;, podemos verificar se o objeto possui o atributo que esperamos para definir se a funcionalidade atende ou não às especificações requeridas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quais são as responsabilidades da &lt;em&gt;React Testing Library&lt;/em&gt;?
&lt;/h3&gt;

&lt;p&gt;A &lt;em&gt;&lt;a href="https://testing-library.com/docs/queries/about/#screen"&gt;RTL&lt;/a&gt;&lt;/em&gt; disponibiliza uma &lt;em&gt;&lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/API/Document_Object_Model/Introduction"&gt;DOM&lt;/a&gt;&lt;/em&gt; virtual, na qual, podemos localizar os elementos que compõem a página. O objeto &lt;em&gt;“screen”&lt;/em&gt; exportado por esta DOM virtual contém os comandos de busca (&lt;em&gt;queries&lt;/em&gt;) necessários para encontrar estes elementos e seu uso é recomendado, pois, realizar a mesma tarefa utilizando apenas o &lt;em&gt;Jest&lt;/em&gt; seria muito trabalhoso. &lt;/p&gt;

&lt;p&gt;A &lt;em&gt;query&lt;/em&gt; utilizada para encontrar o botão foi da família &lt;em&gt;“getBy”&lt;/em&gt;. Este tipo de &lt;em&gt;query&lt;/em&gt; é utilizado quando esperamos encontrar um objeto na página. Caso esperássemos &lt;strong&gt;não&lt;/strong&gt; encontrar o objeto, utilizaríamos &lt;em&gt;“queryBy”&lt;/em&gt;, e, nas situações em que encontrar o objeto procurado depende do carregamento de uma requisição assíncrona (como, por exemplo, o retorno das informações referentes a uma consulta a um banco de dados), utilizaríamos &lt;em&gt;“findBy”&lt;/em&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Nota sobre acessibilidade
&lt;/h3&gt;

&lt;p&gt;No exemplo, localizamos o botão pesquisando pelo &lt;strong&gt;papel&lt;/strong&gt; &lt;em&gt;(role)&lt;/em&gt; que o mesmo desempenha na página &lt;em&gt;(button)&lt;/em&gt;. Todavia, é importante mencionar que é possível localizar elementos pesquisando pelo &lt;strong&gt;texto&lt;/strong&gt;, pelo &lt;strong&gt;id&lt;/strong&gt;, pelo &lt;strong&gt;título&lt;/strong&gt;, entre outras possibilidades. A &lt;em&gt;query&lt;/em&gt; &lt;em&gt;&lt;a href="https://testing-library.com/docs/queries/about#priority"&gt;getByRole&lt;/a&gt;&lt;/em&gt;, contudo, é capaz de localizar todos os elementos acessíveis na tela. Se não for possível encontrar o elemento em questão com esta ferramenta, é possível que haja problemas de acessibilidade na aplicação.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resumo e dicas
&lt;/h3&gt;

&lt;p&gt;Nesse artigo, falamos um pouco sobre testes automatizados e sua importância para a manutenção da qualidade do software. Além disso, discutimos a respeito do &lt;em&gt;framework Jest&lt;/em&gt; e da biblioteca &lt;em&gt;RTL&lt;/em&gt;, utilizados para realizar testes automatizados em aplicações &lt;em&gt;React&lt;/em&gt;. Para aprofundar um pouco mais sobre o assunto, recomendo este &lt;a href="https://www.udemy.com/course/react-testing-library/"&gt;curso&lt;/a&gt; da Bonnie Schulkin, hospedado na Udemy, que serviu de base para este texto. Outra dica é consultar as documentações da &lt;em&gt;&lt;a href="https://testing-library.com/docs/queries/about/"&gt;RTL&lt;/a&gt;&lt;/em&gt; e do &lt;em&gt;&lt;a href="https://jestjs.io/pt-BR/"&gt;Jest&lt;/a&gt;&lt;/em&gt;, e começar a experimentar os conceitos em seus projetos. Ainda há a opção de utilizar o praticar na no &lt;em&gt;&lt;a href="https://testing-playground.com/"&gt;playground&lt;/a&gt;&lt;/em&gt; do &lt;em&gt;RTL&lt;/em&gt;. Para ir ainda mais fundo, este &lt;em&gt;&lt;a href="https://kentcdodds.com/blog/common-mistakes-with-react-testing-library"&gt;artigo&lt;/a&gt;&lt;/em&gt;, escrito por um dos criadores da &lt;em&gt;RTL&lt;/em&gt;, pode ser bastante proveitoso.&lt;/p&gt;

&lt;p&gt;Já usa &lt;em&gt;RTL&lt;/em&gt; e &lt;em&gt;Jest&lt;/em&gt;? Deixe seu comentário! Até a próxima!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>react</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
