diff options
| -rw-r--r-- | src/app.d.ts | 2 | ||||
| -rw-r--r-- | src/hooks.server.ts | 14 | ||||
| -rw-r--r-- | src/routes/+layout.svelte | 6 | ||||
| -rw-r--r-- | src/routes/api/v1/vms/list/+server.ts | 12 | ||||
| -rw-r--r-- | src/routes/api/v1/whoami/+server.ts | 40 | ||||
| -rw-r--r-- | src/routes/aup/+page.svelte | 3 | ||||
| -rw-r--r-- | src/routes/scope-prompt/[scopes]/+server.ts | 6 | ||||
| -rw-r--r-- | src/routes/vms/+page.ts | 5 |
8 files changed, 80 insertions, 8 deletions
diff --git a/src/app.d.ts b/src/app.d.ts index 4f96a65..8d25cc0 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -8,7 +8,7 @@ declare global { // interface Error {} interface Locals { /** - * Undefined: not authorized + * Undefined: not authenticated * Null: failed to validate/renew token */ auth: () => Promise<Session | undefined | null>; diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 05b8b18..4c11926 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -12,6 +12,16 @@ export const authHandler = ( let refreshToken = event.cookies.get('oid__refresh_token'); let accessToken = event.cookies.get('oid__access_token'); let expiry = Number(event.cookies.get('oid__expires_at')); + let tokenSource = accessToken ? 'cookie' : 'none'; + if (!accessToken) { + const auth = event.request.headers.get('Authorization'); + if (auth) { + if (auth.startsWith('Bearer')) { + accessToken = auth.substring(6).trimStart(); + tokenSource = 'header/bearer'; + } + } + } if ( refreshToken && (!accessToken || isNaN(expiry) || expiry - 60 * 1000 >= Date.now()) @@ -41,6 +51,7 @@ export const authHandler = ( auth.unsetCookies(event.cookies); return null; } + expiry = expiry ?? introspectionResponse.exp; return { tokens: { scope: introspectionResponse.scope, @@ -57,7 +68,8 @@ export const authHandler = ( auth.unsetCookies(event.cookies); throw e; }), - __is_session: 1, + __isSession: 1, + __tokenSource: tokenSource, }; } catch (error) { return null; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 61bd14e..c8e4917 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -14,7 +14,11 @@ <nav class="header"> <h1 class="text-4xl">crunched</h1> <p> - <a href="/home">home</a> - {#if page.data.session}<a href="/vms">vms</a> - + <a href="/home" data-sveltekit-preload-code="viewport">home</a> - {#if page.data.session}<a + href="/vms" + data-sveltekit-preload-code="viewport">vms</a + > + - <a href="/login/undo?next={encodeURIComponent( page.url.pathname + page.url.search diff --git a/src/routes/api/v1/vms/list/+server.ts b/src/routes/api/v1/vms/list/+server.ts new file mode 100644 index 0000000..7bbf8f3 --- /dev/null +++ b/src/routes/api/v1/vms/list/+server.ts @@ -0,0 +1,12 @@ +import { error, json } from '@sveltejs/kit'; +import { type Session } from '../../../../../hooks.server.js'; + +export const GET = async ({ locals }) => { + const data = (await locals.auth()) as Session; + if (data === undefined) throw error(403, 'Unauthorized'); + if (data === null) throw error(401, 'Session Expired'); + + return json({ + todo: 'implement', + }); +}; diff --git a/src/routes/api/v1/whoami/+server.ts b/src/routes/api/v1/whoami/+server.ts index 98809a4..2b7d430 100644 --- a/src/routes/api/v1/whoami/+server.ts +++ b/src/routes/api/v1/whoami/+server.ts @@ -3,7 +3,41 @@ import { filterSession, type Session } from '../../../../hooks.server.js'; export const GET = async ({ locals }) => { const data = (await locals.auth()) as Session; - if (data === undefined) throw error(403, 'Unauthorized'); - if (data === null) throw error(401, 'Session Expired'); - return json(filterSession(data)); + + // note: these return types are JUST for this endpoint - rely on status code exclusively for the actual meaning. + const headers = { + 'Access-Control-Allow-Origin': '*', + }; + if (data === undefined) + return json( + { + '': '', + kind: 'NOT_AUTHENTICATED' as const, + message: 'Unauthenticated', + }, + { + status: 403, + statusText: 'Forbidden', + headers, + } + ); + if (data === null) + return json( + { + '': '', + kind: 'EXPIRED' as const, + message: 'Session Expired', + }, + { + status: 401, + statusText: 'Unauthorized', + headers, + } + ); + + return json(filterSession(data), { + headers, + status: 200, + statusText: 'OK :3', + }); }; diff --git a/src/routes/aup/+page.svelte b/src/routes/aup/+page.svelte index 66601ae..cf25031 100644 --- a/src/routes/aup/+page.svelte +++ b/src/routes/aup/+page.svelte @@ -47,7 +47,8 @@ </ol> <p class="mt-2"> Tl;dr: Abide by the same general rules any other provider provides. Try not - to violate regional laws in Zurich, Switzerland. + to violate regional laws in Zurich, Switzerland. Don't do anything you + wouldn't want your friends to do on your internal network. </p> <h2 class="text-2xl mt-4">Excessive Resource Use Policy</h2> <p> diff --git a/src/routes/scope-prompt/[scopes]/+server.ts b/src/routes/scope-prompt/[scopes]/+server.ts index f919b9c..5521cf5 100644 --- a/src/routes/scope-prompt/[scopes]/+server.ts +++ b/src/routes/scope-prompt/[scopes]/+server.ts @@ -17,5 +17,9 @@ export const GET = async (e) => { ) ) throw redirect(303, base + '/scope-prompt/ok'); - else throw error(500, 'In server mode, this branch should be unreachable'); + else + throw error( + 500, + 'In server mode, this branch should be unreachable. checkScope with getScopeOnFail should never return false outside of the client.' + ); }; diff --git a/src/routes/vms/+page.ts b/src/routes/vms/+page.ts new file mode 100644 index 0000000..fb0ce3c --- /dev/null +++ b/src/routes/vms/+page.ts @@ -0,0 +1,5 @@ +export const load = ({ fetch }) => { + return { + todo: 'use /api/v1/vms/list', + }; +}; |