qruiq-google-auth
Automates Google OAuth integration, database setup with Prisma, and middleware protection for Next.js applications.
Install
mkdir -p .claude/skills/qruiq-google-auth && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/13164" && unzip -o skill.zip -d .claude/skills/qruiq-google-auth && rm skill.zipInstalls to .claude/skills/qruiq-google-auth
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Add Google OAuth login to a Next.js app using NextAuth.js v4 + PrismaAdapter + JWT sessions. Use when asked to "add Google login", "add auth", "add authentication", or "setup NextAuth".Key capabilities
- →Install NextAuth.js and Prisma dependencies
- →Copy template API routes and middleware
- →Initialize Prisma and add NextAuth tables
- →Generate NEXTAUTH_SECRET and configure environment variables
- →Integrate SessionProvider into the Next.js app
- →Protect routes using Next.js middleware
How it works
The skill installs required packages, copies authentication and middleware files, initializes Prisma with NextAuth tables, and sets up environment variables for Google OAuth and JWT sessions.
Inputs & outputs
When to use qruiq-google-auth
- →Add Google authentication to Next.js
- →Setup NextAuth with Prisma
- →Protect routes with middleware
About this skill
qruiq-google-auth
NextAuth.js v4 + PrismaAdapter + Google OAuth + JWT Session + route protection middleware.
Parameters
Collect before execution:
| Parameter | Required | Description | Example |
|---|---|---|---|
GOOGLE_CLIENT_ID | Yes | Google OAuth Client ID | xxx.apps.googleusercontent.com |
GOOGLE_CLIENT_SECRET | Yes | Google OAuth Client Secret | GOCSPX-xxx |
DATABASE_URL | Yes | Prisma database connection string | mysql://user:pass@host:3306/db |
NEXTAUTH_URL | Yes | App external URL (with scheme) | https://my-app.qruiq.app |
NEXTAUTH_SECRETis auto-generated during setup.
Steps
Execute all steps directly. Do not list as TODOs.
1. Install dependencies
yarn add next-auth @auth/prisma-adapter @prisma/client
yarn add -D prisma
2. Copy template files
cp -r ~/.qruiq/skills/skills/qruiq-google-auth/template/app/api/auth app/api/
cp -r ~/.qruiq/skills/skills/qruiq-google-auth/template/app/api/health app/api/
cp ~/.qruiq/skills/skills/qruiq-google-auth/template/middleware.ts .
3. Initialize Prisma
npx prisma init
Edit prisma/schema.prisma — add the four NextAuth tables (Account, Session, User, VerificationToken). See "Prisma Schema" section below.
npx prisma db push
4. Create .env
NEXTAUTH_SECRET=<run: openssl rand -base64 32>
NEXTAUTH_URL=<NEXTAUTH_URL>
GOOGLE_CLIENT_ID=<GOOGLE_CLIENT_ID>
GOOGLE_CLIENT_SECRET=<GOOGLE_CLIENT_SECRET>
DATABASE_URL=<DATABASE_URL>
5. Add SessionProvider to app/providers.tsx
import { SessionProvider } from "next-auth/react";
export function Providers({ children, themeProps, session }) {
const router = useRouter();
return (
<SessionProvider session={session}>
<HeroUIProvider navigate={router.push}>
<NextThemesProvider {...themeProps}>{children}</NextThemesProvider>
</HeroUIProvider>
</SessionProvider>
);
}
Core files
app/api/auth/[...nextauth]/lib/options.ts
import { PrismaAdapter } from '@auth/prisma-adapter';
import type { NextAuthOptions } from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';
import prisma from '@/lib/prisma';
export const authOptions: NextAuthOptions = {
secret: process.env.NEXTAUTH_SECRET,
adapter: PrismaAdapter(prisma),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID ?? '',
clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? '',
authorization: {
params: {
prompt: 'consent',
access_type: 'offline',
response_type: 'code',
redirect_uri: `${process.env.NEXTAUTH_URL}/api/auth/callback/google`,
},
},
checks: ['state', 'pkce'],
profile(profile) {
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: profile.picture,
emailVerified: profile.email_verified,
};
},
}),
],
pages: { signIn: '/', error: '/' },
session: { strategy: 'jwt', maxAge: 30 * 24 * 60 * 60 },
callbacks: {
async jwt({ token, user, account }) {
if (user) token.sub = user.id;
if (account) token.provider = account.provider;
return token;
},
async session({ session, token }) {
if (session.user) session.user.id = token.sub as string;
return session;
},
async redirect({ url, baseUrl }) {
if (url.startsWith('/')) return new URL(url, baseUrl).toString();
if (url.startsWith(baseUrl)) return url;
return baseUrl;
},
},
};
middleware.ts — Route protection
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { getToken } from 'next-auth/jwt';
const PUBLIC_PATHS = ['/', '/api/auth'];
export async function middleware(request: NextRequest) {
const path = request.nextUrl.pathname;
if (path.startsWith('/api/auth/callback/')) return NextResponse.next();
const isPublic = PUBLIC_PATHS.some(p => path === p || path.startsWith(p + '/'));
if (isPublic || path.startsWith('/api/')) return NextResponse.next();
const token = await getToken({ req: request, secret: process.env.NEXTAUTH_SECRET });
if (token) return NextResponse.next();
const callbackUrl = encodeURIComponent(request.url);
return NextResponse.redirect(new URL(`/?callbackUrl=${callbackUrl}`, request.url));
}
export const config = {
matcher: ['/dashboard/:path*', '/profile/:path*'],
};
Prisma Schema
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
Google Cloud Console setup
- Go to Google Cloud Console → APIs & Services → Credentials
- Create OAuth 2.0 Client ID (Web application)
- Authorized JavaScript origins:
http://localhost:3000+https://your-domain.com - Authorized redirect URIs:
http://localhost:3000/api/auth/callback/google+https://your-domain.com/api/auth/callback/google
Notes
NEXTAUTH_URLmust be injected via K8s Secret when deploying — must match external domain exactly- Google Console callback URL must exactly match
NEXTAUTH_URL, otherwiseredirect_uri_mismatch checks: ['state', 'pkce']is a security best practice — do not remove- Multiple domains (dev/prod) each need separate entries in Google Console
When not to use it
- →When not using Next.js for the application
- →When not using Prisma for the database adapter
- →When not using Google as the OAuth provider
Limitations
- →Requires a Next.js application
- →Requires Prisma as the database adapter
- →Limited to Google as the OAuth provider
How it compares
This skill automates the setup of Google OAuth with NextAuth.js and Prisma, including file copying, dependency installation, and environment configuration, which would otherwise require manual configuration of multiple components.
Compared to similar skills
qruiq-google-auth side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| qruiq-google-auth (this skill) | 0 | 4mo | Review | Intermediate |
| drizzle-orm | 32 | 2mo | No flags | Intermediate |
| event-store-design | 5 | 2mo | No flags | Advanced |
| springboot-patterns | 11 | 5mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
drizzle-orm
EpicenterHQ
Drizzle ORM patterns for type branding and custom types. Use when working with Drizzle column definitions, branded types, or custom type conversions.
event-store-design
wshobson
Design and implement event stores for event-sourced systems. Use when building event sourcing infrastructure, choosing event store technologies, or implementing event persistence patterns.
springboot-patterns
affaan-m
Spring Boot 架构模式、REST API 设计、分层服务、数据访问、缓存、异步处理和日志记录。适用于 Java Spring Boot 后端工作。
dotnet-architect
sickn33
Expert .NET backend architect specializing in C#, ASP.NET Core, Entity Framework, Dapper, and enterprise application patterns. Masters async/await, dependency injection, caching strategies, and performance optimization. Use PROACTIVELY for .NET API development, code review, or architecture decisions.
backend-development
skillcreatorai
Backend API design, database architecture, microservices patterns, and test-driven development. Use for designing APIs, database schemas, or backend system architecture.
postgresql
sickn33
Design a PostgreSQL-specific schema. Covers best-practices, data types, indexing, constraints, performance patterns, and advanced features