From 53b2b3c8cba84b52e4e41a347bff99b254af5369 Mon Sep 17 00:00:00 2001 From: Mohamed Melouk <42706279+cobraprojects@users.noreply.github.com> Date: Fri, 8 May 2026 00:23:15 +0300 Subject: [PATCH 1/4] add social login to auth --- apps/blog-next/app/api/login/route.ts | 9 +- apps/blog-next/app/api/logout/route.ts | 8 +- apps/blog-next/app/api/register/route.ts | 6 - .../app/auth/github/callback/route.ts | 21 +++ apps/blog-next/app/auth/github/route.ts | 5 + .../app/auth/google/callback/route.ts | 21 +++ apps/blog-next/app/auth/google/route.ts | 5 + apps/blog-next/app/login/page.tsx | 5 + apps/blog-nuxt/app/pages/login.vue | 7 + apps/blog-nuxt/server/api/login.post.ts | 2 - apps/blog-nuxt/server/api/logout.post.ts | 5 +- apps/blog-nuxt/server/api/register.post.ts | 1 - apps/blog-nuxt/server/lib/request.ts | 15 ++ .../server/routes/auth/github.get.ts | 7 + .../server/routes/auth/github/callback.get.ts | 15 ++ .../server/routes/auth/google.get.ts | 7 + .../server/routes/auth/google/callback.get.ts | 15 ++ .../src/routes/api/login/+server.ts | 9 +- .../src/routes/api/logout/+server.ts | 8 +- .../src/routes/api/register/+server.ts | 6 - .../src/routes/auth/github/+server.ts | 5 + .../routes/auth/github/callback/+server.ts | 21 +++ .../src/routes/auth/google/+server.ts | 5 + .../routes/auth/google/callback/+server.ts | 21 +++ .../src/routes/login/+page.svelte | 7 + apps/docs/docs/auth/social-login.md | 44 ++++- packages/adapter-next/src/config.ts | 86 ++++++++- packages/adapter-next/src/runtime.ts | 101 ++++++++++ packages/adapter-next/tests/adapter.test.ts | 33 ++++ .../src/runtime/composables/index.ts | 31 ++++ packages/adapter-nuxt/tests/module.test.ts | 17 ++ packages/adapter-sveltekit/src/index.ts | 112 +++++++++++- .../adapter-sveltekit/tests/runtime.test.ts | 24 +++ packages/auth-social/src/index.ts | 67 ++++--- packages/auth-social/tests/package.test.ts | 128 +++++++++---- packages/auth/src/contracts.ts | 1 + packages/auth/src/runtime.ts | 19 +- packages/auth/src/sveltekit/server.ts | 123 ++++++++++--- packages/auth/tests/package.test.ts | 33 ++++ packages/core/src/portable/holo.ts | 8 + scripts/validate-framework-smoke.mjs | 2 +- tests/example-app-auth-flow.mjs | 172 ++++++++++++++++++ 42 files changed, 1088 insertions(+), 149 deletions(-) create mode 100644 apps/blog-next/app/auth/github/callback/route.ts create mode 100644 apps/blog-next/app/auth/github/route.ts create mode 100644 apps/blog-next/app/auth/google/callback/route.ts create mode 100644 apps/blog-next/app/auth/google/route.ts create mode 100644 apps/blog-nuxt/server/lib/request.ts create mode 100644 apps/blog-nuxt/server/routes/auth/github.get.ts create mode 100644 apps/blog-nuxt/server/routes/auth/github/callback.get.ts create mode 100644 apps/blog-nuxt/server/routes/auth/google.get.ts create mode 100644 apps/blog-nuxt/server/routes/auth/google/callback.get.ts create mode 100644 apps/blog-sveltekit/src/routes/auth/github/+server.ts create mode 100644 apps/blog-sveltekit/src/routes/auth/github/callback/+server.ts create mode 100644 apps/blog-sveltekit/src/routes/auth/google/+server.ts create mode 100644 apps/blog-sveltekit/src/routes/auth/google/callback/+server.ts diff --git a/apps/blog-next/app/api/login/route.ts b/apps/blog-next/app/api/login/route.ts index 85f8ca8..6b706f3 100644 --- a/apps/blog-next/app/api/login/route.ts +++ b/apps/blog-next/app/api/login/route.ts @@ -27,11 +27,6 @@ export async function POST(request: Request) { }) } - const headers = new Headers() - for (const cookie of session.cookies) { - headers.append('set-cookie', cookie) - } - return Response.json(submission.success({ message: session.emailVerificationRequired ? 'Signed in. Verify your email address to continue.' @@ -40,7 +35,5 @@ export async function POST(request: Request) { ? session.emailVerificationRoute ?? '/verify-email' : '/admin', user: session.user, - }), { - headers, - }) + })) } diff --git a/apps/blog-next/app/api/logout/route.ts b/apps/blog-next/app/api/logout/route.ts index 3be87d2..3b94ae4 100644 --- a/apps/blog-next/app/api/logout/route.ts +++ b/apps/blog-next/app/api/logout/route.ts @@ -1,18 +1,12 @@ import { logout, user } from '@holo-js/auth' export async function POST() { - const signedOut = await logout() - const headers = new Headers() - for (const cookie of signedOut.cookies) { - headers.append('set-cookie', cookie) - } + await logout() return Response.json({ ok: true, authenticated: false, message: 'Signed out successfully.', user: await user(), - }, { - headers, }) } diff --git a/apps/blog-next/app/api/register/route.ts b/apps/blog-next/app/api/register/route.ts index f7c109c..b5d8016 100644 --- a/apps/blog-next/app/api/register/route.ts +++ b/apps/blog-next/app/api/register/route.ts @@ -28,11 +28,6 @@ export async function POST(request: Request) { } const session = await loginUsing(created) - const headers = new Headers() - for (const cookie of session.cookies) { - headers.append('set-cookie', cookie) - } - return Response.json(submission.success({ message: session.emailVerificationRequired ? 'Account created. Check your inbox to verify your email address.' @@ -43,6 +38,5 @@ export async function POST(request: Request) { user: session.user, }, 201), { status: 201, - headers, }) } diff --git a/apps/blog-next/app/auth/github/callback/route.ts b/apps/blog-next/app/auth/github/callback/route.ts new file mode 100644 index 0000000..b3b3e24 --- /dev/null +++ b/apps/blog-next/app/auth/github/callback/route.ts @@ -0,0 +1,21 @@ +import { redirect } from 'next/navigation' +import auth from '@holo-js/auth' +import { callback } from '@holo-js/auth-social' + +export function GET(request: Request): Promise { + return handleCallback(request) +} + +async function handleCallback(request: Request): Promise { + const result = await callback('github', request) + if (!result.ok) { + return Response.json({ + message: result.message, + }, { + status: result.status, + }) + } + + await auth.guard(result.guard).loginUsing(result.user) + redirect('/admin') +} diff --git a/apps/blog-next/app/auth/github/route.ts b/apps/blog-next/app/auth/github/route.ts new file mode 100644 index 0000000..0650a4c --- /dev/null +++ b/apps/blog-next/app/auth/github/route.ts @@ -0,0 +1,5 @@ +import { redirect } from '@holo-js/auth-social' + +export function GET(request: Request): Promise { + return redirect('github', request) +} diff --git a/apps/blog-next/app/auth/google/callback/route.ts b/apps/blog-next/app/auth/google/callback/route.ts new file mode 100644 index 0000000..827b3d8 --- /dev/null +++ b/apps/blog-next/app/auth/google/callback/route.ts @@ -0,0 +1,21 @@ +import { redirect } from 'next/navigation' +import auth from '@holo-js/auth' +import { callback } from '@holo-js/auth-social' + +export function GET(request: Request): Promise { + return handleCallback(request) +} + +async function handleCallback(request: Request): Promise { + const result = await callback('google', request) + if (!result.ok) { + return Response.json({ + message: result.message, + }, { + status: result.status, + }) + } + + await auth.guard(result.guard).loginUsing(result.user) + redirect('/admin') +} diff --git a/apps/blog-next/app/auth/google/route.ts b/apps/blog-next/app/auth/google/route.ts new file mode 100644 index 0000000..5c1baa4 --- /dev/null +++ b/apps/blog-next/app/auth/google/route.ts @@ -0,0 +1,5 @@ +import { redirect } from '@holo-js/auth-social' + +export function GET(request: Request): Promise { + return redirect('google', request) +} diff --git a/apps/blog-next/app/login/page.tsx b/apps/blog-next/app/login/page.tsx index 36914d2..2c39684 100644 --- a/apps/blog-next/app/login/page.tsx +++ b/apps/blog-next/app/login/page.tsx @@ -44,6 +44,11 @@ export default function LoginPage() {

Use your email address and password to access the admin area.

+ +
{ event.preventDefault(); form.submit() }} style={{ display: 'grid', gap: '0.9rem' }}>