## ⚖️ License
From 62e19c250f4e4b9347d96300c70987472f4a7cfe Mon Sep 17 00:00:00 2001
From: David Nahodyl
Date: Fri, 20 Dec 2024 15:09:50 -0500
Subject: [PATCH 25/51] docs: add recipe for session and authentication
(#27287)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Sébastien Chopin
---
.../4.sessions-and-authentication.md | 203 ++++++++++++++++++
1 file changed, 203 insertions(+)
create mode 100644 docs/2.guide/4.recipes/4.sessions-and-authentication.md
diff --git a/docs/2.guide/4.recipes/4.sessions-and-authentication.md b/docs/2.guide/4.recipes/4.sessions-and-authentication.md
new file mode 100644
index 0000000000..6a45db6bbb
--- /dev/null
+++ b/docs/2.guide/4.recipes/4.sessions-and-authentication.md
@@ -0,0 +1,203 @@
+---
+title: 'Sessions and Authentication'
+description: "Authentication is an extremely common requirement in web apps. This recipe will show you how to implement basic user registration and authentication in your Nuxt app."
+---
+
+## Introduction
+
+In this recipe we'll be setting up authentication in a full-stack Nuxt app using [Nuxt Auth Utils](https://github.com/Atinux/nuxt-auth-utils) which provides convenient utilities for managing client-side and server-side session data.
+
+The module uses secured & sealed cookies to store session data, so you don't need to setup a database to store session data.
+
+## Install nuxt-auth-utils
+
+Install the `nuxt-auth-utils` module using the `nuxi` CLI.
+
+```bash [Terminal]
+npx nuxi@latest module add auth-utils
+```
+
+::callout
+This command will install `nuxt-auth-utils` as dependency and push it in the `modules` section of our `nuxt.config.ts`
+::
+
+## Cookie Encryption Key
+
+As `nuxt-auth-utils` uses sealed cookies to store session data, session cookies are encrypted using a secret key from the `NUXT_SESSION_PASSWORD` environment variable.
+
+::note
+If not set, this environment variable will be added to your `.env` automatically when running in development mode.
+::
+
+```dotenv [.env]
+NUXT_SESSION_PASSWORD=a-random-password-with-at-least-32-characters
+```
+
+::important
+You'll need to add this environment variable to your production environment before deploying.
+::
+
+## Login API Route
+
+For this recipe, we'll create a simple API route to sign-in a user based on static data.
+
+Let's create a `/api/login` API route that will accept a POST request with the email and password in the request body.
+
+```ts [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') {
+ // set the user session in the cookie
+ // this server util is auto-imported by the auth-utils module
+ await setUserSession(event, {
+ user: {
+ name: 'John Doe'
+ }
+ })
+ return {}
+ }
+ throw createError({
+ statusCode: 401,
+ message: 'Bad credentials'
+ })
+})
+```
+
+::callout
+Make sure to install the `zod` dependency in your project (`npm i zod`).
+::
+
+::tip{to="https://github.com/atinux/nuxt-auth-utils#server-utils"}
+Read more about the `setUserSession` server helper exposed by `nuxt-auth-utils`.
+::
+
+## Login Page
+
+The module exposes a Vue composable to know if a user is authenticated in our application:
+
+```vue
+
+```
+
+Let's create a login page with a form to submit the login data to our `/api/login` route.
+
+```vue [pages/login.vue]
+
+
+
+
+
+```
+
+## Protect API Routes
+
+Protecting server routes is key to making sure your data is safe. Client-side middleware is helpful for the user, but without server-side protection your data can still be accessed. It is critical to protect any routes with sensitive data, we should return a 401 error if the user is not logged in on those.
+
+The `auth-utils` module provides the `requireUserSession` utility function to help make sure that users are logged in and have an active session.
+
+Let's create an example of a `/api/user/stats` route that only authenticated users can access.
+
+```ts [server/api/user/stats.get.ts]
+export default defineEventHandler(async (event) => {
+ // make sure the user is logged in
+ // This will throw a 401 error if the request doesn't come from a valid user session
+ const { user } = await requireUserSession(event)
+
+ // TODO: Fetch some stats based on the user
+
+ return {}
+});
+```
+
+## Protect App Routes
+
+Our data is safe with the server-side route in place, but without doing anything else, unauthenticated users would probably get some odd data when trying to access the `/users` page. We should create a [client-side middleware](https://nuxt.com/docs/guide/directory-structure/middleware) to protect the route on the client side and redirect users to the login page.
+
+`nuxt-auth-utils` provides a convenient `useUserSession` composable which we'll use to check if the user is logged in, and redirect them if they are not.
+
+We'll create a middleware in the `/middleware` directory. Unlike on the server, client-side middleware is not automatically applied to all endpoints, and we'll need to specify where we want it applied.
+
+```typescript [middleware/authenticated.ts]
+export default defineNuxtRouteMiddleware(() => {
+ const { loggedIn } = useUserSession()
+
+ // redirect the user to the login screen if they're not authenticated
+ if (!loggedIn.value) {
+ return navigateTo('/login')
+ }
+})
+```
+
+## Home Page
+
+Now that we have our app middleware to protect our routes, we can use it on our home page that display our authenticated user informations. If the user is not authenticated, they will be redirected to the login page.
+
+We'll use [`definePageMeta`](/docs/api/utils/define-page-meta) to apply the middleware to the route that we want to protect.
+
+```vue [pages/index.vue]
+
+
+
+