Installation
Follow these steps to install Auth in your project. The installation process may vary slightly depending on your framework and database choice.
Getting Started
CLI
- Install Auth Package
npx shadcn@latest add https://yuki-ui.vercel.app/r/auth.json
npx shadcn@latest add https://yuki-ui.vercel.app/r/auth.json
pnpm dlx shadcn@latest add https://yuki-ui.vercel.app/r/auth.json
bunx --bun shadcn@latest add https://yuki-ui.vercel.app/r/auth.json
By default, Auth uses Scrypt
for hashing passwords. You can change the hashing algorithm by passing a different hashing function to the hash
and verify
methods in the server/auth/core/password.ts
.
- Add Adapter (Optional)
Frist, create your database schema to store authentication data.
Install necessary packages.
npm install -d drizzle-kit
pnpm add -d drizzle-kit
yarn add -d drizzle-kit
bun add -d drizzle-kit
npm install drizzle-orm
pnpm add drizzle-orm
yarn add drizzle-orm
bun add drizzle-orm
Create a new table in your database.
import { relations } from 'drizzle-orm'
import { pgTable, primaryKey } from 'drizzle-orm/pg-core'
export const users = pgTable('user', (t) => ({
id: t.uuid().primaryKey().defaultRandom().notNull(),
name: t.varchar({ length: 255 }).notNull(),
email: t.varchar({ length: 255 }).unique().notNull(),
image: t.varchar({ length: 255 }).notNull(),
createdAt: t.timestamp().defaultNow().notNull(),
updatedAt: t
.timestamp({ mode: 'date', withTimezone: true })
.defaultNow()
.$onUpdateFn(() => new Date())
.notNull(),
}))
export const usersRelations = relations(users, ({ many }) => ({
accounts: many(accounts),
sessions: many(sessions),
}))
export const accounts = pgTable(
'account',
(t) => ({
provider: t.varchar({ length: 255 }).notNull(),
accountId: t.varchar({ length: 255 }).notNull(),
userId: t
.uuid()
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),
password: t.varchar({ length: 255 }),
}),
(account) => [primaryKey({ columns: [account.provider, account.accountId] })],
)
export const accountsRelations = relations(accounts, ({ one }) => ({
user: one(users, { fields: [accounts.userId], references: [users.id] }),
}))
export const sessions = pgTable('session', (t) => ({
token: t.varchar({ length: 255 }).primaryKey().notNull(),
expires: t.timestamp({ mode: 'date', withTimezone: true }).notNull(),
userId: t
.uuid()
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),
}))
export const sessionRelations = relations(sessions, ({ one }) => ({
user: one(users, { fields: [sessions.userId], references: [users.id] }),
}))
Export your database instance.
import { drizzle } from 'drizzle-orm/node-postgres'
import * as schema from '@/server/db/schema'
const createDrizzleClient = () =>
drizzle(process.env.DATABASE_URL, {
schema,
casing: 'snake_case',
})
const globalForDrizzle = globalThis as unknown as {
db: ReturnType<typeof createDrizzleClient> | undefined
}
export const db = globalForDrizzle.db ?? createDrizzleClient()
if (process.env.NODE_ENV !== 'production') globalForDrizzle.db = db
Install necessary packages.
npm install -d prisma
pnpm add -d prisma
yarn add -d prisma
bun add -d prisma
npm install @prisma/client
pnpm add @prisma/client
yarn add @prisma/client
bun add @prisma/client
Create a new table in your database.
generator client {
provider = "prisma-client"
output = "../generated/prisma"
moduleFormat = "esm"
importFileExtension = ""
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
name String @db.VarChar(255)
email String @unique(map: "user_email_unique") @db.VarChar(255)
image String @db.VarChar(255)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
accounts Account[]
sessions Session[]
@@map("user")
}
model Account {
provider String @db.VarChar(255)
accountId String @map("account_id") @db.VarChar(255)
password String? @db.VarChar(255)
userId String @map("user_id") @db.Uuid
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "account_user_id_user_id_fk")
@@id([provider, accountId], map: "account_provider_account_id_pk")
@@map("account")
}
model Session {
token String @id @db.VarChar(255)
expires DateTime @db.Timestamptz(6)
userId String @map("user_id") @db.Uuid
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "session_user_id_user_id_fk")
@@map("session")
}
Export your database instance.
import { PrismaClient } from '@/generated/prisma'
const createPrismaClient = () => new PrismaClient()
const globalForPrisma = globalThis as unknown as {
db: ReturnType<typeof createPrismaClient> | undefined
}
export const db = globalForPrisma.db ?? createPrismaClient()
if (process.env.NODE_ENV !== 'production') globalForPrisma.db = db
Install necessary packages.
npm install mongoose
pnpm add mongoose
yarn add mongoose
bun add mongoose
Create a new table in your database.
import type { Document, Model } from 'mongoose'
import { model, models, Schema, Types } from 'mongoose'
export interface User extends Document {
name: string
email: string
image: string
createdAt: Date
updatedAt: Date
}
const userSchema = new Schema(
{
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
image: { type: String, required: true },
},
{ timestamps: { createdAt: true, updatedAt: true } },
)
export const user: Model<User> = models.user ?? model<User>('user', userSchema)
export interface Account extends Document {
provider: string
accountId: string
password?: string
userId: string
}
const accountSchema = new Schema(
{
provider: { type: String, required: true },
accountId: { type: String, required: true },
password: { type: String, required: false },
userId: { type: Types.ObjectId, required: true, ref: 'user' },
},
{ timestamps: false },
)
accountSchema.index({ provider: 1, accountId: 1 }, { unique: true })
export const account: Model<Account> =
models.account ?? model<Account>('account', accountSchema)
export interface Session extends Document {
token: string
expires: Date
userId: string
}
const sessionSchema = new Schema(
{
token: { type: String, required: true, unique: true },
expires: { type: Date, required: true },
userId: { type: Types.ObjectId, required: true, ref: 'user' },
},
{ timestamps: false },
)
export const session: Model<Session> =
models.session ?? model<Session>('session', sessionSchema)
Export your database instance.
import mongoose from 'mongoose'
import * as schema from '@/server/db/schema'
const createMongooseClient = () => {
void mongoose.connect(process.env.DATABASE_URL ?? '')
return schema
}
const globalForMongoose = globalThis as unknown as {
db: ReturnType<typeof createMongooseClient> | undefined
}
export const db = globalForMongoose.db ?? createMongooseClient()
if (process.env.NODE_ENV !== 'production') globalForMongoose.db = db
Then, run this command to install adapter
npx shadcn@latest add https://yuki-ui.vercel.app/r/auth-with-{database}.json
npx shadcn@latest add https://yuki-ui.vercel.app/r/auth-with-{database}.json
pnpm dlx shadcn@latest add https://yuki-ui.vercel.app/r/auth-with-{database}.json
bunx --bun shadcn@latest add https://yuki-ui.vercel.app/r/auth-with-{database}.json
Replace {database}
with your database adapter. Currently supported databases:
- drizzle
- prisma
- mongodb
- memory
- Install OAuth providers.
These OAuth providers are implemented using Arctic, a collection of OAuth 2.0 clients for popular providers.
npx shadcn@latest add https://yuki-ui.vercel.app/r/oauth-{provider}.json
npx shadcn@latest add https://yuki-ui.vercel.app/r/oauth-{provider}.json
pnpm dlx shadcn@latest add https://yuki-ui.vercel.app/r/oauth-{provider}.json
bunx --bun shadcn@latest add https://yuki-ui.vercel.app/r/oauth-{provider}.json
Replace {provider}
with the OAuth provider you want to use. Currently supported providers:
- discord
- figma
- github
- microsoft (not recommended, it returns image blob instead of image url)
- notion
- spotify
Example:
npx shadcn@latest add https://yuki-ui.vercel.app/r/oauth-google.json
npx shadcn@latest add https://yuki-ui.vercel.app/r/oauth-google.json
pnpm dlx shadcn@latest add https://yuki-ui.vercel.app/r/oauth-google.json
bunx --bun shadcn@latest add https://yuki-ui.vercel.app/r/oauth-google.json
Remember to add environment variables for your OAuth providers. You can find the required environment variables in the documentation for each provider.
{PROVIDER}_CLIENT_ID=your-client-id
{PROVIDER}_CLIENT_SECRET=your-client-secret
Example for Google:
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
And set callback URLs in your OAuth provider settings: {base url}/api/auth/{provider}/callback
.
For example, if your base URL is https://example.com
, the callback URL for Google would be https://example.com/api/auth/google/callback
.
- Add OAuth providers to your Auth configuration.
import type { AuthOptions } from '@/server/auth/types'
import { GoogleProvider } from '@/server/auth/providers/google'
export const authOptions = {
google: new GoogleProvider(),
} satisfies AuthOptions
Manual Installation
You can find all the necessary code in our GitHub repository: https://github.com/tiesen243/yuki-ui/tree/main/registry/auth.