diff options
Diffstat (limited to 'src/routes/login')
| -rw-r--r-- | src/routes/login/+server.ts | 16 | ||||
| -rw-r--r-- | src/routes/login/callback/+server.ts | 79 | ||||
| -rw-r--r-- | src/routes/login/callback/ok/+page.svelte | 13 | ||||
| -rw-r--r-- | src/routes/login/undo/+server.ts | 16 |
4 files changed, 72 insertions, 52 deletions
diff --git a/src/routes/login/+server.ts b/src/routes/login/+server.ts index 4a032d4..7313f13 100644 --- a/src/routes/login/+server.ts +++ b/src/routes/login/+server.ts @@ -1,10 +1,13 @@ import { getAuthorizeUrl } from '$lib/auth.server.js'; -import { error, redirect } from '@sveltejs/kit'; +import { redirect } from '@sveltejs/kit'; export const GET = async (event) => { let target = event.url.searchParams.get('next') ?? '/'; - let desiredScopes = - event.url.searchParams.get('scope') ?? 'profile vm-own-read'; + let desiredScopes = event.url.searchParams.get('scope') ?? 'default'; + desiredScopes = desiredScopes + .split(' ') + .flatMap((v) => (v === 'default' ? 'vm-own-read vm-own-write' : '')) + .join(' '); if (new URL(target, event.url.href).host !== event.url.host) target = '/'; const existingScopes = (event.cookies.get('oid__scopes') ?? '').split(' '); const authed = await event.locals.auth(); @@ -44,11 +47,14 @@ export const GET = async (event) => { event.cookies.delete('pending-auth-nonces', { path: '/', }); - event.cookies.delete('next', { - path: target, + event.cookies.set('next', target, { + path: '/', }); throw redirect(303, redirectTo); } else { + event.cookies.delete('next', { + path: '/', + }); throw redirect(303, target); } }; diff --git a/src/routes/login/callback/+server.ts b/src/routes/login/callback/+server.ts index 32b1647..1de7811 100644 --- a/src/routes/login/callback/+server.ts +++ b/src/routes/login/callback/+server.ts @@ -1,5 +1,6 @@ +import { base } from '$app/paths'; import * as auth from '$lib/auth.server.js'; -import { error, json, redirect } from '@sveltejs/kit'; +import { error, isHttpError, isRedirect, json, redirect } from '@sveltejs/kit'; import * as client from 'openid-client'; // Pre-checker for nonce, not the primary implementation @@ -18,63 +19,47 @@ const handleNonce = (nonce: string | null, nonceCookie: string | undefined) => { }; export const GET = async (event) => { const sp = event.url.searchParams; - const params = { - sessionState: sp.get('session_state'), - iss: sp.get('iss'), - code: sp.get('code'), - nonce: sp.get('nonce'), - }; - if (!params.sessionState || !params.iss || !params.code) - throw error(400, 'Missing one of session_state, iss, code'); const remainingNonces = handleNonce( - params.nonce, + sp.get('nonce'), event.cookies.get('pending-auth-nonces') ); try { - const tk = await auth.authorizeNewSession( + const tokens = await auth.authorizeNewSession( new URL(event.url.href), - params.nonce ?? undefined + sp.get('nonce') ?? undefined ); - for (const [k, v] of Object.entries({ - oid__access_token: tk.access_token, - oid__token_type: tk.token_type, - oid__expires_at: '' + (Date.now() + (tk.expiresIn() ?? 0) * 1000), - oid__refresh_token: tk.refresh_token, - oid__sub: tk.claims()!.sub, - 'pending-auth-nonces': JSON.stringify(remainingNonces), - })) - if (v) - event.cookies.set(k, v, { - path: '/', - secure: true, - httpOnly: true, - sameSite: true, - }); - if (tk.scope) - event.cookies.set('oid__scopes', tk.scope, { - path: '/', - secure: true, - httpOnly: true, - sameSite: true, - }); - - console.warn( - 'New Session:', - await client.fetchUserInfo( - await auth.getConfig(), - tk.access_token, - tk.claims()!.sub - ) - ); + auth.setCookies(event.cookies, tokens); + event.cookies.set('pending-auth-nonces', JSON.stringify(remainingNonces), { + path: '/', + secure: true, + sameSite: true, + httpOnly: true, + }); - return json({ - sub: tk.claims()!.sub, - at: tk.access_token, + let target = event.cookies.get('next') ?? '/'; + if (new URL(target, event.url.href).host !== event.url.host) target = '/'; + event.cookies.delete('next', { + path: '/', }); + throw redirect( + 303, + `${base}/login/callback/ok?next=${encodeURIComponent(target)}` + ); } catch (e) { - throw redirect(307, '/login'); + if (isRedirect(e) || isHttpError(e)) throw e; + // @ts-ignore + if (e?.cause?.error === 'invalid_grant') + throw error( + 403, + 'Invalid Grant Provided - Does your account have access to all requested resources?' + ); + else + throw error( + 500, + `Could not authorize new session: ${JSON.stringify(e, null, 2)}` + ); } }; diff --git a/src/routes/login/callback/ok/+page.svelte b/src/routes/login/callback/ok/+page.svelte new file mode 100644 index 0000000..a71d962 --- /dev/null +++ b/src/routes/login/callback/ok/+page.svelte @@ -0,0 +1,13 @@ +<script lang="ts"> + import { page } from '$app/state'; + + let target = page.url.searchParams.get('next') ?? '/'; + if (new URL(target, page.url.href).host !== page.url.host) target = '/'; +</script> + +<svelte:head> + <meta http-equiv="refresh" content="0.1; url={target}" /> +</svelte:head> + +<h2 class="text-xl">Redirecting...</h2> +<p>If nothing happens, click <a href={target}>here</a>.</p> diff --git a/src/routes/login/undo/+server.ts b/src/routes/login/undo/+server.ts new file mode 100644 index 0000000..a3559d6 --- /dev/null +++ b/src/routes/login/undo/+server.ts @@ -0,0 +1,16 @@ +import * as auth from '$lib/auth.server.js'; +import { error, redirect } from '@sveltejs/kit'; +import * as client from 'openid-client'; +export const GET = async (event) => { + const token = event.cookies.get('oid__access_token'); + if (!token) throw error(403, 'Logout requires an access token!'); + await client.tokenRevocation(await auth.getConfig(), token); + let target = + event.url.searchParams.get('next') ?? event.cookies.get('next') ?? '/'; + if (new URL(target, event.url.href).host !== event.url.host) target = '/'; + event.cookies.delete('next', { + path: '/', + }); + auth.unsetCookies(event.cookies); + throw redirect(303, `/login/callback/ok?next=${encodeURIComponent(target)}`); +}; |