diff --git a/apps/blog-next/app/api/auth/workos/callback/route.ts b/apps/blog-next/app/api/auth/workos/callback/route.ts new file mode 100644 index 00000000..ac9510e8 --- /dev/null +++ b/apps/blog-next/app/api/auth/workos/callback/route.ts @@ -0,0 +1,10 @@ +import { completeWorkosAuth } from '@holo-js/auth-workos' + +export async function GET(request: Request) { + const result = await completeWorkosAuth(request) + if (!result.ok) { + return Response.redirect(new URL(`/login?error=${encodeURIComponent(result.code)}`, request.url)) + } + + return Response.redirect(new URL('/admin', request.url)) +} diff --git a/apps/blog-next/app/api/auth/workos/login/route.ts b/apps/blog-next/app/api/auth/workos/login/route.ts new file mode 100644 index 00000000..3839061c --- /dev/null +++ b/apps/blog-next/app/api/auth/workos/login/route.ts @@ -0,0 +1,5 @@ +import { loginWithWorkos } from '@holo-js/auth-workos' + +export async function GET(request: Request) { + return await loginWithWorkos(request) +} diff --git a/apps/blog-next/app/api/auth/workos/logout/route.ts b/apps/blog-next/app/api/auth/workos/logout/route.ts new file mode 100644 index 00000000..d556de00 --- /dev/null +++ b/apps/blog-next/app/api/auth/workos/logout/route.ts @@ -0,0 +1,10 @@ +import { logoutWithWorkos } from '@holo-js/auth-workos' + +export async function POST(request: Request) { + const result = await logoutWithWorkos(request) + if (!result.ok) { + return Response.json(result, { status: 422 }) + } + + return Response.redirect(result.url, 303) +} diff --git a/apps/blog-next/app/api/auth/workos/register/route.ts b/apps/blog-next/app/api/auth/workos/register/route.ts new file mode 100644 index 00000000..93ace66f --- /dev/null +++ b/apps/blog-next/app/api/auth/workos/register/route.ts @@ -0,0 +1,5 @@ +import { registerWithWorkos } from '@holo-js/auth-workos' + +export async function GET(request: Request) { + return await registerWithWorkos(request) +} diff --git a/apps/blog-next/app/auth-nav.tsx b/apps/blog-next/app/auth-nav.tsx index 98ce7f72..61dcd30d 100644 --- a/apps/blog-next/app/auth-nav.tsx +++ b/apps/blog-next/app/auth-nav.tsx @@ -18,6 +18,10 @@ const logoutButtonStyle = { padding: 0, } as const +const logoutFormStyle = { + display: 'inline', +} as const + export function AuthNav() { const auth = useAuth() const [isLoggingOut, setIsLoggingOut] = useState(false) @@ -57,6 +61,9 @@ export function AuthNav() { <> {displayName} +
+ +
) } diff --git a/apps/blog-next/app/login/page.tsx b/apps/blog-next/app/login/page.tsx index 2c396842..5b5c7f2d 100644 --- a/apps/blog-next/app/login/page.tsx +++ b/apps/blog-next/app/login/page.tsx @@ -47,6 +47,7 @@ export default function LoginPage() {
Continue with Google Continue with GitHub + Continue with WorkOS
{ event.preventDefault(); form.submit() }} style={{ display: 'grid', gap: '0.9rem' }}> @@ -97,7 +98,7 @@ export default function LoginPage() { ) : null}
- Create account + Create account Forgot password?
diff --git a/apps/blog-next/app/register/page.tsx b/apps/blog-next/app/register/page.tsx index 1a744cf5..168396d9 100644 --- a/apps/blog-next/app/register/page.tsx +++ b/apps/blog-next/app/register/page.tsx @@ -100,6 +100,7 @@ export default function RegisterPage() { ) : null} Already have an account? + Register with WorkOS ) } diff --git a/apps/blog-next/config/auth.ts b/apps/blog-next/config/auth.ts index 2c9f962b..b54d336e 100644 --- a/apps/blog-next/config/auth.ts +++ b/apps/blog-next/config/auth.ts @@ -41,7 +41,6 @@ export default defineAuthConfig({ personalAccessTokens: { defaultAbilities: [], }, - socialEncryptionKey: env('AUTH_SOCIAL_ENCRYPTION_KEY'), social: { google: { clientId: env('AUTH_GOOGLE_CLIENT_ID'), @@ -57,12 +56,11 @@ export default defineAuthConfig({ }, }, workos: { + provider: env('AUTH_WORKOS_PROVIDER', 'dashboard'), dashboard: { clientId: env('WORKOS_CLIENT_ID'), apiKey: env('WORKOS_API_KEY'), - cookiePassword: env('WORKOS_COOKIE_PASSWORD'), redirectUri: env('WORKOS_REDIRECT_URI'), - sessionCookie: env('WORKOS_SESSION_COOKIE', "wos-session"), }, }, // Add a dedicated guard and provider if WorkOS users should resolve through a different model. diff --git a/apps/blog-next/tests/run.mjs b/apps/blog-next/tests/run.mjs index f66c5abf..6e144b65 100644 --- a/apps/blog-next/tests/run.mjs +++ b/apps/blog-next/tests/run.mjs @@ -40,6 +40,7 @@ let capturedOutput = '' function createChildEnv(overrides = {}) { const env = { ...process.env, + APP_NAME: '', HOLO_SECURITY_TRUST_PROXY: 'true', ...overrides, } diff --git a/apps/blog-nuxt/app/app.vue b/apps/blog-nuxt/app/app.vue index 76c87491..3f5562c6 100644 --- a/apps/blog-nuxt/app/app.vue +++ b/apps/blog-nuxt/app/app.vue @@ -21,6 +21,9 @@ async function logout() { diff --git a/apps/blog-nuxt/config/auth.ts b/apps/blog-nuxt/config/auth.ts index 2c9f962b..b54d336e 100644 --- a/apps/blog-nuxt/config/auth.ts +++ b/apps/blog-nuxt/config/auth.ts @@ -41,7 +41,6 @@ export default defineAuthConfig({ personalAccessTokens: { defaultAbilities: [], }, - socialEncryptionKey: env('AUTH_SOCIAL_ENCRYPTION_KEY'), social: { google: { clientId: env('AUTH_GOOGLE_CLIENT_ID'), @@ -57,12 +56,11 @@ export default defineAuthConfig({ }, }, workos: { + provider: env('AUTH_WORKOS_PROVIDER', 'dashboard'), dashboard: { clientId: env('WORKOS_CLIENT_ID'), apiKey: env('WORKOS_API_KEY'), - cookiePassword: env('WORKOS_COOKIE_PASSWORD'), redirectUri: env('WORKOS_REDIRECT_URI'), - sessionCookie: env('WORKOS_SESSION_COOKIE', "wos-session"), }, }, // Add a dedicated guard and provider if WorkOS users should resolve through a different model. diff --git a/apps/blog-nuxt/server/api/auth/workos/callback.get.ts b/apps/blog-nuxt/server/api/auth/workos/callback.get.ts new file mode 100644 index 00000000..c7d0aa63 --- /dev/null +++ b/apps/blog-nuxt/server/api/auth/workos/callback.get.ts @@ -0,0 +1,12 @@ +import { completeWorkosAuth } from '@holo-js/auth-workos' +import { sendRedirect } from 'h3' + +export default defineEventHandler(async (event) => { + const result = await completeWorkosAuth(event) + if (!result.ok) { + const errCode = result.code ?? 'unknown_error' + return await sendRedirect(event, `/login?error=${encodeURIComponent(errCode)}`, 303) + } + + return await sendRedirect(event, '/admin', 303) +}) diff --git a/apps/blog-nuxt/server/api/auth/workos/login.get.ts b/apps/blog-nuxt/server/api/auth/workos/login.get.ts new file mode 100644 index 00000000..465b7be5 --- /dev/null +++ b/apps/blog-nuxt/server/api/auth/workos/login.get.ts @@ -0,0 +1,5 @@ +import { loginWithWorkos } from '@holo-js/auth-workos' + +export default defineEventHandler(async (event) => { + return await loginWithWorkos(event) +}) diff --git a/apps/blog-nuxt/server/api/auth/workos/logout.post.ts b/apps/blog-nuxt/server/api/auth/workos/logout.post.ts new file mode 100644 index 00000000..0dd8dac4 --- /dev/null +++ b/apps/blog-nuxt/server/api/auth/workos/logout.post.ts @@ -0,0 +1,14 @@ +import { logoutWithWorkos } from '@holo-js/auth-workos' +import { createError, sendRedirect } from 'h3' + +export default defineEventHandler(async (event) => { + const result = await logoutWithWorkos(event) + if (!result.ok) { + throw createError({ + statusCode: 422, + statusMessage: result.message, + }) + } + + return await sendRedirect(event, result.url, 303) +}) diff --git a/apps/blog-nuxt/server/api/auth/workos/register.get.ts b/apps/blog-nuxt/server/api/auth/workos/register.get.ts new file mode 100644 index 00000000..0beb0684 --- /dev/null +++ b/apps/blog-nuxt/server/api/auth/workos/register.get.ts @@ -0,0 +1,5 @@ +import { registerWithWorkos } from '@holo-js/auth-workos' + +export default defineEventHandler(async (event) => { + return await registerWithWorkos(event) +}) diff --git a/apps/blog-nuxt/tests/run.mjs b/apps/blog-nuxt/tests/run.mjs index 24fc1126..ee3117b4 100644 --- a/apps/blog-nuxt/tests/run.mjs +++ b/apps/blog-nuxt/tests/run.mjs @@ -43,6 +43,7 @@ let capturedOutput = '' function createChildEnv(overrides = {}) { const env = { ...process.env, + APP_NAME: '', HOLO_SECURITY_TRUST_PROXY: 'true', ...overrides, } diff --git a/apps/blog-sveltekit/config/auth.ts b/apps/blog-sveltekit/config/auth.ts index 2c9f962b..b54d336e 100644 --- a/apps/blog-sveltekit/config/auth.ts +++ b/apps/blog-sveltekit/config/auth.ts @@ -41,7 +41,6 @@ export default defineAuthConfig({ personalAccessTokens: { defaultAbilities: [], }, - socialEncryptionKey: env('AUTH_SOCIAL_ENCRYPTION_KEY'), social: { google: { clientId: env('AUTH_GOOGLE_CLIENT_ID'), @@ -57,12 +56,11 @@ export default defineAuthConfig({ }, }, workos: { + provider: env('AUTH_WORKOS_PROVIDER', 'dashboard'), dashboard: { clientId: env('WORKOS_CLIENT_ID'), apiKey: env('WORKOS_API_KEY'), - cookiePassword: env('WORKOS_COOKIE_PASSWORD'), redirectUri: env('WORKOS_REDIRECT_URI'), - sessionCookie: env('WORKOS_SESSION_COOKIE', "wos-session"), }, }, // Add a dedicated guard and provider if WorkOS users should resolve through a different model. diff --git a/apps/blog-sveltekit/src/routes/+layout.svelte b/apps/blog-sveltekit/src/routes/+layout.svelte index dc1f257d..87a94ab3 100644 --- a/apps/blog-sveltekit/src/routes/+layout.svelte +++ b/apps/blog-sveltekit/src/routes/+layout.svelte @@ -42,6 +42,9 @@ {#if auth.authenticated} {displayName} + + +
{:else} Login Register @@ -94,6 +97,9 @@ opacity: 0.6; pointer-events: none; } + .logout-form { + display: inline; + } a { color: #cbd5e1; text-decoration: none; diff --git a/apps/blog-sveltekit/src/routes/api/auth/workos/callback/+server.ts b/apps/blog-sveltekit/src/routes/api/auth/workos/callback/+server.ts new file mode 100644 index 00000000..a95a47b1 --- /dev/null +++ b/apps/blog-sveltekit/src/routes/api/auth/workos/callback/+server.ts @@ -0,0 +1,11 @@ +import { redirect, type RequestHandler } from '@sveltejs/kit' +import { completeWorkosAuth } from '@holo-js/auth-workos' + +export const GET = (async (event) => { + const result = await completeWorkosAuth(event) + if (!result.ok) { + throw redirect(303, `/login?error=${encodeURIComponent(result.code)}`) + } + + throw redirect(303, '/admin') +}) satisfies RequestHandler diff --git a/apps/blog-sveltekit/src/routes/api/auth/workos/login/+server.ts b/apps/blog-sveltekit/src/routes/api/auth/workos/login/+server.ts new file mode 100644 index 00000000..72ccebec --- /dev/null +++ b/apps/blog-sveltekit/src/routes/api/auth/workos/login/+server.ts @@ -0,0 +1,6 @@ +import { loginWithWorkos } from '@holo-js/auth-workos' +import type { RequestHandler } from './$types' + +export const GET = (async (event) => { + return await loginWithWorkos(event) +}) satisfies RequestHandler diff --git a/apps/blog-sveltekit/src/routes/api/auth/workos/logout/+server.ts b/apps/blog-sveltekit/src/routes/api/auth/workos/logout/+server.ts new file mode 100644 index 00000000..f1e93aca --- /dev/null +++ b/apps/blog-sveltekit/src/routes/api/auth/workos/logout/+server.ts @@ -0,0 +1,11 @@ +import { redirect, type RequestHandler } from '@sveltejs/kit' +import { logoutWithWorkos } from '@holo-js/auth-workos' + +export const POST = (async (event) => { + const result = await logoutWithWorkos(event) + if (!result.ok) { + return Response.json(result, { status: 422 }) + } + + throw redirect(303, result.url) +}) satisfies RequestHandler diff --git a/apps/blog-sveltekit/src/routes/api/auth/workos/register/+server.ts b/apps/blog-sveltekit/src/routes/api/auth/workos/register/+server.ts new file mode 100644 index 00000000..e271c22f --- /dev/null +++ b/apps/blog-sveltekit/src/routes/api/auth/workos/register/+server.ts @@ -0,0 +1,6 @@ +import { registerWithWorkos } from '@holo-js/auth-workos' +import type { RequestHandler } from './$types' + +export const GET = (async (event) => { + return await registerWithWorkos(event) +}) satisfies RequestHandler diff --git a/apps/blog-sveltekit/src/routes/login/+page.svelte b/apps/blog-sveltekit/src/routes/login/+page.svelte index 8a3523e6..4a472483 100644 --- a/apps/blog-sveltekit/src/routes/login/+page.svelte +++ b/apps/blog-sveltekit/src/routes/login/+page.svelte @@ -30,6 +30,7 @@
{ event.preventDefault(); form.submit() }}> diff --git a/apps/blog-sveltekit/src/routes/register/+page.svelte b/apps/blog-sveltekit/src/routes/register/+page.svelte index a7094569..2701da8d 100644 --- a/apps/blog-sveltekit/src/routes/register/+page.svelte +++ b/apps/blog-sveltekit/src/routes/register/+page.svelte @@ -96,6 +96,7 @@ {/if} Already have an account? + Register with WorkOS