I am building a simple application based on Nuxt (3.16) and @sidebase/nuxt-auth
and I've been trying for now two days to get through that. I am a beginner in Nuxt but I have been developing for a long time for fun (and to learn).
I tried to use ChatGPT to give me some insights but we've been running in loops for some time. You can see one of the sessions at (this is just for reference).
My problem: when accessing the http://localhost:3000/api/auth/signin
endpoint, I get a gray screen with a white rounded square in the middle. There are no errors neither in Nuxt log, nor in the console log.
This is my nuxt.config.ts
file:
import Aura from '@primeuix/themes/aura';
import { PrismaClient } from '@prisma/client'
import { PrismaAdapter } from '@next-auth/prisma-adapter'
const prisma = new PrismaClient()
export default defineNuxtConfig({
modules: [
'@nuxtjs/tailwindcss',
'@primevue/nuxt-module',
'@sidebase/nuxt-auth',
],
auth: {
isEnabled: true,
debug: true,
origin: 'http://localhost:3000',
baseURL: 'http://localhost:3000/api/auth',
basePath: '/api/auth',
enableSession: true,
session: {
strategy: 'database', // <-- persist sessions in SQLite
maxAge: 30 * 24 * 60 * 60, // 30 days session validity
},
adapter: PrismaAdapter(prisma), // <-- connect Nuxt Auth to SQLite DB
providers: [
{
provider: 'google',
options: {
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}
}
],
callbacks: {
async session({ session, user }) {
session.user.id = user.id // attach user id (optional)
return session
}
}
},
primevue: {
options: {
theme: {
preset: Aura
}
}
},
css: [
'@/assets/css/main.css',
'@/assets/css/fonts.css',
],
buildModules: ['@nuxtjs/tailwindcss'],
compatibilityDate: '2025-03-16'
})
The server/api/auth/[...].ts
file is:
import { NuxtAuthHandler } from '#auth'
export default NuxtAuthHandler({
secret: process.env.AUTH_SECRET, // Use a secret for JWT or session cookie
providers: [
{
provider: 'google',
options: {
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
},
},
// Add other providers as needed
],
callbacks: {
async session(session, user) {
console.log('Session callback:', session, user)
return session
},
async signIn(user, account, profile) {
console.log('SignIn callback:', user, account, profile)
return true
},
},
})
I have defined the Google oAuth secrets in .env
.
The authentication flow is not even triggered, in the Network console I see only a call to signin
but no attempts to go to Google are made.
For reference, package.json
{
"name": "nuxt-app",
"private": true,
"type": "module",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"@next-auth/prisma-adapter": "^1.0.7",
"@primeuix/themes": "^1.0.0",
"@primevue/forms": "^4.3.2",
"@prisma/client": "^6.5.0",
"@sidebase/nuxt-auth": "^0.10.1",
"nuxt": "^3.16.0",
"primevue": "^4.3.2",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
},
"devDependencies": {
"@nuxtjs/tailwindcss": "^6.13.2",
"@primevue/nuxt-module": "^4.3.2",
"autoprefixer": "^10.4.21",
"postcss": "^8.5.3",
"prisma": "^6.5.0",
"tailwindcss": "^3.4.17"
}
}
Also for reference - the gray page above. To me there are no embedded actions at all:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
:root {
--border-width: 1px;
--border-radius: 0.5rem;
--color-error: #c94b4b;
--color-info: #157efb;
--color-info-text: #fff;
}
.__next-auth-theme-auto,
.__next-auth-theme-light {
--color-background: #ececec;
--color-background-card: #fff;
--color-text: #000;
--color-primary: #444;
--color-control-border: #bbb;
--color-button-active-background: #f9f9f9;
--color-button-active-border: #aaa;
--color-seperator: #ccc;
}
.__next-auth-theme-dark {
--color-background: #161b22;
--color-background-card: #0d1117;
--color-text: #fff;
--color-primary: #ccc;
--color-control-border: #555;
--color-button-active-background: #060606;
--color-button-active-border: #666;
--color-seperator: #444;
}
@media (prefers-color-scheme: dark) {
.__next-auth-theme-auto {
--color-background: #161b22;
--color-background-card: #0d1117;
--color-text: #fff;
--color-primary: #ccc;
--color-control-border: #555;
--color-button-active-background: #060606;
--color-button-active-border: #666;
--color-seperator: #444;
}
}
body {
background-color: var(--color-background);
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif,
Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
margin: 0;
padding: 0;
}
h1 {
font-weight: 400;
margin-bottom: 1.5rem;
padding: 0 1rem;
}
h1,
p {
color: var(--color-text);
}
form {
margin: 0;
padding: 0;
}
label {
font-weight: 500;
margin-bottom: 0.25rem;
text-align: left;
}
input[type],
label {
color: var(--color-text);
display: block;
}
input[type] {
background: var(--color-background-card);
border: var(--border-width) solid var(--color-control-border);
border-radius: var(--border-radius);
box-sizing: border-box;
font-size: 1rem;
padding: 0.5rem 1rem;
width: 100%;
}
input[type]:focus {
box-shadow: none;
}
p {
font-size: 1.1rem;
line-height: 2rem;
margin: 0 0 1.5rem;
padding: 0 1rem;
}
a.button {
line-height: 1rem;
text-decoration: none;
}
a.button:link,
a.button:visited {
background-color: var(--color-background);
color: var(--color-primary);
}
button span {
flex-grow: 1;
}
a.button,
button {
align-items: center;
background-color: var(--provider-bg, var(--color-background-card));
border-color: rgba(0, 0, 0, 0.1);
border-radius: var(--border-radius);
color: var(--provider-color, var(--color-primary));
display: flex;
font-size: 1.1rem;
font-weight: 500;
justify-content: center;
margin: 0 0 0.75rem;
min-height: 62px;
padding: 0.75rem 1rem;
position: relative;
transition: all 0.1s ease-in-out;
}
@media (max-width: 450px) {
a.button,
button {
font-size: 0.9rem;
}
}
a.button:active,
a.button:hover,
button:active,
button:hover {
cursor: pointer;
}
a.button #provider-logo,
button #provider-logo {
display: block;
width: 25px;
}
a.button #provider-logo-dark,
button #provider-logo-dark {
display: none;
}
#submitButton {
background-color: var(--brand-color, var(--color-info));
color: var(--button-text-color, var(--color-info-text));
width: 100%;
}
@media (prefers-color-scheme: dark) {
a.button,
button {
background-color: var(--provider-dark-bg, var(--color-background));
color: var(--provider-dark-color, var(--color-primary));
}
#provider-logo {
display: none !important;
}
#provider-logo-dark {
display: block !important;
width: 25px;
}
}
a.site {
color: var(--color-primary);
font-size: 1rem;
line-height: 2rem;
text-decoration: none;
}
a.site:hover {
text-decoration: underline;
}
.page {
display: grid;
height: 100%;
margin: 0;
padding: 0;
place-items: center;
position: absolute;
width: 100%;
}
.page > div {
text-align: center;
}
.error a.button {
display: inline-block;
margin-top: 0.5rem;
padding-left: 2rem;
padding-right: 2rem;
}
.error .message {
margin-bottom: 1.5rem;
}
.signin input[type="text"] {
display: block;
margin-left: auto;
margin-right: auto;
}
.signin hr {
border: 0;
border-top: 1px solid var(--color-seperator);
display: block;
margin: 2rem auto 1rem;
overflow: visible;
}
.signin hr:before {
background: var(--color-background-card);
color: #888;
content: "or";
padding: 0 0.4rem;
position: relative;
top: -0.7rem;
}
.signin .error {
background: #f5f5f5;
background: var(--color-error);
border-radius: 0.3rem;
font-weight: 500;
}
.signin .error p {
color: var(--color-info-text);
font-size: 0.9rem;
line-height: 1.2rem;
padding: 0.5rem 1rem;
text-align: left;
}
.signin form,
.signin > div {
display: block;
}
.signin form input[type],
.signin > div input[type] {
margin-bottom: 0.5rem;
}
.signin form button,
.signin > div button {
width: 100%;
}
.signin form,
.signin > div {
max-width: 300px;
}
.logo {
display: inline-block;
margin-bottom: 25px;
margin-top: 20px;
max-height: 70px;
max-width: 150px;
}
@media screen and (min-width: 450px) {
.card {
width: 350px;
}
}
@media screen and (max-width: 450px) {
.card {
width: 200px;
}
}
.card {
background-color: var(--color-background-card);
border-radius: 30px;
margin: 20px 0;
padding: 20px 50px;
}
.card .header {
color: var(--color-primary);
}
.section-header {
color: var(--color-text);
}
</style>
<title>Sign In</title>
</head>
<body class="__next-auth-theme-auto">
<div class="page">
<div class="signin"><div class="card"></div></div>
</div>
</body>
</html>