Skip to content
← Public packages

@kentcdodds/audible

Personal Audible library app — browser re-auth, library, wishlist, NAS archive stub.

src/start-auth.ts

72 lines · 2.4 KB · TypeScript
/**
 * Start Amazon OpenID+PKCE browser login for Audible device registration.
 */

import {
	buildOAuthUrl,
	createCodeVerifier,
	shortAuthSessionId,
} from './login.ts'
import { saveAuthSession } from './auth-session.ts'
import { listLocaleCodes } from './locales.ts'

export type StartAuthInput = {
	/** Marketplace country code (default us). */
	locale?: string
	/** Login with Audible username instead of Amazon account (DE/US/UK only). */
	withUsername?: boolean
}

/**
 * Begin browser re-auth: return an Amazon OpenID+PKCE login URL and store the
 * PKCE verifier in packageStorage under authSessionId. Open loginUrl in a
 * browser, sign in (CAPTCHA/2FA in Amazon’s UI), then pass the final maplanding
 * URL to `./complete-auth` (or the package app form).
 *
 * @param input - Optional locale (default us) and withUsername flag
 * @returns loginUrl, authSessionId, and human instructions (no secrets)
 *
 * @example
 * import startAuth from 'kody:@kentcdodds/audible/start-auth'
 *
 * const { loginUrl, authSessionId, instructions } = await startAuth({ locale: 'us' })
 */
export default async function startAuth(input: StartAuthInput = {}) {
	const codeVerifier = createCodeVerifier()
	const authSessionId = shortAuthSessionId()
	const withUsername = Boolean(input.withUsername)
	const { loginUrl, serial, locale } = await buildOAuthUrl({
		locale: input.locale,
		codeVerifier,
		withUsername,
	})

	await saveAuthSession({
		authSessionId,
		codeVerifier,
		locale: locale.countryCode,
		serial,
		withUsername,
		createdAt: new Date().toISOString(),
	})
	const { packageStorage } = await import('kody:runtime')
	await packageStorage().set('auth-session:latest', authSessionId)

	const instructions = [
		`1. Open this URL in a browser and sign in to Amazon/Audible (${locale.countryCode.toUpperCase()} marketplace).`,
		'2. Complete CAPTCHA / 2FA in Amazon’s UI if asked. You may need to enter credentials twice.',
		'3. After login, the browser shows a 404/error page at …/ap/maplanding?… — that is expected.',
		'4. Copy the full address-bar URL and call complete-auth with { redirectUrl, authSessionId } (or paste it in the package app).',
		`5. Auth session ${authSessionId} expires in about 30 minutes.`,
	].join('\n')

	return {
		ok: true as const,
		loginUrl,
		authSessionId,
		locale: locale.countryCode,
		supportedLocales: listLocaleCodes(),
		instructions,
		next: 'complete-auth',
	}
}