Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions apps/astro/src/@types/types.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { createAuthClient } from "@/lib/client"
import type { authClient } from "@/lib/client"
import type { Session } from "@aura-stack/auth"

export interface AuthContextValue {
session: Session | null
isLoading: boolean
isAuthenticated: boolean
signIn: (typeof createAuthClient)["signIn"]
signOut: (typeof createAuthClient)["signOut"]
signIn: typeof authClient.signIn
signOut: typeof authClient.signOut
}

export interface AuthServerContext {
Expand Down
21 changes: 9 additions & 12 deletions apps/astro/src/contexts/auth.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,31 @@
import { createContext, use, useState, useEffect } from "react"
import { createAuthClient } from "@/lib/client"
import type { Session } from "@aura-stack/auth"
import { authClient } from "@/lib/client"
import type { Session, LiteralUnion, BuiltInOAuthProvider, SignInOptions, SignOutOptions } from "@aura-stack/auth"
import type { AuthProviderProps } from "@/@types/props"
import type { AuthContextValue } from "@/@types/types"

export const AuthContext = createContext<AuthContextValue | undefined>(undefined)

const { signIn: signInClient, signOut: signOutClient, getSession } = createAuthClient

export const AuthProvider = ({ children, session: defaultSession }: AuthProviderProps) => {
const [isLoading, setIsLoading] = useState(defaultSession === undefined)
const [session, setSession] = useState<Session | null>(defaultSession ?? null)
const isAuthenticated = Boolean(session?.user)

const signOut = async (...args: Parameters<typeof signOutClient>) => {
const signIn = async (provider: LiteralUnion<BuiltInOAuthProvider>, options?: SignInOptions) => {
setIsLoading(true)
try {
await signOutClient(...args)
setSession(null)
return await authClient.signIn(provider, options)
} finally {
setIsLoading(false)
}
}

const signIn = async (...args: Parameters<typeof signInClient>) => {
const signOut = async (options?: SignOutOptions) => {
setIsLoading(true)
try {
await signInClient(...args)
const session = await getSession()
setSession(session)
const value = await authClient.signOut(options)
setSession(null)
return value
} finally {
setIsLoading(false)
}
Expand All @@ -42,7 +39,7 @@ export const AuthProvider = ({ children, session: defaultSession }: AuthProvider
}
const fetchSession = async () => {
try {
const session = await getSession()
const session = await authClient.getSession()
setSession(session)
} catch {
setSession(null)
Expand Down
68 changes: 3 additions & 65 deletions apps/astro/src/lib/client.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,6 @@
import { createClient, type Session, type LiteralUnion, type BuiltInOAuthProvider } from "@aura-stack/auth"
import { createAuthClient } from "@aura-stack/auth/client"

export const client = createClient({
baseURL: typeof window !== "undefined" ? window.location.origin : "http://localhost:3000",
export const authClient = createAuthClient({
basePath: "/api/auth",
cache: "no-store",
credentials: "include",
baseURL: "http://localhost:5173",
Comment thread
halvaradop marked this conversation as resolved.
})

const getCSRFToken = async (): Promise<string | null> => {
try {
const response = await client.get("/csrfToken")
if (!response.ok) return null
const data = await response.json()
return data.csrfToken
} catch (error) {
console.log("[error:client] getCSRFToken", error)
return null
}
}

const getSession = async (): Promise<Session | null> => {
try {
const response = await client.get("/session")
if (!response.ok) return null
const session = await response.json()
return session?.authenticated ? session : null
} catch (error) {
console.log("[error:client] getSession", error)
return null
}
}

const signIn = async (provider: LiteralUnion<BuiltInOAuthProvider>, redirectTo: string = "/") => {
const baseURL = window.location.origin
window.location.href = `${baseURL}/api/auth/signIn/${provider}?${new URLSearchParams({ redirectTo })}`
}

const signOut = async (redirectTo: string = "/") => {
try {
const csrfToken = await getCSRFToken()
if (!csrfToken) {
console.log("[error:client] signOut - No CSRF token found")
return null
}
const response = await client.post("/signOut", {
searchParams: {
redirectTo,
token_type_hint: "session_token",
},
headers: {
"X-CSRF-Token": csrfToken,
},
})
const json = await response.json()
return json
} catch (error) {
console.log("[error:client] signOut", error)
return null
}
}

export const createAuthClient = {
getCSRFToken,
getSession,
signIn,
signOut,
}
6 changes: 3 additions & 3 deletions apps/nextjs/app-router/src/@types/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { createAuthClient } from "@/lib/index"
import type { authClient } from "@/lib/client"
import type { Session } from "@aura-stack/auth"

export interface AuthContextValue {
session: Session | null
isLoading: boolean
isAuthenticated: boolean
signIn: (typeof createAuthClient)["signIn"]
signOut: (typeof createAuthClient)["signOut"]
signIn: typeof authClient.signIn
signOut: typeof authClient.signOut
}
40 changes: 2 additions & 38 deletions apps/nextjs/app-router/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Metadata } from "next"
import { Geist, Geist_Mono } from "next/font/google"
import { Header } from "@/components/header"
import { AuthProvider } from "@/contexts/auth"
import { Footer } from "@/components/footer"
import { metadataInfo } from "@/lib/metadata"
import "./globals.css"

const geistSans = Geist({
Expand All @@ -15,43 +15,7 @@ const geistMono = Geist_Mono({
subsets: ["latin"],
})

export const metadata: Metadata = {
title: {
default: "Aura Auth | Next.js Integration Example",
template: "%s | Aura Auth",
},
description:
"Comprehensive authentication for TypeScript applications. Built for speed, security, and developer experience. Powered by Aura Auth Core.",
keywords: ["Next.js", "Authentication", "Aura Auth", "TypeScript", "OAuth", "Session Management", "Security"],
authors: [{ name: "Aura Stack", url: "https://github.com/aura-stack-ts" }],
creator: "Aura Stack",
openGraph: {
type: "website",
locale: "en_US",
url: "https://aura-stack-auth.vercel.app/",
siteName: "Aura Auth",
title: "Aura Auth | Next.js Integration",
description:
"Seamlessly integrate secure authentication into your Next.js apps with Aura Auth Core. Supports OAuth and server-side sessions.",
},
twitter: {
card: "summary_large_image",
title: "Aura Auth | Next.js Integration",
description: "Secure authentication for Next.js powered by Aura Auth Core. Fast, secure, and developer-friendly.",
creator: "@aurastackjs",
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
"max-video-preview": -1,
"max-image-preview": "large",
"max-snippet": -1,
},
},
}
export const metadata = metadataInfo

export default function RootLayout({ children }: LayoutProps<"/">) {
return (
Expand Down
104 changes: 16 additions & 88 deletions apps/nextjs/app-router/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,8 @@
import { Fingerprint, LayoutDashboard } from "lucide-react"
import { builtInOAuthProviders } from "@aura-stack/auth/oauth/index"
import { Button } from "@/components/ui/button"
import { createAuthServer } from "@/lib/index"
import { SessionClient } from "@/components/get-session-client"

const providers = [builtInOAuthProviders.github(), builtInOAuthProviders.gitlab(), builtInOAuthProviders.bitbucket()]
import { Fingerprint } from "lucide-react"
import { AuthClient } from "@/components/auth-client"
import { AuthServer } from "@/components/auth-server"

export default async function Home() {
const { getSession, signIn } = createAuthServer
const session = await getSession()
const isAuthenticated = Boolean(session && session?.user)

const signInAction = async (providerId: string) => {
"use server"
await signIn(providerId)
}

return (
<main className="flex-1 bg-black">
<section className="border-b border-muted">
Expand All @@ -40,79 +27,20 @@ export default async function Home() {
</div>
</section>
<section className="overflow-hidden">
<div className="w-11/12 max-w-5xl mx-auto border-x border-muted grid grid-cols-1 md:grid-cols-2">
<div className="p-8 md:p-12 border-b md:border-b-0 md:border-r border-muted space-y-12 bg-white/1">
<div className="space-y-4">
<div className="flex items-center gap-3 text-foreground">
<Fingerprint className="h-4 w-4" />
<span className="text-white text-xs font-mono uppercase tracking-widest">
NextAuth Integration
</span>
</div>
<p className="text-sm text-white/40 leading-relaxed">
This integration example is not representative of a production application. It demonstrates core
authentication flows and session management patterns for showcase purposes.
</p>
</div>
</div>
<div className="p-8 flex items-center justify-center bg-black md:p-12">
<div className="w-full max-w-sm space-y-6">
{isAuthenticated ? (
<>
<div className="space-y-6 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="py-3 px-2 border border-muted rounded-md space-y-3">
<div className="flex items-center justify-between">
<span className="text-xs font-mono italic">server session active</span>
<LayoutDashboard className="size-4 text-foreground" />
</div>
<div className="flex items-center gap-4">
<div className="size-14 rounded-full bg-linear-to-b from-white to-white/40 p-px">
<div className="h-full w-full rounded-full bg-black flex items-center justify-center text-xl font-bold">
{session?.user?.name?.[0] || "?"}
</div>
</div>
<div>
<p className="text-lg font-medium text-white">{session?.user?.name}</p>
<p className="text-xs text-white/40 font-mono">{session?.user?.email}</p>
</div>
</div>
<div className="pt-3 border-t border-muted">
<div className="flex justify-between items-center text-[10px] font-mono">
<span className="text-white/20 uppercase">ID</span>
<span className="text-white/60 truncate max-w-37.5">
{session?.user?.sub}
</span>
</div>
</div>
</div>
</div>
<SessionClient />
</>
) : (
<div className="space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="space-y-4 text-center">
<h2 className="text-2xl font-semibold text-white">Sign in to continue</h2>
<p className="text-sm text-white/40">
Choose a provider below to authenticate and start your session.
</p>
<div className="flex flex-col gap-y-2">
{providers.map((provider) => (
<form
className="w-full"
action={signInAction.bind(null, provider.id)}
key={provider.id}
>
<Button className="w-full" variant="outline" size="sm" key={provider.id}>
Sign In with {provider.name}
</Button>
</form>
))}
</div>
</div>
</div>
)}
</div>
<div className="w-11/12 max-w-5xl mx-auto py-10 px-6 border-x border-b border-muted space-y-4">
<div className="flex items-center gap-3 text-foreground">
<Fingerprint className="h-4 w-4" />
<span className="text-white text-xs font-mono uppercase tracking-widest">Next.js Auth Integration</span>
</div>
<p className="text-sm text-white/40 leading-relaxed">
This integration example is not representative of a production application. It demonstrates core
authentication flows and session management patterns for showcase purposes for client and server
components.
</p>
</div>
<div className="w-11/12 max-w-5xl mx-auto border-x border-muted grid grid-cols-1 md:grid-cols-2">
<AuthClient />
<AuthServer />
</div>
</section>
</main>
Expand Down
3 changes: 0 additions & 3 deletions apps/nextjs/app-router/src/app/profile/page.tsx

This file was deleted.

3 changes: 2 additions & 1 deletion apps/nextjs/app-router/src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { type AuthInstance, createAuth } from "@aura-stack/auth"
import { builtInOAuthProviders, type BuiltInOAuthProvider } from "@aura-stack/auth/oauth/index"

export const oauth = Object.keys(builtInOAuthProviders) as BuiltInOAuthProvider[]
export const providers = [builtInOAuthProviders.github(), builtInOAuthProviders.gitlab(), builtInOAuthProviders.bitbucket()]

export const { handlers, jose, api }: AuthInstance = createAuth({
oauth,
trustedOrigins: ["http://localhost:3000", "https://*.vercel.app"],
basePath: "/api/auth",
})
Loading
Loading