---
title: "Auth Setup"
description: "Install the nuxt-auth-utils module, register a GitHub OAuth app, configure environment variables, and create the OAuth callback handler."
canonical_url: "https://vercel.com/academy/nuxt-on-vercel/auth-setup"
md_url: "https://vercel.com/academy/nuxt-on-vercel/auth-setup.md"
docset_id: "vercel-academy"
doc_version: "1.0"
last_updated: "2026-10-16T17:45:50.191Z"
content_type: "lesson"
course: "nuxt-on-vercel"
course_title: "Nuxt on Vercel"
prerequisites:  []
---

<agent-instructions>
Vercel Academy — structured learning, not reference docs.
Lessons are sequenced.
Adapt commands to the human's actual environment (OS, package manager, shell, editor) — detect from project context or ask, don't assume.
The lesson shows one path; if the human's project diverges, adapt concepts to their setup.
Preserve the learning goal over literal steps.
Quizzes are pedagogical — engage, don't spoil.
Quiz answers are included for your reference.
</agent-instructions>

# Auth Setup

# Auth Setup

Next.js applications can use libraries such as NextAuth, Clerk, or Lucia, each with its own provider and session configuration.

This project uses `nuxt-auth-utils`, which provides session handling and OAuth helpers. You'll add the module, create a callback route, and configure the required environment variables.

## Outcome

Install `nuxt-auth-utils`, register a GitHub OAuth app, and create the server-side callback handler.

## Fast Track

1. Install `nuxt-auth-utils` and add it to `nuxt.config.ts`
2. Register a GitHub OAuth app and set environment variables
3. Create the GitHub OAuth handler in `server/routes/auth/github.get.ts`

## Hands-on exercise 3.1

Wire up GitHub OAuth from scratch.

**Requirements:**

1. Install `nuxt-auth-utils` and add it to the `modules` array in `nuxt.config.ts`
2. Register a new OAuth app on GitHub with the callback URL `http://localhost:3000/auth/github`
3. Create a `.env` file with `NUXT_OAUTH_GITHUB_CLIENT_ID`, `NUXT_OAUTH_GITHUB_CLIENT_SECRET`, and `NUXT_SESSION_PASSWORD`
4. Create `server/routes/auth/github.get.ts` that handles the OAuth callback
5. On success, store the user's login, avatar URL, and ID in the session

**Implementation hints:**

- `nuxt-auth-utils` auto-imports `defineOAuthGitHubEventHandler`, `setUserSession`, `getUserSession`, and `requireUserSession` in server routes
- It also auto-imports `useUserSession` in Vue components
- The module reads `NUXT_OAUTH_GITHUB_CLIENT_ID` and `NUXT_OAUTH_GITHUB_CLIENT_SECRET` automatically. No config mapping needed
- `NUXT_SESSION_PASSWORD` must be at least 32 characters. It encrypts the session cookie
- Server routes in `server/routes/` (not `server/api/`) map directly to URLs. `server/routes/auth/github.get.ts` becomes `/auth/github`

First, update the Nuxt config to include the module:

```typescript title="nuxt.config.ts" {6}
import tailwindcss from "@tailwindcss/vite";

export default defineNuxtConfig({
  compatibilityDate: "2025-05-01",

  modules: ["nuxt-auth-utils"],

  css: ["~/assets/css/main.css"],

  vite: {
    plugins: [tailwindcss()],
  },
});
```

The module handles session management, cookie encryption, OAuth flows, and composable auto-imports. The comparable Next.js setup would include the auth configuration, route handler, provider, and session provider component.

Next, register a GitHub OAuth app. Go to GitHub Settings > Developer settings > OAuth Apps > New OAuth App:

- **Application name:** Hot Springs Finder (Dev)
- **Homepage URL:** `http://localhost:3000`
- **Authorization callback URL:** `http://localhost:3000/auth/github`

GitHub gives you a Client ID and lets you generate a Client Secret. Put them in a `.env` file:

```bash title=".env"
NUXT_OAUTH_GITHUB_CLIENT_ID=your_client_id_here
NUXT_OAUTH_GITHUB_CLIENT_SECRET=your_client_secret_here
NUXT_SESSION_PASSWORD=a-random-string-at-least-32-characters-long
```

`nuxt-auth-utils` reads the `NUXT_OAUTH_*` variables by convention, so this provider does not need a separate config object.

Now the OAuth handler. This is the route GitHub redirects to after the user authorizes your app:

```typescript title="server/routes/auth/github.get.ts"
export default defineOAuthGitHubEventHandler({
  async onSuccess(event, { user }) {
    await setUserSession(event, {
      user: {
        login: user.login,
        avatar_url: user.avatar_url,
        id: user.id,
      },
    });
    return sendRedirect(event, "/springs");
  },
  onError(event, error) {
    console.error("GitHub OAuth error:", error);
    return sendRedirect(event, "/login?error=auth");
  },
});
```

`defineOAuthGitHubEventHandler` redirects to GitHub, exchanges the callback code for a token, and fetches the user profile. Your handler decides what to store from that result.

`setUserSession` stores the `user` value in an encrypted, HTTP-only cookie. This project uses the cookie as the session and does not need a database-backed session store.

Notice this file lives in `server/routes/auth/`, not `server/api/auth/`. The difference: `server/api/` routes are prefixed with `/api/`. `server/routes/` routes map directly to URLs. Our callback URL is `/auth/github`, not `/api/auth/github`.

\*\*Warning: Restart after .env changes\*\*

Nuxt reads `.env` at startup. If you add or change environment variables, restart the dev server. Hot reload doesn't pick up `.env` changes.

\*\*Note: Generate a session password\*\*

Need a random 32-character string? Run `openssl rand -base64 32` in your terminal. Or type whatever you want, as long as it's long enough. The password never leaves the server.

## Try It

Restart the dev server (to pick up the new module and `.env` changes):

```bash
pnpm dev
```

Visit `http://localhost:3000/auth/github`. You should be redirected to GitHub's authorization page. Authorize the app, and GitHub redirects you back to `/auth/github`, which runs your handler, sets the session, and redirects to `/springs`.

Open your browser's dev tools, go to the Application/Storage tab, and look for a cookie called `nuxt-session`. It should be there, HTTP-only, and encrypted.

If you see an error page instead, check:

- Are the Client ID and Secret correct in `.env`?
- Did you restart the dev server after creating `.env`?
- Is the callback URL in your GitHub OAuth app settings exactly `http://localhost:3000/auth/github`?

## Commit

```bash
git add -A && git commit -m "feat(auth): add nuxt-auth-utils with GitHub OAuth handler"
```

## Done-When

- [ ] `nuxt-auth-utils` is in the `modules` array in `nuxt.config.ts`
- [ ] `.env` contains the three required environment variables
- [ ] Visiting `/auth/github` redirects to GitHub and back
- [ ] After authorization, a `nuxt-session` cookie exists in the browser
- [ ] You can explain the difference between `server/routes/` and `server/api/`

## Solution

```typescript title="nuxt.config.ts"
import tailwindcss from "@tailwindcss/vite";

export default defineNuxtConfig({
  compatibilityDate: "2025-05-01",

  modules: ["nuxt-auth-utils"],

  css: ["~/assets/css/main.css"],

  vite: {
    plugins: [tailwindcss()],
  },
});
```

```bash title=".env"
NUXT_OAUTH_GITHUB_CLIENT_ID=your_client_id_here
NUXT_OAUTH_GITHUB_CLIENT_SECRET=your_client_secret_here
NUXT_SESSION_PASSWORD=a-random-string-at-least-32-characters-long
```

```typescript title="server/routes/auth/github.get.ts"
export default defineOAuthGitHubEventHandler({
  async onSuccess(event, { user }) {
    await setUserSession(event, {
      user: {
        login: user.login,
        avatar_url: user.avatar_url,
        id: user.id,
      },
    });
    return sendRedirect(event, "/springs");
  },
  onError(event, error) {
    console.error("GitHub OAuth error:", error);
    return sendRedirect(event, "/login?error=auth");
  },
});
```


---

[Full course index](/academy/llms.txt) · [Sitemap](/academy/sitemap.md)
