Master Lucia Auth V3 session management for Google Antigravity IDE applications
# Lucia Auth V3 Patterns for Google Antigravity IDE
Implement secure, lightweight authentication with Lucia Auth V3 using Google Antigravity IDE. This comprehensive guide covers session management, OAuth integration, password authentication, and security best practices.
## Core Setup
```typescript
// src/lib/auth.ts
import { Lucia, TimeSpan } from "lucia";
import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle";
import { db } from "./db";
import { users, sessions } from "./db/schema";
const adapter = new DrizzlePostgreSQLAdapter(db, sessions, users);
export const lucia = new Lucia(adapter, {
sessionExpiresIn: new TimeSpan(30, "d"), // 30 days
sessionCookie: {
name: "session",
expires: false, // Session cookie
attributes: {
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
},
},
getUserAttributes: (attributes) => ({
email: attributes.email,
name: attributes.name,
role: attributes.role,
emailVerified: attributes.emailVerified,
avatarUrl: attributes.avatarUrl,
}),
});
// Type declarations
declare module "lucia" {
interface Register {
Lucia: typeof lucia;
DatabaseUserAttributes: {
email: string;
name: string;
role: "admin" | "user" | "guest";
emailVerified: boolean;
avatarUrl: string | null;
};
}
}
```
## Password Authentication
```typescript
// src/lib/auth/password.ts
import { Argon2id } from "oslo/password";
import { generateIdFromEntropySize } from "lucia";
import { lucia } from "../auth";
import { db } from "../db";
import { users } from "../db/schema";
import { eq } from "drizzle-orm";
const argon2id = new Argon2id();
export async function signup(
email: string,
password: string,
name: string
): Promise<{ user: User; session: Session }> {
// Validate password strength
if (password.length < 8) {
throw new Error("Password must be at least 8 characters");
}
// Check if user exists
const existing = await db.query.users.findFirst({
where: eq(users.email, email.toLowerCase()),
});
if (existing) {
throw new Error("Email already registered");
}
// Hash password and create user
const passwordHash = await argon2id.hash(password);
const userId = generateIdFromEntropySize(10);
const [user] = await db.insert(users).values({
id: userId,
email: email.toLowerCase(),
name,
passwordHash,
role: "user",
emailVerified: false,
}).returning();
// Create session
const session = await lucia.createSession(userId, {});
return { user, session };
}
export async function login(
email: string,
password: string
): Promise<{ user: User; session: Session }> {
const user = await db.query.users.findFirst({
where: eq(users.email, email.toLowerCase()),
});
if (!user || !user.passwordHash) {
throw new Error("Invalid credentials");
}
const validPassword = await argon2id.verify(user.passwordHash, password);
if (!validPassword) {
throw new Error("Invalid credentials");
}
const session = await lucia.createSession(user.id, {});
return { user, session };
}
```
## OAuth Integration
```typescript
// src/lib/auth/oauth/github.ts
import { GitHub, generateState } from "arctic";
import { lucia } from "../../auth";
import { db } from "../../db";
import { users, oauthAccounts } from "../../db/schema";
export const github = new GitHub(
process.env.GITHUB_CLIENT_ID!,
process.env.GITHUB_CLIENT_SECRET!
);
export async function createGitHubAuthUrl(): Promise<{
url: URL;
state: string;
}> {
const state = generateState();
const url = await github.createAuthorizationURL(state, {
scopes: ["user:email"],
});
return { url, state };
}
export async function handleGitHubCallback(
code: string
): Promise<{ user: User; session: Session }> {
const tokens = await github.validateAuthorizationCode(code);
// Fetch GitHub user
const githubUserResponse = await fetch("https://api.github.com/user", {
headers: { Authorization: `Bearer ${tokens.accessToken}` },
});
const githubUser = await githubUserResponse.json();
// Check for existing OAuth account
const existingAccount = await db.query.oauthAccounts.findFirst({
where: and(
eq(oauthAccounts.provider, "github"),
eq(oauthAccounts.providerUserId, String(githubUser.id))
),
with: { user: true },
});
if (existingAccount) {
const session = await lucia.createSession(existingAccount.userId, {});
return { user: existingAccount.user, session };
}
// Create new user
const userId = generateIdFromEntropySize(10);
await db.transaction(async (tx) => {
await tx.insert(users).values({
id: userId,
email: githubUser.email,
name: githubUser.name ?? githubUser.login,
avatarUrl: githubUser.avatar_url,
emailVerified: true,
});
await tx.insert(oauthAccounts).values({
provider: "github",
providerUserId: String(githubUser.id),
userId,
});
});
const user = await db.query.users.findFirst({
where: eq(users.id, userId),
});
const session = await lucia.createSession(userId, {});
return { user: user!, session };
}
```
## Best Practices for Google Antigravity IDE
When implementing Lucia Auth with Google Antigravity, use Argon2id for password hashing. Implement CSRF protection for form submissions. Use secure session cookies with proper attributes. Add rate limiting to authentication endpoints. Implement email verification for new accounts. Let Gemini 3 generate OAuth provider integrations from your configuration.
Google Antigravity's agent mode can scaffold complete authentication flows with proper security measures.This Lucia Auth prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their lucia auth implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For Lucia Auth projects, consider mentioning your framework version, coding style, and any specific libraries you're using.