Next.js için hazır oturum açma sayfaları
Sekiz küçük dosya, Next.js uygulamasına, Aurabase e-postalarındaki bağlantıların işaret ettiği sayfalar da dahil olmak üzere eksiksiz bir oturum açma akışı sağlar.
8 dk. oku·Seviye orta düzey·25 Eki 2026 tarihinde revize edildi
Bu İngilizce metin, Fransızca orijinalinden otomatik olarak oluşturulmuştur ve henüz incelenmemiştir.
Bu çeviriden bu yana İngilizce kaynak değişti. Bazı bilgiler güncelliğini kaybetmiş olabilir.
Bu sayfa otomatik olarak çevrildi. İngilizce versiyonu yetkilidir.
#Kurulum
1. İstemciler ve proxy
Bu sayfalar, çerez oturumlarıyla Uygulama Yönlendiricisini kullanır (bkz. Next.js SSR). NEXT_PUBLIC_AURABASE_URL ve NEXT_PUBLIC_AURABASE_ANON_KEY ayarını yapın, ardından sunucu istemcisini ve proxy'yi ekleyin. Next.js 15'te dosyayı middleware.ts ve işlevi middleware olarak adlandırın.
lib/aurabase/server.tstypescript
import { cookies } from 'next/headers'
import { createServerClient } from '@aurabase/aurabase-js/ssr'
export async function serverClient() {
const store = await cookies()
return createServerClient(process.env.NEXT_PUBLIC_AURABASE_URL!, process.env.NEXT_PUBLIC_AURABASE_ANON_KEY!, {
cookies: {
getAll: () => store.getAll(),
// Sunucu Bileşenleri çerezleri yazamaz: bunun yerine aşağıdaki proxy oturumu yeniler.
setAll(list) {
try {
list.forEach(({ name, value, options }) => store.set(name, value, options))
} catch {}
},
},
})
}
proxy.tstypescript
import { NextResponse, type NextRequest } from 'next/server'
import { createServerClient } from '@aurabase/aurabase-js/ssr'
const PROTECTED = ['/dashboard']
export async function proxy(request: NextRequest) {
const response = NextResponse.next({ request })
const aura = createServerClient(process.env.NEXT_PUBLIC_AURABASE_URL!, process.env.NEXT_PUBLIC_AURABASE_ANON_KEY!, {
cookies: {
getAll: () => request.cookies.getAll(),
setAll(list) {
list.forEach(({ name, value, options }) => {
request.cookies.set(name, value)
response.cookies.set(name, value, options)
})
},
},
})
// getUser() belirteçleri yeniler VE sunucuya kullanıcının kim olduğunu sorar. Asla getSession() ile yetkilendirme yapmayın.
const { data: user } = await aura.auth.getUser()
if (!user && PROTECTED.some((p) => request.nextUrl.pathname.startsWith(p))) {
return NextResponse.redirect(new URL('/login', request.url))
}
return response
}
export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'] }
#Oturum aç
2. Oturum açın ve kaydolun
app/login/actions.tstypescript
'use server'
import { redirect } from 'next/navigation'
import { serverClient } from '@/lib/aurabase/server'
export async function login(formData: FormData) {
const aura = await serverClient()
const { data, error } = await aura.auth.signInWithPassword({
email: String(formData.get('email')),
password: String(formData.get('password')),
})
if (error) redirect(`/login?error=${encodeURIComponent(error.code ?? 'ERROR')}`)
// MFA etkinleştirilmiş bir kullanıcı, oturum yerine bir sorgulamayla karşılaşır: kodu buradan isteyin.
if (data && 'mfa_required' in data) redirect(`/login?error=MFA_REQUIRED`)
redirect('/dashboard')
}
export async function sendMagicLink(formData: FormData) {
const aura = await serverClient()
await aura.auth.signInWithMagicLink({ email: String(formData.get('email')) })
redirect('/login?sent=1')
}
app/login/page.tsxtsx
import Link from 'next/link'
import { login, sendMagicLink } from './actions'
export default async function LoginPage({ searchParams }: { searchParams: Promise<{ error?: string; sent?: string }> }) {
const { error, sent } = await searchParams
return (
<main>
<h1>Sign in</h1>
{error && <p role="alert">Sign-in failed: {error}</p>}
{sent && <p>If this address has an account, a sign-in link was sent.</p>}
<form action={login}>
<input name="email" type="email" placeholder="Email" required />
<input name="password" type="password" placeholder="Password" required />
<button type="submit">Sign in</button>
</form>
<form action={sendMagicLink}>
<input name="email" type="email" placeholder="Email" required />
<button type="submit">Email me a sign-in link</button>
</form>
<p>
<Link href="/signup">Create an account</Link> · <Link href="/forgot-password">Forgot your password?</Link>
</p>
</main>
)
}
app/signup/actions.tstypescript
'use server'
import { redirect } from 'next/navigation'
import { serverClient } from '@/lib/aurabase/server'
export async function signup(formData: FormData) {
const aura = await serverClient()
const { data, error } = await aura.auth.signUp({
email: String(formData.get('email')),
password: String(formData.get('password')),
})
if (error) redirect(`/signup?error=${encodeURIComponent(error.message)}`)
// Proje e-posta onayı gerektirdiğinde henüz oturum yoktur: `data.session` boştur.
redirect(data?.session ? '/dashboard' : '/signup?check=1')
}
app/signup/page.tsxtsx
import Link from 'next/link'
import { signup } from './actions'
export default async function SignupPage({ searchParams }: { searchParams: Promise<{ error?: string; check?: string }> }) {
const { error, check } = await searchParams
return (
<main>
<h1>Create an account</h1>
{error && <p role="alert">{error}</p>}
{check && <p>Check your inbox: confirm your email address to finish.</p>}
<form action={signup}>
<input name="email" type="email" placeholder="Email" required />
<input name="password" type="password" placeholder="Password" required minLength={8} />
<button type="submit">Sign up</button>
</form>
<p>
<Link href="/login">Already have an account?</Link>
</p>
</main>
)
}
#Sıfırla
3. Şifre sıfırlama
Sıfırlama e-postası <Site URL>/reset-password?token=… adresine bağlanır. Studio › Kimlik Doğrulama › Yapılandırma bölümünde Site URL'sini ayarlayın.
app/forgot-password/actions.tstypescript
'use server'
import { redirect } from 'next/navigation'
import { serverClient } from '@/lib/aurabase/server'
export async function requestReset(formData: FormData) {
const aura = await serverClient()
await aura.auth.resetPasswordForEmail(String(formData.get('email')))
// Adresin bir hesabı olup olmadığına bakılmaksızın aynı cevap (hesap numaralandırması yok).
redirect('/forgot-password?sent=1')
}
app/forgot-password/page.tsxtsx
import { requestReset } from './actions'
export default async function ForgotPasswordPage({ searchParams }: { searchParams: Promise<{ sent?: string }> }) {
const { sent } = await searchParams
return (
<main>
<h1>Reset your password</h1>
{sent && <p>If this address has an account, a reset link was sent.</p>}
<form action={requestReset}>
<input name="email" type="email" placeholder="Email" required />
<button type="submit">Send the link</button>
</form>
</main>
)
}
app/reset-password/actions.tstypescript
'use server'
import { redirect } from 'next/navigation'
import { serverClient } from '@/lib/aurabase/server'
export async function resetPassword(formData: FormData) {
const token = String(formData.get('token'))
const aura = await serverClient()
const { error } = await aura.auth.resetPassword(token, String(formData.get('password')))
if (error) redirect(`/reset-password?token=${encodeURIComponent(token)}&error=${encodeURIComponent(error.message)}`)
// Sıfırlama, kullanıcının yeni bir oturumla oturum açmasını sağlar; eski oturumlar iptal edildi.
redirect('/dashboard')
}
app/reset-password/page.tsxtsx
import { resetPassword } from './actions'
export default async function ResetPasswordPage({ searchParams }: { searchParams: Promise<{ token?: string; error?: string }> }) {
const { token, error } = await searchParams
if (!token) return <main><p role="alert">This link is incomplete. Request a new one.</p></main>
return (
<main>
<h1>Choose a new password</h1>
{error && <p role="alert">{error}</p>}
<form action={resetPassword}>
<input type="hidden" name="token" value={token} />
<input name="password" type="password" placeholder="New password" required minLength={8} />
<button type="submit">Save</button>
</form>
</main>
)
}
#Bağlantılar
4. E-posta ve sihirli bağlantılar
Onay ve sihirli bağlantı e-postaları <Site URL>/verify-email?token=… ve <Site URL>/magic-link/verify?token=… adresine bağlantı verir. Bir rota işleyicisi jetonu tüketir ve ardından yeniden yönlendirir.
app/verify-email/route.tstypescript
import { NextResponse, type NextRequest } from 'next/server'
import { serverClient } from '@/lib/aurabase/server'
export async function GET(request: NextRequest) {
const token = request.nextUrl.searchParams.get('token')
if (token) {
const aura = await serverClient()
const { error } = await aura.auth.verifyOtp({ type: 'signup', token })
if (!error) return NextResponse.redirect(new URL('/dashboard', request.url))
}
return NextResponse.redirect(new URL('/login?error=LINK_INVALID', request.url))
}
app/magic-link/verify/route.tstypescript
import { NextResponse, type NextRequest } from 'next/server'
import { serverClient } from '@/lib/aurabase/server'
export async function GET(request: NextRequest) {
const token = request.nextUrl.searchParams.get('token')
if (token) {
const aura = await serverClient()
const { error } = await aura.auth.verifyMagicLink(token)
if (!error) return NextResponse.redirect(new URL('/dashboard', request.url))
}
return NextResponse.redirect(new URL('/login?error=LINK_INVALID', request.url))
}
#Kontrol Paneli
5. Korumalı sayfa
app/dashboard/actions.tstypescript
'use server'
import { redirect } from 'next/navigation'
import { serverClient } from '@/lib/aurabase/server'
export async function logout() {
const aura = await serverClient()
await aura.auth.signOut()
redirect('/login')
}
app/dashboard/page.tsxtsx
import { redirect } from 'next/navigation'
import { serverClient } from '@/lib/aurabase/server'
import { logout } from './actions'
export default async function DashboardPage() {
const aura = await serverClient()
const { data: user } = await aura.auth.getUser()
if (!user) redirect('/login')
return (
<main>
<h1>Dashboard</h1>
<p>Signed in as {user.email}</p>
<form action={logout}>
<button type="submit">Sign out</button>
</form>
</main>
)
}
#testi
6. Yerel olarak deneyin
Yerel yığında e-postalar gönderilmek yerine Mailpit tarafından yakalanır. Gelen kutusunu kubectl -n aurabase-dev port-forward svc/aurabase-mailpit 8025:8025 ve ardından http://localhost:8025 ile açın. Uygulamanızın kaynağını (örneğin http://localhost:3000/*) Studio › Kimlik Doğrulama › Yapılandırma › Yönlendirme URL'lerine ekleyin ve Site URL'sini buna ayarlayın.
Bilgi
proxy.ts yalnızca PROTECTED içinde listelenen rotalara yönlendirme yapar; kontrol paneli sayfası kullanıcıyı getUser() ile tekrar kontrol eder çünkü proxy kendi başına bir yetkilendirme sınırı değildir.
Son güncelleme · 25 Eki 2026