Skip to content
← Public packages

@kentcdodds/package-app-kit

Design tokens, PWA install/update, About/version, cache helpers, and optional realtime notes sync for Kody package apps.

FollowFork

scripts/smoke-auth.mjs

151 lines · 5.5 KB · JavaScript
import assert from 'node:assert/strict'
import {
	createPackageAppAuth,
	parsePackageAppAuthIdentityFromHostedUrl,
	readPackageAppVisitorHeader,
} from '../src/auth.ts'

assert.deepEqual(
	parsePackageAppAuthIdentityFromHostedUrl(
		'https://kentcdodds.kody.run/packages/package-app-kit/',
	),
	{ app: 'package-app-kit', org: 'kentcdodds', appOriginMount: false },
)
assert.deepEqual(
	parsePackageAppAuthIdentityFromHostedUrl(
		'https://kody.codes/@KentCDodds/packages/Demo/notes',
	),
	{ app: 'demo', org: 'kentcdodds', appOriginMount: true },
)
assert.deepEqual(parsePackageAppAuthIdentityFromHostedUrl('https://custom.example/'), {
	app: null,
	org: null,
	appOriginMount: false,
})

const calls = []
const auth = createPackageAppAuth({
	mode: 'required',
	scopes: ['email', 'email'],
	hostedUrl: 'https://notes.kody.run/notes-app',
	fetch: async (request) => {
		calls.push(request)
		if (!request.headers.get('Cookie')?.includes('__Host-kody_pkg_session=ok')) {
			return new Response('{}', { status: 401 })
		}
		return Response.json({ userId: 'u1', username: 'kent', displayName: 'Kent', role: 'admin' })
	},
})

const req = (cookie) =>
	new Request('https://notes.kody.run/notes?tab=1', cookie ? { headers: { Cookie: cookie } } : {})

// Subdomain host: app only (org lives in the Host label)
assert.equal(auth.loginUrl(), 'https://notes.kody.run/-/auth/login?app=notes-app&scope=email')
assert.equal(
	auth.loginUrl({ request: req(), returnTo: '/notes?tab=1' }),
	'https://notes.kody.run/-/auth/login?app=notes-app&return_to=%2Fnotes%3Ftab%3D1&scope=email',
)
assert.equal(auth.loginUrl({ scopes: [] }), 'https://notes.kody.run/-/auth/login?app=notes-app')
assert.equal(
	auth.logoutUrl({ returnTo: '/' }),
	'https://notes.kody.run/-/auth/logout?app=notes-app&return_to=%2F',
)
assert.equal(auth.meUrl(), 'https://notes.kody.run/-/auth/me?app=notes-app')

const withHosted = createPackageAppAuth({ hostedUrl: 'https://x.kody.run/x/' })
assert.equal(withHosted.meUrl(), 'https://x.kody.run/-/auth/me?app=x')

const legacyHosted = createPackageAppAuth({ hostedUrl: 'https://x.kody.run/packages/x/' })
assert.equal(legacyHosted.meUrl(), 'https://x.kody.run/-/auth/me?app=x')

const withOrigin = createPackageAppAuth({ origin: 'https://a.test', hostedUrl: 'https://b.test' })
assert.equal(withOrigin.logoutUrl(), 'https://a.test/-/auth/logout')

const withOriginAndApp = createPackageAppAuth({
	origin: 'https://a.test',
	hostedUrl: 'https://owner.kody.run/leaf',
})
assert.equal(
	withOriginAndApp.logoutUrl({ returnTo: '/' }),
	'https://a.test/-/auth/logout?app=leaf&org=owner&return_to=%2F',
)

// Preview / app-origin: app + org
const preview = createPackageAppAuth({
	hostedUrl: 'https://kody.codes/@acme/packages/demo',
})
assert.equal(
	preview.loginUrl({ returnTo: '/notes' }),
	'https://kody.codes/-/auth/login?app=demo&org=acme&return_to=%2Fnotes',
)
assert.equal(
	preview.logoutUrl({ returnTo: '/' }),
	'https://kody.codes/-/auth/logout?app=demo&org=acme&return_to=%2F',
)
assert.equal(preview.meUrl(), 'https://kody.codes/-/auth/me?app=demo&org=acme')

// Explicit options win over hostedUrl parse
const explicit = createPackageAppAuth({
	hostedUrl: 'https://kody.codes/@acme/packages/demo',
	app: 'other',
	org: 'beta',
})
assert.equal(explicit.meUrl(), 'https://kody.codes/-/auth/me?app=other&org=beta')

// username alias
const viaUsername = createPackageAppAuth({
	origin: 'https://preview.example',
	app: 'leaf',
	username: 'Owner',
})
assert.equal(
	viaUsername.loginUrl(),
	'https://preview.example/-/auth/login?app=leaf&org=owner',
)

assert.equal(await auth.getUser(req()), null)
assert.equal(calls.length, 0, 'no cookie → no fetch')
assert.equal(await auth.getUser(req('a=b')), null)
assert.equal(calls[0].url, 'https://notes.kody.run/-/auth/me?app=notes-app')
const user = await auth.getUser(req('__Host-kody_pkg_session=ok'))
assert.equal(user?.userId, 'u1')

let thrown
try {
	await auth.resolveUser(req('a=b'))
} catch (e) {
	thrown = e
}
assert.ok(thrown instanceof Response)
assert.equal(thrown.status, 302)
assert.equal(
	thrown.headers.get('Location'),
	'https://notes.kody.run/-/auth/login?app=notes-app&return_to=%2Fnotes%3Ftab%3D1&scope=email',
)
assert.equal((await auth.resolveUser(req('__Host-kody_pkg_session=ok')))?.username, 'kent')

// Package-app server code: the platform strips Cookie and sets the verified
// X-Kody-Visitor header. getUser reads it without any network call.
const visitorReq = (value) =>
	new Request('https://notes.kody.run/notes', { headers: { 'X-Kody-Visitor': value } })
const callsBeforeHeader = calls.length
assert.deepEqual(
	await auth.getUser(visitorReq(JSON.stringify({ userId: 'u2', username: 'outside', role: null }))),
	{ userId: 'u2', username: 'outside', displayName: 'outside', role: 'user' },
)
assert.deepEqual(
	await auth.resolveUser(visitorReq(JSON.stringify({ userId: 'u1', username: 'kent', role: 'owner' }))),
	{ userId: 'u1', username: 'kent', displayName: 'kent', role: 'owner' },
)
assert.equal(calls.length, callsBeforeHeader, 'visitor header → no fetch')
assert.equal(await auth.getUser(visitorReq('not json')), null)
assert.equal(calls.length, callsBeforeHeader, 'malformed header → null, still no fetch')
assert.equal(readPackageAppVisitorHeader(req()), null)

const optional = createPackageAppAuth({ fetch: async () => new Response('x', { status: 500 }) })
assert.equal(optional.mode, 'optional')
assert.equal(await optional.resolveUser(req()), null)
await assert.rejects(() => optional.getUser(req('a=b')), { name: 'PackageAppAuthError', status: 500 })

console.log('smoke-auth ok')