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
- Install
nuxt-auth-utilsand add it tonuxt.config.ts - Register a GitHub OAuth app and set environment variables
- Create the GitHub OAuth handler in
server/routes/auth/github.get.ts
Hands-on exercise 3.1
Wire up GitHub OAuth from scratch.
Requirements:
- Install
nuxt-auth-utilsand add it to themodulesarray innuxt.config.ts - Register a new OAuth app on GitHub with the callback URL
http://localhost:3000/auth/github - Create a
.envfile withNUXT_OAUTH_GITHUB_CLIENT_ID,NUXT_OAUTH_GITHUB_CLIENT_SECRET, andNUXT_SESSION_PASSWORD - Create
server/routes/auth/github.get.tsthat handles the OAuth callback - On success, store the user's login, avatar URL, and ID in the session
Implementation hints:
nuxt-auth-utilsauto-importsdefineOAuthGitHubEventHandler,setUserSession,getUserSession, andrequireUserSessionin server routes- It also auto-imports
useUserSessionin Vue components - The module reads
NUXT_OAUTH_GITHUB_CLIENT_IDandNUXT_OAUTH_GITHUB_CLIENT_SECRETautomatically. No config mapping needed NUXT_SESSION_PASSWORDmust be at least 32 characters. It encrypts the session cookie- Server routes in
server/routes/(notserver/api/) map directly to URLs.server/routes/auth/github.get.tsbecomes/auth/github
First, update the Nuxt config to include the module:
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:
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-longnuxt-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:
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.
Try It
Restart the dev server (to pick up the new module and .env changes):
pnpm devVisit 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
git add -A && git commit -m "feat(auth): add nuxt-auth-utils with GitHub OAuth handler"Done-When
nuxt-auth-utilsis in themodulesarray innuxt.config.ts.envcontains the three required environment variables- Visiting
/auth/githubredirects to GitHub and back - After authorization, a
nuxt-sessioncookie exists in the browser - You can explain the difference between
server/routes/andserver/api/
Solution
import tailwindcss from "@tailwindcss/vite";
export default defineNuxtConfig({
compatibilityDate: "2025-05-01",
modules: ["nuxt-auth-utils"],
css: ["~/assets/css/main.css"],
vite: {
plugins: [tailwindcss()],
},
});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-longexport 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");
},
});Was this helpful?