<?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: Felipe de Senna</title>
    <description>The latest articles on DEV Community by Felipe de Senna (@felipedesenna).</description>
    <link>https://dev.to/felipedesenna</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%2F535324%2Fa9778dc2-f7c5-4b0d-9ef9-e80467bd70a1.jpeg</url>
      <title>DEV Community: Felipe de Senna</title>
      <link>https://dev.to/felipedesenna</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/felipedesenna"/>
    <language>en</language>
    <item>
      <title>Autenticação ReactJS - (ReactJS, Azure AD)</title>
      <dc:creator>Felipe de Senna</dc:creator>
      <pubDate>Sun, 28 Mar 2021 21:24:47 +0000</pubDate>
      <link>https://dev.to/felipedesenna/autenticacao-reactjs-reactjs-azure-ad-4d90</link>
      <guid>https://dev.to/felipedesenna/autenticacao-reactjs-reactjs-azure-ad-4d90</guid>
      <description>&lt;p&gt;Com o crescimento constante dos sistemas na web cria-se uma necessidade e preocupação com a segurança desses sistemas. Uma forma de criar uma camada de segurança é a criação de autenticação via login.&lt;/p&gt;

&lt;p&gt;E uma alternativa de autenticação é o Azure AD (Active Directory), com ele é possível criar configurações específicas para ter essa camada de segurança para seu sistema web.&lt;/p&gt;

&lt;p&gt;No Azure AD é possível criar um grupo de usuários e nele adicionar todas as contas de e-mail que podem acessar o sistema web, você pode adicionar qualquer conta que esteja dentro dos domínios da Microsoft, e-mails pessoais e corporativos.&lt;/p&gt;

&lt;p&gt;Sendo assim, nesse artigo eu vou demonstrar como fazer as configurações para ativar o Active Directory dentro do Portal do Azure e em seguida as configurações para integrar o Azure AD com o ReactJS.&lt;/p&gt;

&lt;p&gt;O primeiro passo é a configuração dentro do &lt;a href="https://portal.azure.com/" rel="noopener noreferrer"&gt;Portal do Azure&lt;/a&gt;, após entrar no portal é necessário acessar o diretório/assinatura a qual será criada a configuração, em seguida pesquise por Azure Active Directory e selecione, agora selecione a opção &lt;strong&gt;Registros de aplicativo&lt;/strong&gt; e clique em &lt;strong&gt;Novo registro&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Nesse momento irá abrir uma tela para cadastrar algumas informações sobre seu aplicativo, são elas: nome, quem pode usar este aplicativo e URI de redirecionamento que é opcional e finalizamos clicando em &lt;strong&gt;Registrar&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A imagem abaixo demonstra como ficará esta primeira etapa.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwa0ehx80dry67zfmldu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftwa0ehx80dry67zfmldu.png" alt="Registro do aplicativo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assim que o registro do aplicativo for concluído o portal do azure irá redirecionar a página para a visão geral do aplicativo criado, uma página semelhante a imagem abaixo:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzwzmdzy9e8lxzepnztji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzwzmdzy9e8lxzepnztji.png" alt="Visão geral do aplicativo criado"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nessa tela o importante a destacar é o &lt;strong&gt;ID do aplicativo (cliente)&lt;/strong&gt;, esse código é utilizado como parte da validação de token de segurança entre o sistema web e o Active Directory.&lt;/p&gt;

&lt;p&gt;Para começar o projeto ReactJS vamos utilizar o &lt;strong&gt;npx create-react-app my-app&lt;/strong&gt; para criar o projeto base da aplicação e logo em seguida criaremos uma pasta &lt;strong&gt;pages&lt;/strong&gt; e dentro dela teremos duas pastas para ter rotas diferentes do projeto depois, são elas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/pages/SignIn/index.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import React, &lt;span class="o"&gt;{&lt;/span&gt; useCallback &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'react'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import &lt;span class="o"&gt;{&lt;/span&gt; useAuth &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'../../hooks/auth'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import logo from &lt;span class="s1"&gt;'../../assets/logo.svg'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="s1"&gt;'../../assets/styles.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const SignIn &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  const &lt;span class="o"&gt;{&lt;/span&gt; signIn &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; useAuth&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  const handleSignIn &lt;span class="o"&gt;=&lt;/span&gt; useCallback&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    const accessToken &lt;span class="o"&gt;=&lt;/span&gt; localStorage.getItem&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@AzureAd:accessToken'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;accessToken&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      signIn&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;signIn]&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &amp;lt;div &lt;span class="nv"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"App"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &amp;lt;img &lt;span class="nv"&gt;src&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;logo&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ReactJS, Azure AD"&lt;/span&gt; &lt;span class="nv"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"App-logo"&lt;/span&gt; /&amp;gt;

      &amp;lt;button &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"button"&lt;/span&gt; &lt;span class="nv"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;handleSignIn&lt;span class="o"&gt;}&amp;gt;&lt;/span&gt;Entrar&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;default SignIn&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/pages/Dashboard/index.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import React from &lt;span class="s1"&gt;'react'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import &lt;span class="o"&gt;{&lt;/span&gt; useAuth &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'../../hooks/auth'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import logo from &lt;span class="s1"&gt;'../../assets/logo.svg'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="s1"&gt;'../../assets/styles.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const Dashboard &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  const &lt;span class="o"&gt;{&lt;/span&gt; signOut, accountInfo &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; useAuth&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &amp;lt;div&amp;gt;
      &amp;lt;header &lt;span class="nv"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"App-header"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &amp;lt;img &lt;span class="nv"&gt;src&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;logo&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ReactJS, Azure AD"&lt;/span&gt; &lt;span class="nv"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"App-logo"&lt;/span&gt; /&amp;gt;

        &amp;lt;div&amp;gt;
          &amp;lt;p&amp;gt;Bem-vindo,
            &amp;lt;strong&amp;gt; &lt;span class="o"&gt;{&lt;/span&gt;accountInfo.user.displayName&lt;span class="o"&gt;}&lt;/span&gt;&amp;lt;/strong&amp;gt;
          &amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;button &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"button"&lt;/span&gt; &lt;span class="nv"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"App-button"&lt;/span&gt; &lt;span class="nv"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;signOut&lt;span class="o"&gt;}&amp;gt;&lt;/span&gt;sair&amp;lt;/button&amp;gt;
      &amp;lt;/header&amp;gt;
    &amp;lt;/div&amp;gt;
  &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;default Dashboard&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vale notar que nessas duas telas utilizamos o &lt;strong&gt;useAuth&lt;/strong&gt; que é um hook que foi criado para ter acesso ao login e informações do usuário logado, mais tarde vamos falar sobre esse hook.&lt;/p&gt;

&lt;p&gt;Agora criamos uma pasta &lt;strong&gt;routes&lt;/strong&gt;, nela vamos configurar a opção de rotas do projeto e definir qual rota será publica ou privada. A rota privada será acessada somente quando o usuário fizer o login que é autenticado pelo Azure AD.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/routes/Route.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import React from &lt;span class="s1"&gt;'react'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="o"&gt;{&lt;/span&gt; Route as ReactDOMRoute, Redirect &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'react-router-dom'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import &lt;span class="o"&gt;{&lt;/span&gt; useAuth &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'../hooks/auth'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const Route &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;({&lt;/span&gt;
  isPrivate &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;,
  component: Component,
  ...rest
&lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  const &lt;span class="o"&gt;{&lt;/span&gt; accountInfo &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; useAuth&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &amp;lt;ReactDOMRoute
      &lt;span class="o"&gt;{&lt;/span&gt;...rest&lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="nv"&gt;render&lt;/span&gt;&lt;span class="o"&gt;={({&lt;/span&gt; location &lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;isPrivate &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;accountInfo.user.email ? &lt;span class="o"&gt;(&lt;/span&gt;
          &amp;lt;Component /&amp;gt;
        &lt;span class="o"&gt;)&lt;/span&gt; : &lt;span class="o"&gt;(&lt;/span&gt;
          &amp;lt;Redirect
            &lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="o"&gt;={{&lt;/span&gt;
              pathname: isPrivate ? &lt;span class="s1"&gt;'/'&lt;/span&gt; : &lt;span class="s1"&gt;'/dashboard'&lt;/span&gt;,
              state: &lt;span class="o"&gt;{&lt;/span&gt; from: location &lt;span class="o"&gt;}&lt;/span&gt;,
            &lt;span class="o"&gt;}}&lt;/span&gt;
          /&amp;gt;
        &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="o"&gt;}}&lt;/span&gt;
    /&amp;gt;
  &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;default Route&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Na &lt;strong&gt;Route.js&lt;/strong&gt; utilizamos o hook useAuth para recuperar as informações do usuário logado e verificar se essas informações são validas a partir do e-mail dele.&lt;/p&gt;

&lt;p&gt;Se o e-mail do usuário for valido ele é redirecionado para a tela &lt;strong&gt;Dashboard&lt;/strong&gt; onde aparece uma mensagem de boas vindas junto ao nome do usuário que logou e se essa validação do e-mail for invalida o usuário é redirecionado para a tela &lt;strong&gt;SignIn&lt;/strong&gt; onde ele pode fazer o login para se autenticar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/routes/index.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import React from &lt;span class="s1"&gt;'react'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="o"&gt;{&lt;/span&gt; Switch &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'react-router-dom'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import Route from &lt;span class="s1"&gt;'./Route'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import SignIn from &lt;span class="s1"&gt;'../pages/SignIn'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import Dashboard from &lt;span class="s1"&gt;'../pages/Dashboard'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const Routes &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &amp;lt;Switch&amp;gt;
    &amp;lt;Route &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt; exact &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;SignIn&lt;span class="o"&gt;}&lt;/span&gt; /&amp;gt;

    &amp;lt;Route &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/dashboard"&lt;/span&gt; &lt;span class="nv"&gt;component&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;Dashboard&lt;span class="o"&gt;}&lt;/span&gt; isPrivate /&amp;gt;
  &amp;lt;/Switch&amp;gt;
&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;default Routes&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E para finalizar as configurações de rotas criamos um &lt;strong&gt;index.js&lt;/strong&gt; para exportar as configurações de rotas e os componentes que ele irá exibir de acordo com a rota do projeto.&lt;/p&gt;

&lt;p&gt;Para isso utilizamos a lib &lt;strong&gt;react-router-dom&lt;/strong&gt; que é muito utilizada em projeto ReactJS para fazer configurações de rotas e na página &lt;strong&gt;index.js&lt;/strong&gt; configuramos o &lt;strong&gt;&lt;/strong&gt; que foi desenvolvido anteriormente e que recebe os valores de &lt;strong&gt;path&lt;/strong&gt; que recebe o nome da rota, &lt;strong&gt;component&lt;/strong&gt; que recebe o componente a ser renderizado e por fim o &lt;strong&gt;isPrivate&lt;/strong&gt; que define qual rota é privada ou publica, que no nosso caso a rota &lt;strong&gt;/dashboard&lt;/strong&gt; será privada.&lt;/p&gt;

&lt;p&gt;Após as configurações de páginas e rotas partiremos para criação do &lt;strong&gt;hook useAuth&lt;/strong&gt; que vai ter as configurações para efetuar login, logout, acesso ao token e acesso ao usuário que são autenticados no Azure AD.&lt;/p&gt;

&lt;p&gt;Para começar vamos criar uma pasta &lt;strong&gt;hooks&lt;/strong&gt; e nela teremos algumas arquivos.&lt;/p&gt;

&lt;p&gt;No &lt;strong&gt;auth.js&lt;/strong&gt; vamos fazer as configurações de comunicação e validação com o Azure AD e utilizaremos a lib &lt;strong&gt;@azure/msal-browser&lt;/strong&gt; para fazer isso.&lt;/p&gt;

&lt;p&gt;Basicamente no &lt;strong&gt;auth.js&lt;/strong&gt; temos quatro métodos: signIn, signOut, getAccessToken, getUserProfile e um useEffect que faz uma primeira validação ao acessar a aplicação para saber se já existe um usuário logado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;signIn&lt;/strong&gt; é um método assíncrono que faz uma chamada para a lib &lt;strong&gt;@azure/msal-browser&lt;/strong&gt; abrir o login de usuário em modo &lt;strong&gt;Popup&lt;/strong&gt; passando as informações de configurações do Azure Ad que falaremos depois e recuperando esse usuário com o método &lt;strong&gt;getUserProfile&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;getUserProfile&lt;/strong&gt; que é chamado pelo &lt;strong&gt;signIn&lt;/strong&gt; envia as informações de request para o &lt;strong&gt;getAccessToken&lt;/strong&gt; que retorna se o token é válido ou não, se esse token existir ele chama uma configuração do &lt;strong&gt;graphService&lt;/strong&gt; para ter acesso as informações do usuário de acordo com o token, após isso ele salva o token no &lt;strong&gt;localStorage&lt;/strong&gt; para utilizar em outro momento e ainda salva um estado utilizando o &lt;strong&gt;useState&lt;/strong&gt; com as informações do usuário como &lt;strong&gt;displayName de mail&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;getAccessToken&lt;/strong&gt; faz a validação utilizando o &lt;strong&gt;getAllAccounts&lt;/strong&gt; para recuperar o token do usuário e ele tem dois métodos para isso um é o &lt;strong&gt;acquireTokenSilent&lt;/strong&gt; que valida o token sem interação do usuário e o outro é o &lt;strong&gt;acquireTokenPopup&lt;/strong&gt; que valida o token a partir do momento que o usuário faz o login no Popup que foi aberto pelo sistema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;signOut&lt;/strong&gt; esse método simples executa a remoção do token que foi salvo no localStorage e o logout da lib &lt;strong&gt;@azure/msal-browser&lt;/strong&gt; para fazer o logout daquele usuário logado.&lt;/p&gt;

&lt;p&gt;E por fim utilizamos o &lt;strong&gt;&lt;/strong&gt; para exportar os métodos &lt;strong&gt;signIn, signOut, accountInfo&lt;/strong&gt; que serão utilizados no projeto, esse último sendo um estado com as informações do usuário.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/hooks/auth.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import &lt;span class="o"&gt;{&lt;/span&gt;
  createContext,
  useCallback,
  useContext,
  useEffect,
  useState,
&lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'react'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="o"&gt;{&lt;/span&gt; PublicClientApplication &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'@azure/msal-browser'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import &lt;span class="o"&gt;{&lt;/span&gt;
  msalConfig,
  loginRequest,
&lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'../utils/configAzureAd'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="o"&gt;{&lt;/span&gt; getUserDetails &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'../utils/graphService'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const AuthContext &lt;span class="o"&gt;=&lt;/span&gt; createContext&lt;span class="o"&gt;({})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const msalInstance &lt;span class="o"&gt;=&lt;/span&gt; new PublicClientApplication&lt;span class="o"&gt;(&lt;/span&gt;msalConfig&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const AuthProvider &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;({&lt;/span&gt; children &lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  const &lt;span class="o"&gt;[&lt;/span&gt;accountInfo, setAccountInfo] &lt;span class="o"&gt;=&lt;/span&gt; useState&lt;span class="o"&gt;({&lt;/span&gt;
    isAuthenticated: &lt;span class="nb"&gt;false&lt;/span&gt;,
    user: &lt;span class="o"&gt;{}&lt;/span&gt;,
    error: null,
  &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  const signIn &lt;span class="o"&gt;=&lt;/span&gt; async &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    try &lt;span class="o"&gt;{&lt;/span&gt;
      await msalInstance.loginPopup&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;{&lt;/span&gt;
          scopes: loginRequest.scopes,
          prompt: &lt;span class="s2"&gt;"select_account"&lt;/span&gt;
        &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      await getUserProfile&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    catch &lt;span class="o"&gt;(&lt;/span&gt;err&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      setAccountInfo&lt;span class="o"&gt;({&lt;/span&gt;
        isAuthenticated: &lt;span class="nb"&gt;false&lt;/span&gt;,
        user: &lt;span class="o"&gt;{}&lt;/span&gt;,
        error: err,
      &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  const signOut &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    localStorage.removeItem&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@AzureAd:accessToken'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    msalInstance.logout&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  const getAccessToken &lt;span class="o"&gt;=&lt;/span&gt; async &lt;span class="o"&gt;(&lt;/span&gt;scopes&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    try &lt;span class="o"&gt;{&lt;/span&gt;
      const accounts &lt;span class="o"&gt;=&lt;/span&gt; msalInstance.getAllAccounts&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;accounts.length &amp;lt;&lt;span class="o"&gt;=&lt;/span&gt; 0&lt;span class="o"&gt;)&lt;/span&gt; throw new Error&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Login required'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      const silentResult &lt;span class="o"&gt;=&lt;/span&gt; await msalInstance.acquireTokenSilent&lt;span class="o"&gt;({&lt;/span&gt;
        scopes: scopes,
        account: accounts[0]
      &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;return &lt;/span&gt;silentResult.accessToken&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; catch &lt;span class="o"&gt;(&lt;/span&gt;err&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;err&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        const interactiveResult &lt;span class="o"&gt;=&lt;/span&gt; await msalInstance.acquireTokenPopup&lt;span class="o"&gt;({&lt;/span&gt;
          scopes: scopes,
        &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return &lt;/span&gt;interactiveResult.accessToken&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        throw err&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  const getUserProfile &lt;span class="o"&gt;=&lt;/span&gt; useCallback&lt;span class="o"&gt;(&lt;/span&gt;async &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    try &lt;span class="o"&gt;{&lt;/span&gt;
      const accessToken &lt;span class="o"&gt;=&lt;/span&gt; await getAccessToken&lt;span class="o"&gt;(&lt;/span&gt;loginRequest.scopes&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;accessToken&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        const user &lt;span class="o"&gt;=&lt;/span&gt; await getUserDetails&lt;span class="o"&gt;(&lt;/span&gt;accessToken&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        localStorage.setItem&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@AzureAd:accessToken'&lt;/span&gt;, accessToken&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        setAccountInfo&lt;span class="o"&gt;({&lt;/span&gt;
          isAuthenticated: &lt;span class="nb"&gt;true&lt;/span&gt;,
          user: &lt;span class="o"&gt;{&lt;/span&gt;
            displayName: user.displayName,
            email: user.mail &lt;span class="o"&gt;||&lt;/span&gt; user.userPrincipalName,
          &lt;span class="o"&gt;}&lt;/span&gt;,
          error: null
        &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    catch &lt;span class="o"&gt;(&lt;/span&gt;err&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      setAccountInfo&lt;span class="o"&gt;({&lt;/span&gt;
        isAuthenticated: &lt;span class="nb"&gt;false&lt;/span&gt;,
        user: &lt;span class="o"&gt;{}&lt;/span&gt;,
        error: err,
      &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;, &lt;span class="o"&gt;[])&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  useEffect&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    const accounts &lt;span class="o"&gt;=&lt;/span&gt; msalInstance.getAllAccounts&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;accounts &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; accounts.length &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 0&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      getUserProfile&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;getUserProfile]&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &amp;lt;AuthContext.Provider &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="o"&gt;={{&lt;/span&gt; signIn, signOut, accountInfo &lt;span class="o"&gt;}}&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;{&lt;/span&gt;children&lt;span class="o"&gt;}&lt;/span&gt;
    &amp;lt;/AuthContext.Provider&amp;gt;
  &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

const useAuth &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  const context &lt;span class="o"&gt;=&lt;/span&gt; useContext&lt;span class="o"&gt;(&lt;/span&gt;AuthContext&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;context&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    throw new Error&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'useAuth must be used within an AuthProvider'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;context&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; AuthProvider, useAuth &lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um ponto importante do &lt;strong&gt;auth.js&lt;/strong&gt; é que ele é criado como &lt;strong&gt;contextAPI&lt;/strong&gt; para ser possível repassar suas informações.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/hooks/index.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import React from &lt;span class="s1"&gt;'react'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import &lt;span class="o"&gt;{&lt;/span&gt; AuthProvider &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'./auth'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const AppProvider &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;({&lt;/span&gt; children &lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &amp;lt;AuthProvider&amp;gt;
    &lt;span class="o"&gt;{&lt;/span&gt;children&lt;span class="o"&gt;}&lt;/span&gt;
  &amp;lt;/AuthProvider&amp;gt;
&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;default AppProvider&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;strong&gt;index.js&lt;/strong&gt; é importante para exportar os métodos &lt;strong&gt;signIn, signOut, accountInfo&lt;/strong&gt; que foram desenvolvidos no &lt;strong&gt;auth.js&lt;/strong&gt;, com esses dois arquivos &lt;strong&gt;auth.js&lt;/strong&gt; e &lt;strong&gt;index.js&lt;/strong&gt; criamos um conceito no ReactJS que é chamado de &lt;strong&gt;contextAPI&lt;/strong&gt; onde é possível criar funções específicas e que serão utilizadas em mais de um lugar do projeto.&lt;/p&gt;

&lt;p&gt;No &lt;strong&gt;auth.js&lt;/strong&gt; usamos alguns dados que são acessos do Azure AD e uma configuração para recuperar informações do usuário que são disponibilizadas pela lib &lt;strong&gt;@microsoft/microsoft-graph-client&lt;/strong&gt; após o usuário realizar o login na aplicação.&lt;/p&gt;

&lt;p&gt;E para isso vamos criar uma pasta &lt;strong&gt;utils&lt;/strong&gt; para fazer essas configurações.&lt;/p&gt;

&lt;p&gt;No &lt;strong&gt;configAzureAd.js&lt;/strong&gt; temos as informações do &lt;strong&gt;clientId e redirectUri&lt;/strong&gt; que são disponibilizadas ao fazer o registro de um aplicativo no Azure AD e também temos a configuração do &lt;strong&gt;loginRequest&lt;/strong&gt; onde falamos em qual escopo o projeto terá acesso, que nesse caso é apenas para leitura das informações desse usuário.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/utils/configAzureAd.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;const msalConfig &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  auth: &lt;span class="o"&gt;{&lt;/span&gt;
    clientId: process.env.REACT_APP_CLIENT_ID,
    redirectUri: process.env.REACT_APP_REDIRECT_URI,
  &lt;span class="o"&gt;}&lt;/span&gt;,
  cache: &lt;span class="o"&gt;{&lt;/span&gt;
    cacheLocation: &lt;span class="s1"&gt;'localStorage'&lt;/span&gt;,
    storeAuthStateInCookie: &lt;span class="nb"&gt;false&lt;/span&gt;,
  &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;const loginRequest &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  scopes: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'user.read'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para segurança dos dados sensíveis utilizados no &lt;strong&gt;configAzureAd.js&lt;/strong&gt; foi criado um arquivo &lt;strong&gt;.env&lt;/strong&gt; na raíz do projeto, essas informações estão disponíveis ao cadastrar um resgistro de aplicativo no Azure AD.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Config Azure AD&lt;/span&gt;
&lt;span class="nv"&gt;REACT_APP_CLIENT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ID_do_aplicativo
&lt;span class="nv"&gt;REACT_APP_REDIRECT_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;URIs_de_Redirecionamento
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No &lt;strong&gt;graphService.js&lt;/strong&gt; só fazemos uma validação com o token recuperado após o login do usuário para recuperar da API &lt;strong&gt;graph&lt;/strong&gt; as informações do usuário como &lt;strong&gt;nome e e-mail&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/utils/graphService.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;const graph &lt;span class="o"&gt;=&lt;/span&gt; require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@microsoft/microsoft-graph-client'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;getAuthenticatedClient&lt;span class="o"&gt;(&lt;/span&gt;accessToken&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  const client &lt;span class="o"&gt;=&lt;/span&gt; graph.Client.init&lt;span class="o"&gt;({&lt;/span&gt;
    authProvider: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;null, accessToken&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;client&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;async &lt;span class="k"&gt;function &lt;/span&gt;getUserDetails&lt;span class="o"&gt;(&lt;/span&gt;accessToken&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  const client &lt;span class="o"&gt;=&lt;/span&gt; getAuthenticatedClient&lt;span class="o"&gt;(&lt;/span&gt;accessToken&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  const user &lt;span class="o"&gt;=&lt;/span&gt; await client
    .api&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/me'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    .select&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'displayName,mail,userPrincipalName'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    .get&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;user&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E para finalizar no &lt;strong&gt;App.js&lt;/strong&gt; importamos do &lt;strong&gt;Routes&lt;/strong&gt; as configurações de rotas que a aplicação terá acesso e também o &lt;strong&gt;AppProvider&lt;/strong&gt; que vai disponibilizar os métodos de &lt;strong&gt;signIn, signOut, accountInfo&lt;/strong&gt; que serão utilizados em outros componentes utilizando o &lt;strong&gt;contextAPI&lt;/strong&gt; para passar as informações.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/App.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import React from &lt;span class="s1"&gt;'react'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="o"&gt;{&lt;/span&gt; BrowserRouter as Router &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'react-router-dom'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import AppProvider from &lt;span class="s1"&gt;'./hooks'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import Routes from &lt;span class="s1"&gt;'./routes'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const App &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
  &amp;lt;Router&amp;gt;
    &amp;lt;AppProvider&amp;gt;
      &amp;lt;Routes /&amp;gt;
    &amp;lt;/AppProvider&amp;gt;
  &amp;lt;/Router&amp;gt;
&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;default App&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E assim finalizamos o projeto com autenticação via Azure AD, trazendo uma visão de como funciona o Azure AD e suas configurações e o seu funcionamento com o ReactJS. Espero ter ajudado!&lt;/p&gt;

&lt;p&gt;Vale lembrar que com o próprio Azure AD você consegue criar outras configurações de permissões para quem vai acessar a aplicação, criação de grupos de usuários, e até mesmo fazer configurações para validar o token do login em uma API Rest criada pelo back end por exemplo.&lt;/p&gt;

&lt;p&gt;Referência:&lt;br&gt;
&lt;a href="https://docs.microsoft.com/pt-br/graph/tutorials/react" rel="noopener noreferrer"&gt;https://docs.microsoft.com/pt-br/graph/tutorials/react&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O projeto completo pode ser baixado no github:&lt;br&gt;
&lt;a href="https://github.com/felipedesenna/react-authentication-azuread" rel="noopener noreferrer"&gt;https://github.com/felipedesenna/react-authentication-azuread&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>azure</category>
    </item>
    <item>
      <title>Variável de ambiente - (ReactJS, Docker, AKS)</title>
      <dc:creator>Felipe de Senna</dc:creator>
      <pubDate>Thu, 28 Jan 2021 22:48:23 +0000</pubDate>
      <link>https://dev.to/felipedesenna/variavel-de-ambiente-reactjs-docker-aks-4hb3</link>
      <guid>https://dev.to/felipedesenna/variavel-de-ambiente-reactjs-docker-aks-4hb3</guid>
      <description>&lt;p&gt;A maioria dos projetos hoje em dia são desenvolvidos para diversos ambientes de trabalho (homolog, staging, production). E junto com esses ambientes temos a preocupação com a infraestrutura que o projeto vai utilizar, além do &lt;strong&gt;Framework&lt;/strong&gt; utilizado no front-end para usabilidade e visualização de conteúdo.&lt;/p&gt;

&lt;p&gt;Seguindo nesse raciocínio vamos falar sobre como utilizar variável de ambiente em um projeto que utiliza &lt;strong&gt;ReactJS, Docker e AKS&lt;/strong&gt;, fazendo uma configuração simples para conseguir consumir a URL de uma API diferente de acordo com o ambiente em que o usuário está.&lt;/p&gt;

&lt;p&gt;Após criar o projeto base com o &lt;strong&gt;&lt;code&gt;npx create-react-app my-app&lt;/code&gt;&lt;/strong&gt; vamos criar uma pasta onde ficará as configurações de variáveis para cada ambiente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;environments/base.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;default &lt;span class="o"&gt;{&lt;/span&gt;
  api: &lt;span class="s1"&gt;'http://localhost:5000/api'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;strong&gt;&lt;code&gt;base.js&lt;/code&gt;&lt;/strong&gt; é um arquivo inicial com o proposito de ser utilizado se nenhum outro arquivo ambiente for detectado pelas configurações.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;environments/Homolog.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;default &lt;span class="o"&gt;{&lt;/span&gt;
  api: &lt;span class="s1"&gt;'http://suaapi.hlg.seudominio.com.br/api'&lt;/span&gt;,
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;environments/Staging.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;default &lt;span class="o"&gt;{&lt;/span&gt;
  api: &lt;span class="s1"&gt;'http://suaapi.stg.seudominio.com.br/api'&lt;/span&gt;,
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;environments/Production.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;default &lt;span class="o"&gt;{&lt;/span&gt;
  api: &lt;span class="s1"&gt;'http://suaapi.prd.seudominio.com.br/api'&lt;/span&gt;,
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora para finalizar as configurações das variáveis de ambiente vamos criar um último arquivo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;environments/index.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import base from &lt;span class="s1"&gt;'./base'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;window.ENV&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  localStorage.setItem&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@environment'&lt;/span&gt;, window.ENV&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  delete window.ENV&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

const envClient &lt;span class="o"&gt;=&lt;/span&gt; localStorage.getItem&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@environment'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
const environments &lt;span class="o"&gt;=&lt;/span&gt; envClient &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'base'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

const &lt;span class="nb"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./'&lt;/span&gt; + environments&lt;span class="o"&gt;)&lt;/span&gt;.default&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;default &lt;span class="o"&gt;{&lt;/span&gt;
  ...base,
  ...env,
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nessa configuração verificamos se existe algum valor em &lt;strong&gt;&lt;code&gt;window.ENV&lt;/code&gt;&lt;/strong&gt; se existir valor salvamos ele no &lt;strong&gt;&lt;code&gt;localStorage&lt;/code&gt;&lt;/strong&gt; e deletamos o &lt;strong&gt;&lt;code&gt;window.ENV&lt;/code&gt;&lt;/strong&gt;, depois recuperamos esse valor salvo no &lt;strong&gt;&lt;code&gt;localStorage&lt;/code&gt;&lt;/strong&gt; para utiliza-lo e caso esse valor não exista utilizamos &lt;strong&gt;&lt;code&gt;'base'&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
Ao final da configuração criamos uma nova importação utilizando &lt;strong&gt;&lt;code&gt;require&lt;/code&gt;&lt;/strong&gt; onde ela importa o arquivo correto utilizando a variável &lt;strong&gt;&lt;code&gt;environments&lt;/code&gt;&lt;/strong&gt; que pode conter o valor do &lt;strong&gt;&lt;code&gt;localStorage&lt;/code&gt;&lt;/strong&gt; ou &lt;strong&gt;&lt;code&gt;'base'&lt;/code&gt;&lt;/strong&gt; e na conclusão exportamos as variáveis &lt;strong&gt;&lt;code&gt;base&lt;/code&gt;&lt;/strong&gt; e &lt;strong&gt;&lt;code&gt;env&lt;/code&gt;&lt;/strong&gt; onde teremos as informações necessárias para utilizar mais tarde.&lt;/p&gt;

&lt;p&gt;Seguindo na configuração de variáveis de ambiente eu fiz uma alteração no &lt;strong&gt;&lt;code&gt;App.js&lt;/code&gt;&lt;/strong&gt;, essa alteração é simplesmente para exibir a variável &lt;strong&gt;&lt;code&gt;env.api&lt;/code&gt;&lt;/strong&gt; que vai ser consumida das configurações que fizemos anteriormente na pasta environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;App.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import React from &lt;span class="s1"&gt;'react'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

import logo from &lt;span class="s1"&gt;'./logo.svg'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="nb"&gt;env &lt;/span&gt;from &lt;span class="s1"&gt;'./environments'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="s1"&gt;'./App.css'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;App&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;
    &amp;lt;div &lt;span class="nv"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"App"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &amp;lt;header &lt;span class="nv"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"App-header"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &amp;lt;img &lt;span class="nv"&gt;src&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;logo&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"App-logo"&lt;/span&gt; &lt;span class="nv"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"logo"&lt;/span&gt; /&amp;gt;
        &amp;lt;p&amp;gt;&lt;span class="o"&gt;{&lt;/span&gt;env.api&lt;span class="o"&gt;}&lt;/span&gt;&amp;lt;/p&amp;gt;
      &amp;lt;/header&amp;gt;
    &amp;lt;/div&amp;gt;
  &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;default App&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E para finalizar a configuração inicial e antes de partirmos para a criação da imagem do Docker e as configurações .YAML do Kubernetes, faremos algumas modificações na pasta &lt;strong&gt;&lt;code&gt;public&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Primeiro vamos criar um novo arquivo .js dentro dela.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;config.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;window.ENV &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Homolog"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dentro desse arquivo temos uma configuração do &lt;strong&gt;&lt;code&gt;window.ENV&lt;/code&gt;&lt;/strong&gt; que utilizamos para leitura dentro do &lt;strong&gt;&lt;code&gt;environments/index.js&lt;/code&gt;&lt;/strong&gt; e que futuramente vai ser alterada via Kubernetes.&lt;/p&gt;

&lt;p&gt;Logo após a criação desse arquivo vamos adicionar mais um script dentro do arquivo &lt;strong&gt;&lt;code&gt;index.html&lt;/code&gt;&lt;/strong&gt; que fica na pasta public.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;index.html&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;script &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"text/javascript"&lt;/span&gt; &lt;span class="nv"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"%PUBLIC_URL%/config.js"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa alteração é para o projeto conseguir consumir o arquivo &lt;strong&gt;&lt;code&gt;config.js&lt;/code&gt;&lt;/strong&gt; após o build do projeto.&lt;/p&gt;

&lt;h2&gt;Configuração de build e Kubernetes&lt;/h2&gt;

&lt;p&gt;Antes de criar a imagem do projeto no Docker vamos primeiro executar o build do próprio ReactJS, o que vai facilitar a criação da imagem no Docker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build / yarn build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para criação da imagem do Docker o arquivo &lt;strong&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/strong&gt; ficará da seguinte maneira:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stage 1&lt;/span&gt;
FROM nginx:1.17

&lt;span class="c"&gt;# Stage 2&lt;/span&gt;
COPY build/ /usr/share/nginx/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Além de já utilizar o build que foi feito pelo ReactJS anteriormente, utilizamos o nginx para rodar o html do projeto. Vale lembrar que o arquivo &lt;strong&gt;&lt;code&gt;.dockerignore&lt;/code&gt;&lt;/strong&gt; não deve conter a pasta build, porque se não ocorrerá um erro quando a imagem for criada.&lt;/p&gt;

&lt;p&gt;Seguiremos para criação da imagem do Docker executando os comando na sequencia:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;1 - Criando a imagem &lt;span class="k"&gt;do &lt;/span&gt;projeto
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; react-docker-aks &lt;span class="nb"&gt;.&lt;/span&gt;

2 - Criação &lt;span class="k"&gt;do &lt;/span&gt;registro no Docker &lt;span class="nb"&gt;local
&lt;/span&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 5000:5000 &lt;span class="nt"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;always &lt;span class="nt"&gt;--name&lt;/span&gt; registry registry:2

3 - Criação de tag para referencia da imagem
docker tag react-docker-aks localhost:5000/react-docker-aks

4 - Fazendo o push da imagem para o Docker &lt;span class="nb"&gt;local
&lt;/span&gt;docker push localhost:5000/react-docker-aks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obs.: é importante lembrar que para executar os comandos acima é necessário ter o Docker Desktop instalado na máquina.&lt;/p&gt;

&lt;p&gt;E para finalizar criaremos os arquivos .YAML que são utilizados pelo Kubernetes para configuração dos clusters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;deployment.yaml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apiVersion: v1
kind: ConfigMap
metadata:
  name: react-docker-aks
  labels:
    app: react-docker-aks
data:
  config.js: &lt;span class="s2"&gt;"window.ENV = &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Homolog&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;
&lt;span class="nt"&gt;---&lt;/span&gt;
kind: Deployment
apiVersion: apps/v1
metadata:
  name: react-docker-aks
spec:
  replicas: 1
  selector:
    matchLabels:
      app: react-docker-aks
  template:
    metadata:
      labels:
        app: react-docker-aks
    spec:
      containers:
        - name: react-docker-aks
          image: localhost:5000/react-docker-aks
          imagePullPolicy: Always
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config-js
              mountPath: /usr/share/nginx/html/config.js
              subPath: config.js
      volumes:
        - name: config-js
          configMap:
            name: react-docker-aks
      restartPolicy: Always
&lt;span class="nt"&gt;---&lt;/span&gt;
kind: Service
apiVersion: v1
metadata:
  name: react-docker-aks
spec:
  &lt;span class="nb"&gt;type&lt;/span&gt;: NodePort
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
      nodePort: 31000
  selector:
    app: react-docker-aks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Na criação dos arquivos .YAML utilizamos uma estrutura padrão de configuração adicionando apenas alguns métodos que serviram para leitura e configuração do arquivo &lt;strong&gt;&lt;code&gt;config.js&lt;/code&gt;&lt;/strong&gt; que está na pasta public do projeto. São eles:&lt;/p&gt;

&lt;p&gt;No &lt;strong&gt;&lt;code&gt;ConfigMap&lt;/code&gt;&lt;/strong&gt; adicionei&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;data:
  config.js: &lt;span class="s2"&gt;"window.ENV = &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Homolog&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No &lt;strong&gt;&lt;code&gt;Deployment&lt;/code&gt;&lt;/strong&gt; dentro de spec containers&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;volumeMounts:
  - name: config-js
    mountPath: /usr/share/nginx/html/config.js
    subPath: config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E a criação do volumes dentro do spec&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;volumes:
  - name: config-js
    configMap:
      name: react-docker-aks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Foi uma escolha minha criar todas as configurações dentro do arquivo &lt;strong&gt;&lt;code&gt;deployment.yaml&lt;/code&gt;&lt;/strong&gt; mas da certo criando os arquivos separados em &lt;strong&gt;&lt;code&gt;configmap.yaml&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;deployment.yaml&lt;/code&gt;&lt;/strong&gt; e &lt;strong&gt;&lt;code&gt;service.yaml&lt;/code&gt;&lt;/strong&gt;, e depois criando o &lt;strong&gt;&lt;code&gt;kustomization.yaml&lt;/code&gt;&lt;/strong&gt; para juntar todos eles.&lt;/p&gt;

&lt;p&gt;Para simular outros ambientes eu criei mais dois arquivos &lt;strong&gt;&lt;code&gt;deployment.yaml&lt;/code&gt;&lt;/strong&gt; o &lt;strong&gt;&lt;code&gt;deployment-staging.yaml&lt;/code&gt;&lt;/strong&gt; e &lt;strong&gt;&lt;code&gt;deployment-production.yaml&lt;/code&gt;&lt;/strong&gt; que tem o mesmo conteúdo do primeiro só modificando namespace, o valor do window.ENV e criando uma outra porta pro service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;deployment-staging.yaml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apiVersion: v1
kind: ConfigMap
metadata:
  name: react-docker-aks-stg
  labels:
    app: react-docker-aks-stg
data:
  config.js: &lt;span class="s2"&gt;"window.ENV = &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Staging&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;
&lt;span class="nt"&gt;--------&lt;/span&gt;
kind: Deployment
apiVersion: apps/v1
metadata:
  name: react-docker-aks-stg
spec:
  replicas: 1
  selector:
    matchLabels:
      app: react-docker-aks-stg
  template:
    metadata:
      labels:
        app: react-docker-aks-stg
    spec:
      containers:
        - name: react-docker-aks-stg
          image: localhost:5000/react-docker-aks
          imagePullPolicy: Always
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config-js
              mountPath: /usr/share/nginx/html/config.js
              subPath: config.js
      volumes:
        - name: config-js
          configMap:
            name: react-docker-aks-stg
      restartPolicy: Always
&lt;span class="nt"&gt;--------&lt;/span&gt;
kind: Service
apiVersion: v1
metadata:
  name: react-docker-aks-stg
spec:
  &lt;span class="nb"&gt;type&lt;/span&gt;: NodePort
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
      nodePort: 31001
  selector:
    app: react-docker-aks-stg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;deployment-production.yaml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apiVersion: v1
kind: ConfigMap
metadata:
  name: react-docker-aks-prd
  labels:
    app: react-docker-aks-prd
data:
  config.js: &lt;span class="s2"&gt;"window.ENV = &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Production&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;
&lt;span class="nt"&gt;--------&lt;/span&gt;
kind: Deployment
apiVersion: apps/v1
metadata:
  name: react-docker-aks-prd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: react-docker-aks-prd
  template:
    metadata:
      labels:
        app: react-docker-aks-prd
    spec:
      containers:
        - name: react-docker-aks-prd
          image: localhost:5000/react-docker-aks
          imagePullPolicy: Always
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config-js
              mountPath: /usr/share/nginx/html/config.js
              subPath: config.js
      volumes:
        - name: config-js
          configMap:
            name: react-docker-aks-prd
      restartPolicy: Always
&lt;span class="nt"&gt;--------&lt;/span&gt;
kind: Service
apiVersion: v1
metadata:
  name: react-docker-aks-prd
spec:
  &lt;span class="nb"&gt;type&lt;/span&gt;: NodePort
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
      nodePort: 31002
  selector:
    app: react-docker-aks-prd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para executar o Kubernetes no Docker Desktop é necessário ativar-lo e também é preciso ter o Minikube instalado para executar os comandos que virão na sequencia.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Ativando o Kubernetes&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--58asKZcq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/felipedesenna/react-docker-aks/raw/main/src/img/kubernetes-docker-desktop.png" class="article-body-image-wrapper"&gt;&lt;img alt="Ativando o Kubernetes no Docker-Desktop" src="https://res.cloudinary.com/practicaldev/image/fetch/s--58asKZcq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/felipedesenna/react-docker-aks/raw/main/src/img/kubernetes-docker-desktop.png" width="830px"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Executando os comandos&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;1 - Criando o contexto padrão para o cluster &lt;span class="k"&gt;do &lt;/span&gt;Kubernetes
kubectl config use-context docker-desktop

2 - Criando o serviço Kubernetes
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; deployment.yaml

3 - Serviço &lt;span class="k"&gt;do &lt;/span&gt;ambiente staging
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; deployment-staging.yaml

4 - Serviço &lt;span class="k"&gt;do &lt;/span&gt;ambiente production
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; deployment-production.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os ambientes ficaram disponivéis nas URLs:&lt;br&gt;
&lt;strong&gt;HLG&lt;/strong&gt;&lt;br&gt;
&lt;a href="http://localhost:31000/"&gt;http://localhost:31000/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STG&lt;/strong&gt;&lt;br&gt;
&lt;a href="http://localhost:31001/"&gt;http://localhost:31001/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PRD&lt;/strong&gt;&lt;br&gt;
&lt;a href="http://localhost:31002/"&gt;http://localhost:31002/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E assim se concluí o projeto e todas as configurações realizadas para conseguir ler uma variável de ambiente após o build do ReactJS via Kubernetes.&lt;br&gt;
O projeto todo pode ser acessado e baixado no meu github: &lt;a href="https://github.com/felipedesenna/react-docker-aks"&gt;https://github.com/felipedesenna/react-docker-aks&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>docker</category>
      <category>kubernetes</category>
    </item>
  </channel>
</rss>
