nuxt logo

Tradução da Documentação (Não Oficial)

Nuxt.js
Version:v3.17

Sessões e Autenticação

Autenticação é um requisito extremamente comum em aplicativos web. Esta receita mostrará como implementar registro básico de usuário e autenticação em seu aplicativo Nuxt.

Introdução

Nesta receita, configuraremos a autenticação em um aplicativo Nuxt full-stack usando Nuxt Auth Utils, que fornece utilitários convenientes para gerenciar dados de sessão no lado do cliente e do servidor.

O módulo usa cookies seguros e selados para armazenar dados de sessão, então você não precisa configurar um banco de dados para armazenar dados de sessão.

Instalar nuxt-auth-utils

Instale o módulo nuxt-auth-utils usando o CLI do nuxt.

Terminal
npx nuxt module add auth-utils

Este comando instalará nuxt-auth-utils como dependência e o adicionará na seção modules do nosso nuxt.config.ts

Como nuxt-auth-utils usa cookies selados para armazenar dados de sessão, os cookies de sessão são criptografados usando uma chave secreta da variável de ambiente NUXT_SESSION_PASSWORD.

Se não estiver definida, esta variável de ambiente será adicionada automaticamente ao seu .env quando estiver em modo de desenvolvimento.

.env
NUXT_SESSION_PASSWORD=a-random-password-with-at-least-32-characters

Você precisará adicionar esta variável de ambiente ao seu ambiente de produção antes de implantar.

Rota de API de Login

Para esta receita, criaremos uma rota de API simples para fazer login de um usuário com base em dados estáticos.

Vamos criar uma rota de API /api/login que aceitará uma solicitação POST com o email e a senha no corpo da solicitação.

server/api/login.post.ts
import { z } from 'zod'

const bodySchema = z.object({
  email: z.string().email(),
  password: z.string().min(8)
})

export default defineEventHandler(async (event) => {
  const { email, password } = await readValidatedBody(event, bodySchema.parse)

  if (email === 'admin@admin.com' && password === 'iamtheadmin') {
    // define a sessão do usuário no cookie
    // este utilitário do servidor é importado automaticamente pelo módulo auth-utils
    await setUserSession(event, {
      user: {
        name: 'John Doe'
      }
    })
    return {}
  }
  throw createError({
    statusCode: 401,
    message: 'Credenciais inválidas'
  })
})

Certifique-se de instalar a dependência zod em seu projeto (npm i zod).

Leia mais sobre o helper de servidor setUserSession exposto por nuxt-auth-utils.

Página de Login

O módulo expõe um composable Vue para saber se um usuário está autenticado em nossa aplicação:

const { loggedIn, session, user, clear, fetch } = useUserSession()

Vamos criar uma página de login com um formulário para enviar os dados de login para nossa rota /api/login.

pages/login.vue
<script setup lang="ts">
const { loggedIn, user, fetch: refreshSession } = useUserSession()
const credentials = reactive({
  email: '',
  password: '',
})
async function login() {
  $fetch('/api/login', {
    method: 'POST',
    body: credentials
  })
  .then(async () => {
    // Atualiza a sessão no lado do cliente e redireciona para a página inicial
    await refreshSession()
    await navigateTo('/')
  })
  .catch(() => alert('Credenciais inválidas'))
}
</script>

<template>
  <form @submit.prevent="login">
    <input v-model="credentials.email" type="email" placeholder="Email" />
    <input v-model="credentials.password" type="password" placeholder="Senha" />
    <button type="submit">Login</button>
  </form>
</template>

Proteger Rotas de API

Proteger rotas do servidor é fundamental para garantir que seus dados estejam seguros. Middleware no lado do cliente é útil para o usuário, mas sem proteção no lado do servidor, seus dados ainda podem ser acessados. É crucial proteger qualquer rota com dados sensíveis, devemos retornar um erro 401 se o usuário não estiver logado.

O módulo auth-utils fornece a função utilitária requireUserSession para ajudar a garantir que os usuários estejam logados e tenham uma sessão ativa.

Vamos criar um exemplo de uma rota /api/user/stats que apenas usuários autenticados podem acessar.

server/api/user/stats.get.ts
export default defineEventHandler(async (event) => {
  // certifique-se de que o usuário está logado
  // Isso lançará um erro 401 se a solicitação não vier de uma sessão de usuário válida
  const { user } = await requireUserSession(event)

  // TODO: Buscar algumas estatísticas com base no usuário

  return {}
});

Proteger Rotas do Aplicativo

Nossos dados estão seguros com a rota do lado do servidor em vigor, mas sem fazer mais nada, usuários não autenticados provavelmente obteriam alguns dados estranhos ao tentar acessar a página /users. Devemos criar um middleware do lado do cliente para proteger a rota no lado do cliente e redirecionar os usuários para a página de login.

nuxt-auth-utils fornece um composable conveniente useUserSession que usaremos para verificar se o usuário está logado e redirecioná-lo se não estiver.

Vamos criar um middleware no diretório /middleware. Ao contrário do servidor, o middleware do lado do cliente não é aplicado automaticamente a todos os endpoints, e precisaremos especificar onde queremos que ele seja aplicado.

middleware/authenticated.ts
export default defineNuxtRouteMiddleware(() => {
  const { loggedIn } = useUserSession()

  // redireciona o usuário para a tela de login se não estiver autenticado
  if (!loggedIn.value) {
    return navigateTo('/login')
  }
})

Página Inicial

Agora que temos nosso middleware de aplicativo para proteger nossas rotas, podemos usá-lo em nossa página inicial que exibe as informações do usuário autenticado. Se o usuário não estiver autenticado, ele será redirecionado para a página de login.

Usaremos definePageMeta para aplicar o middleware à rota que queremos proteger.

pages/index.vue
<script setup lang="ts">
definePageMeta({
  middleware: ['authenticated'],
})
  
const { user, clear: clearSession } = useUserSession()

async function logout() {
  await clearSession()
  await navigateTo('/login')
}
</script>

<template>
  <div>
    <h1>Bem-vindo {{ user.name }}</h1>
    <button @click="logout">Logout</button>
  </div>
</template>

Também adicionamos um botão de logout para limpar a sessão e redirecionar o usuário para a página de login.

Conclusão

Configuramos com sucesso uma autenticação de usuário muito básica e gerenciamento de sessão em nosso aplicativo Nuxt. Também protegemos rotas sensíveis no lado do servidor e do cliente para garantir que apenas usuários autenticados possam acessá-las.

Como próximos passos, você pode:

Confira o repositório open source atidone para um exemplo completo de um aplicativo Nuxt com autenticação OAuth, banco de dados e operações CRUD.