@pofsis-nbt/pofsis-auth 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/Documentation.md +143 -143
  2. package/README.md +130 -130
  3. package/dist/PofsisAuth.d.ts +1 -1
  4. package/dist/PofsisAuth.d.ts.map +1 -1
  5. package/dist/PofsisAuthClient-B3YHqgZL.cjs +2 -0
  6. package/dist/PofsisAuthClient-B3YHqgZL.cjs.map +1 -0
  7. package/dist/{PofsisAuthClient-c9BY8iNp.js → PofsisAuthClient-CEw_lL5S.js} +31 -80
  8. package/dist/PofsisAuthClient-CEw_lL5S.js.map +1 -0
  9. package/dist/{PofsisAuthModal-DIzzLJSP.cjs → RequireAuth-CPhXupYh.cjs} +2 -2
  10. package/dist/RequireAuth-CPhXupYh.cjs.map +1 -0
  11. package/dist/{PofsisAuthModal-DGbtRZ4f.js → RequireAuth-DFa8_MR1.js} +6 -98
  12. package/dist/RequireAuth-DFa8_MR1.js.map +1 -0
  13. package/dist/auth/authLaunch.d.ts +1 -2
  14. package/dist/auth/authLaunch.d.ts.map +1 -1
  15. package/dist/auth/config.d.ts.map +1 -1
  16. package/dist/components/index.d.ts +0 -1
  17. package/dist/components/index.d.ts.map +1 -1
  18. package/dist/core/PofsisAuthClient.d.ts +0 -4
  19. package/dist/core/PofsisAuthClient.d.ts.map +1 -1
  20. package/dist/core/popupProtocol.d.ts.map +1 -1
  21. package/dist/core.cjs +1 -1
  22. package/dist/core.js +1 -1
  23. package/dist/elements.cjs +1 -1
  24. package/dist/elements.cjs.map +1 -1
  25. package/dist/elements.js +3 -3
  26. package/dist/elements.js.map +1 -1
  27. package/dist/index.cjs +1 -1
  28. package/dist/index.d.ts +2 -2
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +3 -3
  31. package/dist/pofsis-auth-elements.js +1 -1
  32. package/dist/pofsis-auth-elements.js.map +1 -1
  33. package/dist/react/index.d.ts +2 -2
  34. package/dist/react/index.d.ts.map +1 -1
  35. package/dist/react.cjs +1 -1
  36. package/dist/react.js +2 -2
  37. package/dist/types.d.ts +7 -21
  38. package/dist/types.d.ts.map +1 -1
  39. package/docs/popup-integration.md +162 -178
  40. package/package.json +87 -87
  41. package/dist/PofsisAuthClient-CRYYsJYc.cjs +0 -2
  42. package/dist/PofsisAuthClient-CRYYsJYc.cjs.map +0 -1
  43. package/dist/PofsisAuthClient-c9BY8iNp.js.map +0 -1
  44. package/dist/PofsisAuthModal-DGbtRZ4f.js.map +0 -1
  45. package/dist/PofsisAuthModal-DIzzLJSP.cjs.map +0 -1
  46. package/dist/components/PofsisAuthModal.d.ts +0 -3
  47. package/dist/components/PofsisAuthModal.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PofsisAuthClient-B3YHqgZL.cjs","names":[],"sources":["../src/auth/api.ts","../src/auth/config.ts","../src/auth/authLaunch.ts","../src/core/popupProtocol.ts","../src/auth/pkce.ts","../src/core/PofsisAuthClient.ts"],"sourcesContent":["import type { AccountProfile, OAuthClientConfig, PofsisAuthConfig, TokenResponse } from '../types'\r\n\r\nasync function parseJson<T>(response: Response): Promise<T> {\r\n if (response.status === 204) return null as T\r\n const text = await response.text()\r\n if (!text) return null as T\r\n return JSON.parse(text) as T\r\n}\r\n\r\nasync function request<T>(\r\n config: PofsisAuthConfig,\r\n path: string,\r\n init?: RequestInit,\r\n): Promise<{ status: number; data: T }> {\r\n const response = await fetch(`${config.apiBaseUrl}${path}`, {\r\n credentials: 'include',\r\n ...init,\r\n headers: {\r\n Accept: 'application/json',\r\n ...(init?.body && !(init.body instanceof FormData)\r\n ? { 'Content-Type': 'application/json' }\r\n : {}),\r\n ...init?.headers,\r\n },\r\n })\r\n if (!response.ok) {\r\n const error = new Error(`Auth API ${path} failed (${response.status})`)\r\n ;(error as Error & { status?: number }).status = response.status\r\n throw error\r\n }\r\n return { status: response.status, data: await parseJson<T>(response) }\r\n}\r\n\r\nexport async function fetchOAuthClient(config: PofsisAuthConfig) {\r\n const applicationId = encodeURIComponent(config.applicationId)\r\n const origin = encodeURIComponent(window.location.origin)\r\n const { data } = await request<OAuthClientConfig>(\r\n config,\r\n `/oauth/applications/${applicationId}/client?origin=${origin}`,\r\n )\r\n return data\r\n}\r\n\r\nexport async function exchangeCode(\r\n config: PofsisAuthConfig,\r\n code: string,\r\n verifier: string,\r\n client: Pick<OAuthClientConfig, 'client_id' | 'redirect_uri'>,\r\n) {\r\n const { data } = await request<TokenResponse>(config, '/oauth/token', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n grant_type: 'authorization_code',\r\n client_id: client.client_id,\r\n redirect_uri: client.redirect_uri,\r\n code,\r\n code_verifier: verifier,\r\n }),\r\n })\r\n return data\r\n}\r\n\r\nexport async function refresh(config: PofsisAuthConfig, clientId: string) {\r\n const { data } = await request<TokenResponse | null>(config, '/oauth/token', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n client_id: clientId,\r\n }),\r\n })\r\n return data || null\r\n}\r\n\r\nexport async function checkSession(config: PofsisAuthConfig) {\r\n try {\r\n await request(config, '/auth/session')\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nexport async function signOut(config: PofsisAuthConfig) {\r\n await request(config, '/auth/logout', { method: 'POST' })\r\n}\r\n\r\nexport async function getAccountProfile(config: PofsisAuthConfig, accessToken: string) {\r\n const { data } = await request<AccountProfile>(config, '/auth/profile/me', {\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n })\r\n return data\r\n}\r\n\r\nexport async function updateAccountProfile(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n profile: { firstName?: string | null; lastName?: string | null },\r\n) {\r\n const { data } = await request<AccountProfile>(config, '/auth/profile/me', {\r\n method: 'PATCH',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n body: JSON.stringify(profile),\r\n })\r\n return data\r\n}\r\n\r\nexport async function uploadAccountProfileImage(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n kind: 'profile' | 'cover',\r\n file: File,\r\n) {\r\n const body = new FormData()\r\n body.append('file', file)\r\n const { data } = await request<AccountProfile>(config, `/auth/profile/me/images/${kind}`, {\r\n method: 'POST',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n body,\r\n })\r\n return data\r\n}\r\n\r\nexport async function deleteAccountProfileImage(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n kind: 'profile' | 'cover',\r\n) {\r\n const { data } = await request<AccountProfile>(config, `/auth/profile/me/images/${kind}`, {\r\n method: 'DELETE',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n })\r\n return data\r\n}\r\n","import type { PofsisAuthClientConfig, ResolvedPofsisAuthConfig } from '../types'\r\n\r\nfunction stripTrailingSlash(value: string) {\r\n return value.replace(/\\/$/, '')\r\n}\r\n\r\nexport type ConfigOverrides = Partial<PofsisAuthClientConfig>\r\n\r\n/**\r\n * Validate and normalize explicitly supplied runtime configuration.\r\n */\r\nexport function resolveConfig(overrides: ConfigOverrides = {}): ResolvedPofsisAuthConfig {\r\n const applicationId = overrides.applicationId?.trim()\r\n const apiBaseUrl = overrides.apiBaseUrl?.trim()\r\n const authUrl = overrides.authUrl?.trim()\r\n const scope = overrides.scope?.trim() || 'openid profile email'\r\n const callbackPath = overrides.callbackPath?.trim() || '/auth/callback'\r\n const popup = {\r\n width: overrides.popup?.width ?? 480,\r\n height: overrides.popup?.height ?? 720,\r\n name: overrides.popup?.name?.trim() || 'pofsis-auth',\r\n timeoutMs: overrides.popup?.timeoutMs ?? 300_000,\r\n }\r\n\r\n const missing: string[] = []\r\n if (!applicationId) missing.push('applicationId')\r\n if (!apiBaseUrl) missing.push('apiBaseUrl')\r\n if (!authUrl) missing.push('authUrl')\r\n if (missing.length) {\r\n throw new Error(`@pofsis-nbt/pofsis-auth missing config: ${missing.join(', ')}`)\r\n }\r\n if (!applicationId || !apiBaseUrl || !authUrl) {\r\n throw new Error('@pofsis-nbt/pofsis-auth missing config')\r\n }\r\n if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(applicationId)) {\r\n throw new Error('@pofsis-nbt/pofsis-auth applicationId must be a UUID')\r\n }\r\n if (!callbackPath.startsWith('/') || callbackPath.startsWith('//')) {\r\n throw new Error('@pofsis-nbt/pofsis-auth callbackPath must be application-relative')\r\n }\r\n if (popup.width <= 0 || popup.height <= 0 || popup.timeoutMs <= 0) {\r\n throw new Error('@pofsis-nbt/pofsis-auth popup dimensions and timeout must be positive')\r\n }\r\n\r\n return {\r\n applicationId: applicationId.toLowerCase(),\r\n apiBaseUrl: stripTrailingSlash(apiBaseUrl),\r\n authUrl: stripTrailingSlash(authUrl),\r\n scope,\r\n callbackPath,\r\n popup,\r\n }\r\n}\r\n","import type { AuthLaunchOptions, AuthMethod, AuthScreen } from '../types'\r\n\r\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\r\nconst PHILIPPINE_MOBILE = /^(?:\\+63|63|0)?9\\d{9}$/\r\nconst METHODS = new Set<AuthMethod>(['password', 'passkey', 'otp'])\r\nconst SCREENS = new Set<AuthScreen>(['login', 'signup', 'reset'])\r\nconst MAX_HINT_LENGTH = 320\r\n\r\nfunction normalizeHint(value: unknown, emailOnly = false): string | undefined {\r\n const candidate = typeof value === 'string' ? value.trim() : ''\r\n if (!candidate || candidate.length > MAX_HINT_LENGTH) return undefined\r\n if (EMAIL.test(candidate)) return candidate.toLowerCase()\r\n const compact = candidate.replace(/[\\s()-]/g, '')\r\n if (emailOnly || !PHILIPPINE_MOBILE.test(compact)) return undefined\r\n return `+63${compact.replace(/^(?:\\+63|63|0)/, '')}`\r\n}\r\n\r\nexport function normalizeAuthLaunchOptions(\r\n value?: AuthLaunchOptions | string | null,\r\n defaultScreen: AuthScreen = 'login',\r\n) {\r\n const options = typeof value === 'string' ? { returnUrl: value } : value || {}\r\n const requestedScreen = options.screen === 'register' ? 'signup' : options.screen\r\n const screen = SCREENS.has(requestedScreen as AuthScreen)\r\n ? (requestedScreen as AuthScreen)\r\n : defaultScreen\r\n const requestedMethod = METHODS.has(options.method as AuthMethod)\r\n ? (options.method as AuthMethod)\r\n : undefined\r\n const method =\r\n screen === 'login' ||\r\n (screen === 'signup' && (requestedMethod === 'password' || requestedMethod === 'otp'))\r\n ? requestedMethod\r\n : undefined\r\n return {\r\n returnUrl: options.returnUrl,\r\n screen,\r\n loginHint: normalizeHint(options.loginHint),\r\n method,\r\n }\r\n}\r\n\r\nexport function authLaunchOptionsFromSearch(search: string) {\r\n const params = new URLSearchParams(search)\r\n const canonicalHint = params.get('login_hint')\r\n const loginHint =\r\n canonicalHint !== null\r\n ? normalizeHint(canonicalHint)\r\n : normalizeHint(params.get('email'), true)\r\n return normalizeAuthLaunchOptions({\r\n screen: (params.get('screen') || undefined) as AuthLaunchOptions['screen'],\r\n loginHint,\r\n method: (params.get('method') || undefined) as AuthLaunchOptions['method'],\r\n })\r\n}\r\n\r\nexport function buildAuthDestination({\r\n authUrl,\r\n query,\r\n options,\r\n}: {\r\n authUrl: string\r\n query: URLSearchParams\r\n options?: AuthLaunchOptions\r\n}) {\r\n const launch = normalizeAuthLaunchOptions(options)\r\n const authorizationUrl = new URL(authUrl)\r\n authorizationUrl.search = query.toString()\r\n if (launch.loginHint) authorizationUrl.searchParams.set('login_hint', launch.loginHint)\r\n if (launch.screen === 'login' && launch.method) {\r\n authorizationUrl.searchParams.set('method', launch.method)\r\n }\r\n if (launch.screen === 'login') return authorizationUrl.toString()\r\n\r\n const pathname = launch.screen === 'signup' ? '/signup' : '/forgot-password'\r\n const destination = new URL(pathname, authorizationUrl)\r\n const clientId = query.get('client_id')\r\n if (clientId) destination.searchParams.set('client_id', clientId)\r\n destination.searchParams.set(\r\n 'return_to',\r\n `${authorizationUrl.pathname}${authorizationUrl.search}`,\r\n )\r\n if (launch.loginHint) destination.searchParams.set('login_hint', launch.loginHint)\r\n if (launch.screen === 'signup') {\r\n destination.searchParams.set('method', launch.method || 'password')\r\n }\r\n return destination.toString()\r\n}\r\n","export const POPUP_MESSAGE_TYPE = 'pofsis-auth:callback'\r\n\r\nexport type PopupCallbackMessage = {\r\n type: typeof POPUP_MESSAGE_TYPE\r\n code?: string\r\n state?: string\r\n error?: string\r\n correlationId?: string\r\n}\r\n\r\nexport function correlationFromState(state: string | null) {\r\n if (!state) return undefined\r\n const separator = state.indexOf('.')\r\n return separator > 0 ? state.slice(0, separator) : undefined\r\n}\r\n\r\nexport function relayPopupCallback(targetOrigin = window.location.origin) {\r\n if (!window.opener || window.opener.closed) return false\r\n const params = new URLSearchParams(window.location.search)\r\n const state = params.get('state') || undefined\r\n const message: PopupCallbackMessage = {\r\n type: POPUP_MESSAGE_TYPE,\r\n code: params.get('code') || undefined,\r\n state,\r\n error: params.get('error') || undefined,\r\n correlationId: correlationFromState(state || null),\r\n }\r\n window.opener.postMessage(message, targetOrigin)\r\n window.close()\r\n return true\r\n}\r\n","const encode = (bytes: Uint8Array) =>\r\n btoa(String.fromCharCode(...bytes))\r\n .replace(/\\+/g, '-')\r\n .replace(/\\//g, '_')\r\n .replace(/=+$/, '')\r\n\r\nexport const randomValue = () => encode(crypto.getRandomValues(new Uint8Array(32)))\r\n\r\nexport async function pkceChallenge(verifier: string) {\r\n return encode(\r\n new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))),\r\n )\r\n}\r\n","import { checkSession, exchangeCode, fetchOAuthClient, refresh, signOut } from '../auth/api'\r\nimport { buildAuthDestination, normalizeAuthLaunchOptions } from '../auth/authLaunch'\r\nimport { resolveConfig } from '../auth/config'\r\nimport { pkceChallenge, randomValue } from '../auth/pkce'\r\nimport type {\r\n AuthLaunchOptions,\r\n AuthResult,\r\n OAuthClientConfig,\r\n PofsisAuthClientConfig,\r\n ResolvedPofsisAuthConfig,\r\n PofsisUser,\r\n SessionPayload,\r\n} from '../types'\r\nimport {\r\n correlationFromState,\r\n POPUP_MESSAGE_TYPE,\r\n type PopupCallbackMessage,\r\n} from './popupProtocol'\r\n\r\ntype Subscriber = (session: SessionPayload | null) => void\r\ntype PopupAttempt = {\r\n popup: Window\r\n state: string\r\n verifier: string\r\n correlationId: string\r\n returnUrl?: string\r\n resolve: (result: AuthResult) => void\r\n reject: (error: Error) => void\r\n timer: ReturnType<typeof setInterval>\r\n timeout: ReturnType<typeof setTimeout>\r\n}\r\n\r\nconst safeLocalPath = (value?: string) =>\r\n value?.startsWith('/') && !value.startsWith('//') ? value : undefined\r\n\r\nconst toSession = (result: { token_type: string; expires_in: number; user: PofsisUser }) => ({\r\n token_type: result.token_type,\r\n expires_in: result.expires_in,\r\n user: result.user,\r\n})\r\n\r\nexport class PofsisAuthClient {\r\n readonly config: ResolvedPofsisAuthConfig\r\n private token: string | null = null\r\n private session: SessionPayload | null = null\r\n private client: OAuthClientConfig | null = null\r\n private clientPromise: Promise<OAuthClientConfig> | null = null\r\n private refreshPromise: Promise<void> | null = null\r\n private subscribers = new Set<Subscriber>()\r\n private attempt: PopupAttempt | null = null\r\n private listening = false\r\n\r\n constructor(config: PofsisAuthClientConfig) {\r\n this.config = resolveConfig(config)\r\n this.attach()\r\n }\r\n\r\n private attach() {\r\n if (this.listening) return\r\n window.addEventListener('message', this.onPopupMessage)\r\n this.listening = true\r\n }\r\n\r\n destroy() {\r\n window.removeEventListener('message', this.onPopupMessage)\r\n this.listening = false\r\n const attempt = this.finishAttempt()\r\n if (attempt) {\r\n attempt.popup.close()\r\n attempt.resolve({ status: 'cancelled' })\r\n }\r\n this.subscribers.clear()\r\n }\r\n\r\n getUser() {\r\n return this.session?.user ?? null\r\n }\r\n\r\n getSession() {\r\n return this.session\r\n }\r\n\r\n getAccessToken() {\r\n return this.token\r\n }\r\n\r\n subscribe(listener: Subscriber) {\r\n this.attach()\r\n this.subscribers.add(listener)\r\n listener(this.session)\r\n return () => {\r\n this.subscribers.delete(listener)\r\n }\r\n }\r\n\r\n private emit() {\r\n for (const listener of this.subscribers) listener(this.session)\r\n }\r\n\r\n private accept(result: Awaited<ReturnType<typeof exchangeCode>>) {\r\n this.token = result.access_token\r\n this.session = toSession(result)\r\n this.emit()\r\n }\r\n\r\n private loadClient() {\r\n if (!this.clientPromise) {\r\n this.clientPromise = fetchOAuthClient(this.config)\r\n .then((client) => (this.client = client))\r\n .catch((error) => {\r\n this.clientPromise = null\r\n throw error\r\n })\r\n }\r\n return this.clientPromise\r\n }\r\n\r\n getOAuthClient() {\r\n return this.loadClient()\r\n }\r\n\r\n async refreshSession() {\r\n const client = await this.loadClient()\r\n if (!this.refreshPromise) {\r\n this.refreshPromise = refresh(this.config, client.client_id)\r\n .then((result) => {\r\n if (result) this.accept(result)\r\n else this.clearSession()\r\n })\r\n .finally(() => (this.refreshPromise = null))\r\n }\r\n return this.refreshPromise\r\n }\r\n\r\n async isRemoteSessionActive() {\r\n return checkSession(this.config)\r\n }\r\n\r\n clearSession() {\r\n this.token = null\r\n this.session = null\r\n this.emit()\r\n }\r\n\r\n replaceUser(user: PofsisUser) {\r\n if (!this.session) return\r\n this.session = { ...this.session, user }\r\n this.emit()\r\n }\r\n\r\n async logout() {\r\n try {\r\n await signOut(this.config)\r\n } finally {\r\n this.clearSession()\r\n }\r\n }\r\n\r\n signup(options: Omit<AuthLaunchOptions, 'screen'> = {}) {\r\n return this.login({ ...options, screen: 'signup' })\r\n }\r\n\r\n resetPassword(options: Omit<AuthLaunchOptions, 'screen'> = {}) {\r\n return this.login({ ...options, screen: 'reset' })\r\n }\r\n\r\n async login(options: AuthLaunchOptions = {}): Promise<AuthResult> {\r\n const launch = normalizeAuthLaunchOptions(options)\r\n const presentation = options.presentation ?? 'popup'\r\n if (presentation === 'popup') return this.openPopup({ ...options, ...launch })\r\n return this.startRedirect({ ...options, ...launch })\r\n }\r\n\r\n private async authorizationUrl(options: AuthLaunchOptions, state: string, verifier: string) {\r\n const client = await this.loadClient()\r\n const query = new URLSearchParams({\r\n client_id: client.client_id,\r\n redirect_uri: client.redirect_uri,\r\n response_type: 'code',\r\n scope: this.config.scope,\r\n state,\r\n code_challenge: await pkceChallenge(verifier),\r\n code_challenge_method: 'S256',\r\n })\r\n return buildAuthDestination({\r\n authUrl: this.config.authUrl,\r\n query,\r\n options,\r\n })\r\n }\r\n\r\n private storageKey(suffix: string) {\r\n return `${this.config.applicationId}.auth.${suffix}`\r\n }\r\n\r\n private async startRedirect(options: AuthLaunchOptions): Promise<AuthResult> {\r\n const state = randomValue()\r\n const verifier = randomValue()\r\n sessionStorage.setItem(this.storageKey('state'), state)\r\n sessionStorage.setItem(this.storageKey('verifier'), verifier)\r\n const returnUrl = safeLocalPath(options.returnUrl)\r\n if (returnUrl) sessionStorage.setItem(this.storageKey('return-path'), returnUrl)\r\n else sessionStorage.removeItem(this.storageKey('return-path'))\r\n window.location.assign(await this.authorizationUrl(options, state, verifier))\r\n return { status: 'redirecting' }\r\n }\r\n\r\n private async openPopup(options: AuthLaunchOptions): Promise<AuthResult> {\r\n if (this.attempt && !this.attempt.popup.closed) {\r\n this.attempt.popup.focus()\r\n return new Promise((resolve, reject) => {\r\n const current = this.attempt!\r\n const originalResolve = current.resolve\r\n const originalReject = current.reject\r\n current.resolve = (value) => {\r\n originalResolve(value)\r\n resolve(value)\r\n }\r\n current.reject = (error) => {\r\n originalReject(error)\r\n reject(error)\r\n }\r\n })\r\n }\r\n const { width, height, name, timeoutMs } = this.config.popup\r\n const left = Math.max(0, window.screenX + (window.outerWidth - width) / 2)\r\n const top = Math.max(0, window.screenY + (window.outerHeight - height) / 2)\r\n const popup = window.open(\r\n 'about:blank',\r\n name,\r\n `popup=yes,width=${width},height=${height},left=${Math.round(left)},top=${Math.round(top)}`,\r\n )\r\n if (!popup) return this.startRedirect({ ...options, presentation: 'redirect' })\r\n\r\n const correlationId = randomValue()\r\n const state = `${correlationId}.${randomValue()}`\r\n const verifier = randomValue()\r\n const returnUrl = safeLocalPath(options.returnUrl)\r\n return new Promise<AuthResult>((resolve, reject) => {\r\n const timer = setInterval(() => {\r\n if (!popup.closed) return\r\n const attempt = this.finishAttempt()\r\n attempt?.resolve({ status: 'cancelled' })\r\n }, 250)\r\n const timeout = setTimeout(() => {\r\n const attempt = this.finishAttempt()\r\n popup.close()\r\n attempt?.reject(new Error('POFSIS Auth popup timed out.'))\r\n }, timeoutMs)\r\n this.attempt = {\r\n popup,\r\n state,\r\n verifier,\r\n correlationId,\r\n returnUrl,\r\n resolve,\r\n reject,\r\n timer,\r\n timeout,\r\n }\r\n void this.authorizationUrl(options, state, verifier)\r\n .then((url) => popup.location.replace(url))\r\n .catch((error) => {\r\n const attempt = this.finishAttempt()\r\n popup.close()\r\n attempt?.reject(error instanceof Error ? error : new Error(String(error)))\r\n })\r\n })\r\n }\r\n\r\n private finishAttempt() {\r\n const attempt = this.attempt\r\n if (!attempt) return null\r\n clearInterval(attempt.timer)\r\n clearTimeout(attempt.timeout)\r\n this.attempt = null\r\n return attempt\r\n }\r\n\r\n private onPopupMessage = (event: MessageEvent<PopupCallbackMessage>) => {\r\n const attempt = this.attempt\r\n const message = event.data\r\n if (\r\n !attempt ||\r\n event.origin !== window.location.origin ||\r\n event.source !== attempt.popup ||\r\n message?.type !== POPUP_MESSAGE_TYPE ||\r\n message.correlationId !== attempt.correlationId ||\r\n correlationFromState(message.state || null) !== attempt.correlationId ||\r\n message.state !== attempt.state\r\n )\r\n return\r\n\r\n const completed = this.finishAttempt()\r\n if (!completed) return\r\n if (message.error || !message.code) {\r\n completed.popup.close()\r\n completed.reject(new Error(message.error || 'POFSIS Auth callback was incomplete.'))\r\n return\r\n }\r\n void this.completeCode(message.code, message.state, completed.verifier)\r\n .then(() => {\r\n completed.popup.close()\r\n if (completed.returnUrl) window.history.replaceState(null, '', completed.returnUrl)\r\n completed.resolve({ status: 'authenticated', user: this.getUser()! })\r\n })\r\n .catch((error) => {\r\n completed.popup.close()\r\n completed.reject(error instanceof Error ? error : new Error(String(error)))\r\n })\r\n }\r\n\r\n private async completeCode(code: string, state: string, verifier: string) {\r\n if (!state || !verifier) throw new Error('Authentication state could not be verified.')\r\n const client = await this.loadClient()\r\n this.accept(await exchangeCode(this.config, code, verifier, client))\r\n }\r\n\r\n async completeRedirectCallback(code: string, state: string) {\r\n const expected = sessionStorage.getItem(this.storageKey('state'))\r\n const verifier = sessionStorage.getItem(this.storageKey('verifier'))\r\n sessionStorage.removeItem(this.storageKey('state'))\r\n sessionStorage.removeItem(this.storageKey('verifier'))\r\n if (!expected || !verifier || state !== expected) {\r\n throw new Error('Authentication state could not be verified.')\r\n }\r\n await this.completeCode(code, state, verifier)\r\n }\r\n}\r\n\r\nexport function createPofsisAuth(config: PofsisAuthClientConfig) {\r\n return new PofsisAuthClient(config)\r\n}\r\n"],"mappings":"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"}
@@ -24,7 +24,7 @@ async function t(t, n, r) {
24
24
  };
25
25
  }
26
26
  async function n(e) {
27
- let { data: n } = await t(e, `/oauth/clients/${encodeURIComponent(e.appName.toUpperCase())}?origin=${encodeURIComponent(window.location.origin)}`);
27
+ let { data: n } = await t(e, `/oauth/applications/${encodeURIComponent(e.applicationId)}/client?origin=${encodeURIComponent(window.location.origin)}`);
28
28
  return n;
29
29
  }
30
30
  async function r(e, n, r, i) {
@@ -95,18 +95,19 @@ function d(e) {
95
95
  return e.replace(/\/$/, "");
96
96
  }
97
97
  function f(e = {}) {
98
- let t = e.appName?.trim(), n = e.apiBaseUrl?.trim(), r = e.authUrl?.trim(), i = e.scope?.trim() || "openid profile email", a = e.callbackPath?.trim() || "/auth/callback", o = {
98
+ let t = e.applicationId?.trim(), n = e.apiBaseUrl?.trim(), r = e.authUrl?.trim(), i = e.scope?.trim() || "openid profile email", a = e.callbackPath?.trim() || "/auth/callback", o = {
99
99
  width: e.popup?.width ?? 480,
100
100
  height: e.popup?.height ?? 720,
101
101
  name: e.popup?.name?.trim() || "pofsis-auth",
102
102
  timeoutMs: e.popup?.timeoutMs ?? 3e5
103
103
  }, s = [];
104
- if (t || s.push("appName"), n || s.push("apiBaseUrl"), r || s.push("authUrl"), s.length) throw Error(`@pofsis-nbt/pofsis-auth missing config: ${s.join(", ")}`);
104
+ if (t || s.push("applicationId"), n || s.push("apiBaseUrl"), r || s.push("authUrl"), s.length) throw Error(`@pofsis-nbt/pofsis-auth missing config: ${s.join(", ")}`);
105
105
  if (!t || !n || !r) throw Error("@pofsis-nbt/pofsis-auth missing config");
106
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(t)) throw Error("@pofsis-nbt/pofsis-auth applicationId must be a UUID");
106
107
  if (!a.startsWith("/") || a.startsWith("//")) throw Error("@pofsis-nbt/pofsis-auth callbackPath must be application-relative");
107
108
  if (o.width <= 0 || o.height <= 0 || o.timeoutMs <= 0) throw Error("@pofsis-nbt/pofsis-auth popup dimensions and timeout must be positive");
108
109
  return {
109
- appName: t,
110
+ applicationId: t.toLowerCase(),
110
111
  apiBaseUrl: d(n),
111
112
  authUrl: d(r),
112
113
  scope: i,
@@ -149,11 +150,11 @@ function b(e) {
149
150
  method: t.get("method") || void 0
150
151
  });
151
152
  }
152
- function x({ authUrl: e, appName: t, query: n, options: r }) {
153
- let i = y(r), a = new URL(e);
154
- if (a.search = n.toString(), i.loginHint && a.searchParams.set("login_hint", i.loginHint), i.screen === "login" && i.method && a.searchParams.set("method", i.method), i.screen === "login") return a.toString();
155
- let o = i.screen === "signup" ? "/signup" : "/forgot-password", s = new URL(o, a);
156
- return s.searchParams.set("app", t), s.searchParams.set("return_to", `${a.pathname}${a.search}`), i.loginHint && s.searchParams.set("login_hint", i.loginHint), i.screen === "signup" && s.searchParams.set("method", i.method || "password"), s.toString();
153
+ function x({ authUrl: e, query: t, options: n }) {
154
+ let r = y(n), i = new URL(e);
155
+ if (i.search = t.toString(), r.loginHint && i.searchParams.set("login_hint", r.loginHint), r.screen === "login" && r.method && i.searchParams.set("method", r.method), r.screen === "login") return i.toString();
156
+ let a = r.screen === "signup" ? "/signup" : "/forgot-password", o = new URL(a, i), s = t.get("client_id");
157
+ return s && o.searchParams.set("client_id", s), o.searchParams.set("return_to", `${i.pathname}${i.search}`), r.loginHint && o.searchParams.set("login_hint", r.loginHint), r.screen === "signup" && o.searchParams.set("method", r.method || "password"), o.toString();
157
158
  }
158
159
  //#endregion
159
160
  //#region src/core/popupProtocol.ts
@@ -164,16 +165,15 @@ function C(e) {
164
165
  return t > 0 ? e.slice(0, t) : void 0;
165
166
  }
166
167
  function w(e = window.location.origin) {
167
- let t = window.opener && !window.opener.closed ? window.opener : window.parent === window ? null : window.parent;
168
- if (!t) return !1;
169
- let n = new URLSearchParams(window.location.search), r = n.get("state") || void 0, i = {
168
+ if (!window.opener || window.opener.closed) return !1;
169
+ let t = new URLSearchParams(window.location.search), n = t.get("state") || void 0, r = {
170
170
  type: S,
171
- code: n.get("code") || void 0,
172
- state: r,
173
- error: n.get("error") || void 0,
174
- correlationId: C(r || null)
171
+ code: t.get("code") || void 0,
172
+ state: n,
173
+ error: t.get("error") || void 0,
174
+ correlationId: C(n || null)
175
175
  };
176
- return t.postMessage(i, e), t === window.opener && window.close(), !0;
176
+ return window.opener.postMessage(r, e), window.close(), !0;
177
177
  }
178
178
  //#endregion
179
179
  //#region src/auth/pkce.ts
@@ -196,7 +196,6 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
196
196
  refreshPromise = null;
197
197
  subscribers = /* @__PURE__ */ new Set();
198
198
  attempt = null;
199
- iframeAttempt = null;
200
199
  listening = !1;
201
200
  constructor(e) {
202
201
  this.config = f(e), this.attach();
@@ -207,7 +206,7 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
207
206
  destroy() {
208
207
  window.removeEventListener("message", this.onPopupMessage), this.listening = !1;
209
208
  let e = this.finishAttempt();
210
- e && (e.popup.close(), e.resolve({ status: "cancelled" })), this.cancelIframeLogin(), this.subscribers.clear();
209
+ e && (e.popup.close(), e.resolve({ status: "cancelled" })), this.subscribers.clear();
211
210
  }
212
211
  getUser() {
213
212
  return this.session?.user ?? null;
@@ -275,11 +274,8 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
275
274
  });
276
275
  }
277
276
  async login(e = {}) {
278
- let t = y(e), n = e.presentation ?? "popup";
279
- return n === "popup" ? this.openPopup({
280
- ...e,
281
- ...t
282
- }) : n === "iframe" ? this.openIframe({
277
+ let t = y(e);
278
+ return (e.presentation ?? "popup") === "popup" ? this.openPopup({
283
279
  ...e,
284
280
  ...t
285
281
  }) : this.startRedirect({
@@ -287,35 +283,8 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
287
283
  ...t
288
284
  });
289
285
  }
290
- cancelIframeLogin() {
291
- this.finishIframeAttempt()?.resolve({ status: "cancelled" });
292
- }
293
- openIframe(e) {
294
- let t = e.target;
295
- if (!t) return Promise.reject(/* @__PURE__ */ Error("POFSIS Auth iframe target is required."));
296
- this.cancelIframeLogin();
297
- let n = E(), r = `${n}.${E()}`, i = E(), a = O(e.returnUrl);
298
- return new Promise((o, s) => {
299
- let c = setTimeout(() => {
300
- this.finishIframeAttempt()?.reject(/* @__PURE__ */ Error("POFSIS Auth iframe timed out."));
301
- }, this.config.popup.timeoutMs);
302
- this.iframeAttempt = {
303
- frame: t,
304
- state: r,
305
- verifier: i,
306
- correlationId: n,
307
- returnUrl: a,
308
- resolve: o,
309
- reject: s,
310
- timeout: c
311
- }, this.authorizationUrl(e, r, i).then((e) => t.contentWindow?.location.replace(e)).catch((e) => {
312
- this.finishIframeAttempt()?.reject(e instanceof Error ? e : Error(String(e)));
313
- });
314
- });
315
- }
316
286
  async authorizationUrl(e, t, n) {
317
287
  let r = await this.loadClient(), i = new URLSearchParams({
318
- app: this.config.appName.toUpperCase(),
319
288
  client_id: r.client_id,
320
289
  redirect_uri: r.redirect_uri,
321
290
  response_type: "code",
@@ -326,13 +295,12 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
326
295
  });
327
296
  return x({
328
297
  authUrl: this.config.authUrl,
329
- appName: this.config.appName.toUpperCase(),
330
298
  query: i,
331
299
  options: e
332
300
  });
333
301
  }
334
302
  storageKey(e) {
335
- return `${this.config.appName.toLowerCase()}.auth.${e}`;
303
+ return `${this.config.applicationId}.auth.${e}`;
336
304
  }
337
305
  async startRedirect(e) {
338
306
  let t = E(), n = E();
@@ -382,39 +350,22 @@ var O = (e) => e?.startsWith("/") && !e.startsWith("//") ? e : void 0, k = (e) =
382
350
  let e = this.attempt;
383
351
  return e ? (clearInterval(e.timer), clearTimeout(e.timeout), this.attempt = null, e) : null;
384
352
  }
385
- finishIframeAttempt() {
386
- let e = this.iframeAttempt;
387
- return e ? (clearTimeout(e.timeout), this.iframeAttempt = null, e) : null;
388
- }
389
353
  onPopupMessage = (e) => {
390
- let t = this.iframeAttempt;
391
- if (t && e.origin === window.location.origin && e.source === t.frame.contentWindow && e.data?.type === "pofsis-auth:callback" && e.data.correlationId === t.correlationId && C(e.data.state || null) === t.correlationId && e.data.state === t.state) {
392
- let t = this.finishIframeAttempt();
393
- if (e.data.error || !e.data.code) {
394
- t.reject(Error(e.data.error || "POFSIS Auth callback was incomplete."));
395
- return;
396
- }
397
- this.completeCode(e.data.code, e.data.state, t.verifier).then(() => t.resolve({
398
- status: "authenticated",
399
- user: this.getUser()
400
- })).catch((e) => t.reject(e instanceof Error ? e : Error(String(e))));
401
- return;
402
- }
403
- let n = this.attempt, r = e.data;
404
- if (!n || e.origin !== window.location.origin || e.source !== n.popup || r?.type !== "pofsis-auth:callback" || r.correlationId !== n.correlationId || C(r.state || null) !== n.correlationId || r.state !== n.state) return;
405
- let i = this.finishAttempt();
406
- if (i) {
407
- if (r.error || !r.code) {
408
- i.popup.close(), i.reject(Error(r.error || "POFSIS Auth callback was incomplete."));
354
+ let t = this.attempt, n = e.data;
355
+ if (!t || e.origin !== window.location.origin || e.source !== t.popup || n?.type !== "pofsis-auth:callback" || n.correlationId !== t.correlationId || C(n.state || null) !== t.correlationId || n.state !== t.state) return;
356
+ let r = this.finishAttempt();
357
+ if (r) {
358
+ if (n.error || !n.code) {
359
+ r.popup.close(), r.reject(Error(n.error || "POFSIS Auth callback was incomplete."));
409
360
  return;
410
361
  }
411
- this.completeCode(r.code, r.state, i.verifier).then(() => {
412
- i.popup.close(), i.returnUrl && window.history.replaceState(null, "", i.returnUrl), i.resolve({
362
+ this.completeCode(n.code, n.state, r.verifier).then(() => {
363
+ r.popup.close(), r.returnUrl && window.history.replaceState(null, "", r.returnUrl), r.resolve({
413
364
  status: "authenticated",
414
365
  user: this.getUser()
415
366
  });
416
367
  }).catch((e) => {
417
- i.popup.close(), i.reject(e instanceof Error ? e : Error(String(e)));
368
+ r.popup.close(), r.reject(e instanceof Error ? e : Error(String(e)));
418
369
  });
419
370
  }
420
371
  };
@@ -435,4 +386,4 @@ function j(e) {
435
386
  //#endregion
436
387
  export { f as a, c, b as i, l, j as n, u as o, w as r, s, A as t };
437
388
 
438
- //# sourceMappingURL=PofsisAuthClient-c9BY8iNp.js.map
389
+ //# sourceMappingURL=PofsisAuthClient-CEw_lL5S.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PofsisAuthClient-CEw_lL5S.js","names":[],"sources":["../src/auth/api.ts","../src/auth/config.ts","../src/auth/authLaunch.ts","../src/core/popupProtocol.ts","../src/auth/pkce.ts","../src/core/PofsisAuthClient.ts"],"sourcesContent":["import type { AccountProfile, OAuthClientConfig, PofsisAuthConfig, TokenResponse } from '../types'\r\n\r\nasync function parseJson<T>(response: Response): Promise<T> {\r\n if (response.status === 204) return null as T\r\n const text = await response.text()\r\n if (!text) return null as T\r\n return JSON.parse(text) as T\r\n}\r\n\r\nasync function request<T>(\r\n config: PofsisAuthConfig,\r\n path: string,\r\n init?: RequestInit,\r\n): Promise<{ status: number; data: T }> {\r\n const response = await fetch(`${config.apiBaseUrl}${path}`, {\r\n credentials: 'include',\r\n ...init,\r\n headers: {\r\n Accept: 'application/json',\r\n ...(init?.body && !(init.body instanceof FormData)\r\n ? { 'Content-Type': 'application/json' }\r\n : {}),\r\n ...init?.headers,\r\n },\r\n })\r\n if (!response.ok) {\r\n const error = new Error(`Auth API ${path} failed (${response.status})`)\r\n ;(error as Error & { status?: number }).status = response.status\r\n throw error\r\n }\r\n return { status: response.status, data: await parseJson<T>(response) }\r\n}\r\n\r\nexport async function fetchOAuthClient(config: PofsisAuthConfig) {\r\n const applicationId = encodeURIComponent(config.applicationId)\r\n const origin = encodeURIComponent(window.location.origin)\r\n const { data } = await request<OAuthClientConfig>(\r\n config,\r\n `/oauth/applications/${applicationId}/client?origin=${origin}`,\r\n )\r\n return data\r\n}\r\n\r\nexport async function exchangeCode(\r\n config: PofsisAuthConfig,\r\n code: string,\r\n verifier: string,\r\n client: Pick<OAuthClientConfig, 'client_id' | 'redirect_uri'>,\r\n) {\r\n const { data } = await request<TokenResponse>(config, '/oauth/token', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n grant_type: 'authorization_code',\r\n client_id: client.client_id,\r\n redirect_uri: client.redirect_uri,\r\n code,\r\n code_verifier: verifier,\r\n }),\r\n })\r\n return data\r\n}\r\n\r\nexport async function refresh(config: PofsisAuthConfig, clientId: string) {\r\n const { data } = await request<TokenResponse | null>(config, '/oauth/token', {\r\n method: 'POST',\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n client_id: clientId,\r\n }),\r\n })\r\n return data || null\r\n}\r\n\r\nexport async function checkSession(config: PofsisAuthConfig) {\r\n try {\r\n await request(config, '/auth/session')\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nexport async function signOut(config: PofsisAuthConfig) {\r\n await request(config, '/auth/logout', { method: 'POST' })\r\n}\r\n\r\nexport async function getAccountProfile(config: PofsisAuthConfig, accessToken: string) {\r\n const { data } = await request<AccountProfile>(config, '/auth/profile/me', {\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n })\r\n return data\r\n}\r\n\r\nexport async function updateAccountProfile(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n profile: { firstName?: string | null; lastName?: string | null },\r\n) {\r\n const { data } = await request<AccountProfile>(config, '/auth/profile/me', {\r\n method: 'PATCH',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n body: JSON.stringify(profile),\r\n })\r\n return data\r\n}\r\n\r\nexport async function uploadAccountProfileImage(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n kind: 'profile' | 'cover',\r\n file: File,\r\n) {\r\n const body = new FormData()\r\n body.append('file', file)\r\n const { data } = await request<AccountProfile>(config, `/auth/profile/me/images/${kind}`, {\r\n method: 'POST',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n body,\r\n })\r\n return data\r\n}\r\n\r\nexport async function deleteAccountProfileImage(\r\n config: PofsisAuthConfig,\r\n accessToken: string,\r\n kind: 'profile' | 'cover',\r\n) {\r\n const { data } = await request<AccountProfile>(config, `/auth/profile/me/images/${kind}`, {\r\n method: 'DELETE',\r\n headers: { Authorization: `Bearer ${accessToken}` },\r\n })\r\n return data\r\n}\r\n","import type { PofsisAuthClientConfig, ResolvedPofsisAuthConfig } from '../types'\r\n\r\nfunction stripTrailingSlash(value: string) {\r\n return value.replace(/\\/$/, '')\r\n}\r\n\r\nexport type ConfigOverrides = Partial<PofsisAuthClientConfig>\r\n\r\n/**\r\n * Validate and normalize explicitly supplied runtime configuration.\r\n */\r\nexport function resolveConfig(overrides: ConfigOverrides = {}): ResolvedPofsisAuthConfig {\r\n const applicationId = overrides.applicationId?.trim()\r\n const apiBaseUrl = overrides.apiBaseUrl?.trim()\r\n const authUrl = overrides.authUrl?.trim()\r\n const scope = overrides.scope?.trim() || 'openid profile email'\r\n const callbackPath = overrides.callbackPath?.trim() || '/auth/callback'\r\n const popup = {\r\n width: overrides.popup?.width ?? 480,\r\n height: overrides.popup?.height ?? 720,\r\n name: overrides.popup?.name?.trim() || 'pofsis-auth',\r\n timeoutMs: overrides.popup?.timeoutMs ?? 300_000,\r\n }\r\n\r\n const missing: string[] = []\r\n if (!applicationId) missing.push('applicationId')\r\n if (!apiBaseUrl) missing.push('apiBaseUrl')\r\n if (!authUrl) missing.push('authUrl')\r\n if (missing.length) {\r\n throw new Error(`@pofsis-nbt/pofsis-auth missing config: ${missing.join(', ')}`)\r\n }\r\n if (!applicationId || !apiBaseUrl || !authUrl) {\r\n throw new Error('@pofsis-nbt/pofsis-auth missing config')\r\n }\r\n if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(applicationId)) {\r\n throw new Error('@pofsis-nbt/pofsis-auth applicationId must be a UUID')\r\n }\r\n if (!callbackPath.startsWith('/') || callbackPath.startsWith('//')) {\r\n throw new Error('@pofsis-nbt/pofsis-auth callbackPath must be application-relative')\r\n }\r\n if (popup.width <= 0 || popup.height <= 0 || popup.timeoutMs <= 0) {\r\n throw new Error('@pofsis-nbt/pofsis-auth popup dimensions and timeout must be positive')\r\n }\r\n\r\n return {\r\n applicationId: applicationId.toLowerCase(),\r\n apiBaseUrl: stripTrailingSlash(apiBaseUrl),\r\n authUrl: stripTrailingSlash(authUrl),\r\n scope,\r\n callbackPath,\r\n popup,\r\n }\r\n}\r\n","import type { AuthLaunchOptions, AuthMethod, AuthScreen } from '../types'\r\n\r\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\r\nconst PHILIPPINE_MOBILE = /^(?:\\+63|63|0)?9\\d{9}$/\r\nconst METHODS = new Set<AuthMethod>(['password', 'passkey', 'otp'])\r\nconst SCREENS = new Set<AuthScreen>(['login', 'signup', 'reset'])\r\nconst MAX_HINT_LENGTH = 320\r\n\r\nfunction normalizeHint(value: unknown, emailOnly = false): string | undefined {\r\n const candidate = typeof value === 'string' ? value.trim() : ''\r\n if (!candidate || candidate.length > MAX_HINT_LENGTH) return undefined\r\n if (EMAIL.test(candidate)) return candidate.toLowerCase()\r\n const compact = candidate.replace(/[\\s()-]/g, '')\r\n if (emailOnly || !PHILIPPINE_MOBILE.test(compact)) return undefined\r\n return `+63${compact.replace(/^(?:\\+63|63|0)/, '')}`\r\n}\r\n\r\nexport function normalizeAuthLaunchOptions(\r\n value?: AuthLaunchOptions | string | null,\r\n defaultScreen: AuthScreen = 'login',\r\n) {\r\n const options = typeof value === 'string' ? { returnUrl: value } : value || {}\r\n const requestedScreen = options.screen === 'register' ? 'signup' : options.screen\r\n const screen = SCREENS.has(requestedScreen as AuthScreen)\r\n ? (requestedScreen as AuthScreen)\r\n : defaultScreen\r\n const requestedMethod = METHODS.has(options.method as AuthMethod)\r\n ? (options.method as AuthMethod)\r\n : undefined\r\n const method =\r\n screen === 'login' ||\r\n (screen === 'signup' && (requestedMethod === 'password' || requestedMethod === 'otp'))\r\n ? requestedMethod\r\n : undefined\r\n return {\r\n returnUrl: options.returnUrl,\r\n screen,\r\n loginHint: normalizeHint(options.loginHint),\r\n method,\r\n }\r\n}\r\n\r\nexport function authLaunchOptionsFromSearch(search: string) {\r\n const params = new URLSearchParams(search)\r\n const canonicalHint = params.get('login_hint')\r\n const loginHint =\r\n canonicalHint !== null\r\n ? normalizeHint(canonicalHint)\r\n : normalizeHint(params.get('email'), true)\r\n return normalizeAuthLaunchOptions({\r\n screen: (params.get('screen') || undefined) as AuthLaunchOptions['screen'],\r\n loginHint,\r\n method: (params.get('method') || undefined) as AuthLaunchOptions['method'],\r\n })\r\n}\r\n\r\nexport function buildAuthDestination({\r\n authUrl,\r\n query,\r\n options,\r\n}: {\r\n authUrl: string\r\n query: URLSearchParams\r\n options?: AuthLaunchOptions\r\n}) {\r\n const launch = normalizeAuthLaunchOptions(options)\r\n const authorizationUrl = new URL(authUrl)\r\n authorizationUrl.search = query.toString()\r\n if (launch.loginHint) authorizationUrl.searchParams.set('login_hint', launch.loginHint)\r\n if (launch.screen === 'login' && launch.method) {\r\n authorizationUrl.searchParams.set('method', launch.method)\r\n }\r\n if (launch.screen === 'login') return authorizationUrl.toString()\r\n\r\n const pathname = launch.screen === 'signup' ? '/signup' : '/forgot-password'\r\n const destination = new URL(pathname, authorizationUrl)\r\n const clientId = query.get('client_id')\r\n if (clientId) destination.searchParams.set('client_id', clientId)\r\n destination.searchParams.set(\r\n 'return_to',\r\n `${authorizationUrl.pathname}${authorizationUrl.search}`,\r\n )\r\n if (launch.loginHint) destination.searchParams.set('login_hint', launch.loginHint)\r\n if (launch.screen === 'signup') {\r\n destination.searchParams.set('method', launch.method || 'password')\r\n }\r\n return destination.toString()\r\n}\r\n","export const POPUP_MESSAGE_TYPE = 'pofsis-auth:callback'\r\n\r\nexport type PopupCallbackMessage = {\r\n type: typeof POPUP_MESSAGE_TYPE\r\n code?: string\r\n state?: string\r\n error?: string\r\n correlationId?: string\r\n}\r\n\r\nexport function correlationFromState(state: string | null) {\r\n if (!state) return undefined\r\n const separator = state.indexOf('.')\r\n return separator > 0 ? state.slice(0, separator) : undefined\r\n}\r\n\r\nexport function relayPopupCallback(targetOrigin = window.location.origin) {\r\n if (!window.opener || window.opener.closed) return false\r\n const params = new URLSearchParams(window.location.search)\r\n const state = params.get('state') || undefined\r\n const message: PopupCallbackMessage = {\r\n type: POPUP_MESSAGE_TYPE,\r\n code: params.get('code') || undefined,\r\n state,\r\n error: params.get('error') || undefined,\r\n correlationId: correlationFromState(state || null),\r\n }\r\n window.opener.postMessage(message, targetOrigin)\r\n window.close()\r\n return true\r\n}\r\n","const encode = (bytes: Uint8Array) =>\r\n btoa(String.fromCharCode(...bytes))\r\n .replace(/\\+/g, '-')\r\n .replace(/\\//g, '_')\r\n .replace(/=+$/, '')\r\n\r\nexport const randomValue = () => encode(crypto.getRandomValues(new Uint8Array(32)))\r\n\r\nexport async function pkceChallenge(verifier: string) {\r\n return encode(\r\n new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))),\r\n )\r\n}\r\n","import { checkSession, exchangeCode, fetchOAuthClient, refresh, signOut } from '../auth/api'\r\nimport { buildAuthDestination, normalizeAuthLaunchOptions } from '../auth/authLaunch'\r\nimport { resolveConfig } from '../auth/config'\r\nimport { pkceChallenge, randomValue } from '../auth/pkce'\r\nimport type {\r\n AuthLaunchOptions,\r\n AuthResult,\r\n OAuthClientConfig,\r\n PofsisAuthClientConfig,\r\n ResolvedPofsisAuthConfig,\r\n PofsisUser,\r\n SessionPayload,\r\n} from '../types'\r\nimport {\r\n correlationFromState,\r\n POPUP_MESSAGE_TYPE,\r\n type PopupCallbackMessage,\r\n} from './popupProtocol'\r\n\r\ntype Subscriber = (session: SessionPayload | null) => void\r\ntype PopupAttempt = {\r\n popup: Window\r\n state: string\r\n verifier: string\r\n correlationId: string\r\n returnUrl?: string\r\n resolve: (result: AuthResult) => void\r\n reject: (error: Error) => void\r\n timer: ReturnType<typeof setInterval>\r\n timeout: ReturnType<typeof setTimeout>\r\n}\r\n\r\nconst safeLocalPath = (value?: string) =>\r\n value?.startsWith('/') && !value.startsWith('//') ? value : undefined\r\n\r\nconst toSession = (result: { token_type: string; expires_in: number; user: PofsisUser }) => ({\r\n token_type: result.token_type,\r\n expires_in: result.expires_in,\r\n user: result.user,\r\n})\r\n\r\nexport class PofsisAuthClient {\r\n readonly config: ResolvedPofsisAuthConfig\r\n private token: string | null = null\r\n private session: SessionPayload | null = null\r\n private client: OAuthClientConfig | null = null\r\n private clientPromise: Promise<OAuthClientConfig> | null = null\r\n private refreshPromise: Promise<void> | null = null\r\n private subscribers = new Set<Subscriber>()\r\n private attempt: PopupAttempt | null = null\r\n private listening = false\r\n\r\n constructor(config: PofsisAuthClientConfig) {\r\n this.config = resolveConfig(config)\r\n this.attach()\r\n }\r\n\r\n private attach() {\r\n if (this.listening) return\r\n window.addEventListener('message', this.onPopupMessage)\r\n this.listening = true\r\n }\r\n\r\n destroy() {\r\n window.removeEventListener('message', this.onPopupMessage)\r\n this.listening = false\r\n const attempt = this.finishAttempt()\r\n if (attempt) {\r\n attempt.popup.close()\r\n attempt.resolve({ status: 'cancelled' })\r\n }\r\n this.subscribers.clear()\r\n }\r\n\r\n getUser() {\r\n return this.session?.user ?? null\r\n }\r\n\r\n getSession() {\r\n return this.session\r\n }\r\n\r\n getAccessToken() {\r\n return this.token\r\n }\r\n\r\n subscribe(listener: Subscriber) {\r\n this.attach()\r\n this.subscribers.add(listener)\r\n listener(this.session)\r\n return () => {\r\n this.subscribers.delete(listener)\r\n }\r\n }\r\n\r\n private emit() {\r\n for (const listener of this.subscribers) listener(this.session)\r\n }\r\n\r\n private accept(result: Awaited<ReturnType<typeof exchangeCode>>) {\r\n this.token = result.access_token\r\n this.session = toSession(result)\r\n this.emit()\r\n }\r\n\r\n private loadClient() {\r\n if (!this.clientPromise) {\r\n this.clientPromise = fetchOAuthClient(this.config)\r\n .then((client) => (this.client = client))\r\n .catch((error) => {\r\n this.clientPromise = null\r\n throw error\r\n })\r\n }\r\n return this.clientPromise\r\n }\r\n\r\n getOAuthClient() {\r\n return this.loadClient()\r\n }\r\n\r\n async refreshSession() {\r\n const client = await this.loadClient()\r\n if (!this.refreshPromise) {\r\n this.refreshPromise = refresh(this.config, client.client_id)\r\n .then((result) => {\r\n if (result) this.accept(result)\r\n else this.clearSession()\r\n })\r\n .finally(() => (this.refreshPromise = null))\r\n }\r\n return this.refreshPromise\r\n }\r\n\r\n async isRemoteSessionActive() {\r\n return checkSession(this.config)\r\n }\r\n\r\n clearSession() {\r\n this.token = null\r\n this.session = null\r\n this.emit()\r\n }\r\n\r\n replaceUser(user: PofsisUser) {\r\n if (!this.session) return\r\n this.session = { ...this.session, user }\r\n this.emit()\r\n }\r\n\r\n async logout() {\r\n try {\r\n await signOut(this.config)\r\n } finally {\r\n this.clearSession()\r\n }\r\n }\r\n\r\n signup(options: Omit<AuthLaunchOptions, 'screen'> = {}) {\r\n return this.login({ ...options, screen: 'signup' })\r\n }\r\n\r\n resetPassword(options: Omit<AuthLaunchOptions, 'screen'> = {}) {\r\n return this.login({ ...options, screen: 'reset' })\r\n }\r\n\r\n async login(options: AuthLaunchOptions = {}): Promise<AuthResult> {\r\n const launch = normalizeAuthLaunchOptions(options)\r\n const presentation = options.presentation ?? 'popup'\r\n if (presentation === 'popup') return this.openPopup({ ...options, ...launch })\r\n return this.startRedirect({ ...options, ...launch })\r\n }\r\n\r\n private async authorizationUrl(options: AuthLaunchOptions, state: string, verifier: string) {\r\n const client = await this.loadClient()\r\n const query = new URLSearchParams({\r\n client_id: client.client_id,\r\n redirect_uri: client.redirect_uri,\r\n response_type: 'code',\r\n scope: this.config.scope,\r\n state,\r\n code_challenge: await pkceChallenge(verifier),\r\n code_challenge_method: 'S256',\r\n })\r\n return buildAuthDestination({\r\n authUrl: this.config.authUrl,\r\n query,\r\n options,\r\n })\r\n }\r\n\r\n private storageKey(suffix: string) {\r\n return `${this.config.applicationId}.auth.${suffix}`\r\n }\r\n\r\n private async startRedirect(options: AuthLaunchOptions): Promise<AuthResult> {\r\n const state = randomValue()\r\n const verifier = randomValue()\r\n sessionStorage.setItem(this.storageKey('state'), state)\r\n sessionStorage.setItem(this.storageKey('verifier'), verifier)\r\n const returnUrl = safeLocalPath(options.returnUrl)\r\n if (returnUrl) sessionStorage.setItem(this.storageKey('return-path'), returnUrl)\r\n else sessionStorage.removeItem(this.storageKey('return-path'))\r\n window.location.assign(await this.authorizationUrl(options, state, verifier))\r\n return { status: 'redirecting' }\r\n }\r\n\r\n private async openPopup(options: AuthLaunchOptions): Promise<AuthResult> {\r\n if (this.attempt && !this.attempt.popup.closed) {\r\n this.attempt.popup.focus()\r\n return new Promise((resolve, reject) => {\r\n const current = this.attempt!\r\n const originalResolve = current.resolve\r\n const originalReject = current.reject\r\n current.resolve = (value) => {\r\n originalResolve(value)\r\n resolve(value)\r\n }\r\n current.reject = (error) => {\r\n originalReject(error)\r\n reject(error)\r\n }\r\n })\r\n }\r\n const { width, height, name, timeoutMs } = this.config.popup\r\n const left = Math.max(0, window.screenX + (window.outerWidth - width) / 2)\r\n const top = Math.max(0, window.screenY + (window.outerHeight - height) / 2)\r\n const popup = window.open(\r\n 'about:blank',\r\n name,\r\n `popup=yes,width=${width},height=${height},left=${Math.round(left)},top=${Math.round(top)}`,\r\n )\r\n if (!popup) return this.startRedirect({ ...options, presentation: 'redirect' })\r\n\r\n const correlationId = randomValue()\r\n const state = `${correlationId}.${randomValue()}`\r\n const verifier = randomValue()\r\n const returnUrl = safeLocalPath(options.returnUrl)\r\n return new Promise<AuthResult>((resolve, reject) => {\r\n const timer = setInterval(() => {\r\n if (!popup.closed) return\r\n const attempt = this.finishAttempt()\r\n attempt?.resolve({ status: 'cancelled' })\r\n }, 250)\r\n const timeout = setTimeout(() => {\r\n const attempt = this.finishAttempt()\r\n popup.close()\r\n attempt?.reject(new Error('POFSIS Auth popup timed out.'))\r\n }, timeoutMs)\r\n this.attempt = {\r\n popup,\r\n state,\r\n verifier,\r\n correlationId,\r\n returnUrl,\r\n resolve,\r\n reject,\r\n timer,\r\n timeout,\r\n }\r\n void this.authorizationUrl(options, state, verifier)\r\n .then((url) => popup.location.replace(url))\r\n .catch((error) => {\r\n const attempt = this.finishAttempt()\r\n popup.close()\r\n attempt?.reject(error instanceof Error ? error : new Error(String(error)))\r\n })\r\n })\r\n }\r\n\r\n private finishAttempt() {\r\n const attempt = this.attempt\r\n if (!attempt) return null\r\n clearInterval(attempt.timer)\r\n clearTimeout(attempt.timeout)\r\n this.attempt = null\r\n return attempt\r\n }\r\n\r\n private onPopupMessage = (event: MessageEvent<PopupCallbackMessage>) => {\r\n const attempt = this.attempt\r\n const message = event.data\r\n if (\r\n !attempt ||\r\n event.origin !== window.location.origin ||\r\n event.source !== attempt.popup ||\r\n message?.type !== POPUP_MESSAGE_TYPE ||\r\n message.correlationId !== attempt.correlationId ||\r\n correlationFromState(message.state || null) !== attempt.correlationId ||\r\n message.state !== attempt.state\r\n )\r\n return\r\n\r\n const completed = this.finishAttempt()\r\n if (!completed) return\r\n if (message.error || !message.code) {\r\n completed.popup.close()\r\n completed.reject(new Error(message.error || 'POFSIS Auth callback was incomplete.'))\r\n return\r\n }\r\n void this.completeCode(message.code, message.state, completed.verifier)\r\n .then(() => {\r\n completed.popup.close()\r\n if (completed.returnUrl) window.history.replaceState(null, '', completed.returnUrl)\r\n completed.resolve({ status: 'authenticated', user: this.getUser()! })\r\n })\r\n .catch((error) => {\r\n completed.popup.close()\r\n completed.reject(error instanceof Error ? error : new Error(String(error)))\r\n })\r\n }\r\n\r\n private async completeCode(code: string, state: string, verifier: string) {\r\n if (!state || !verifier) throw new Error('Authentication state could not be verified.')\r\n const client = await this.loadClient()\r\n this.accept(await exchangeCode(this.config, code, verifier, client))\r\n }\r\n\r\n async completeRedirectCallback(code: string, state: string) {\r\n const expected = sessionStorage.getItem(this.storageKey('state'))\r\n const verifier = sessionStorage.getItem(this.storageKey('verifier'))\r\n sessionStorage.removeItem(this.storageKey('state'))\r\n sessionStorage.removeItem(this.storageKey('verifier'))\r\n if (!expected || !verifier || state !== expected) {\r\n throw new Error('Authentication state could not be verified.')\r\n }\r\n await this.completeCode(code, state, verifier)\r\n }\r\n}\r\n\r\nexport function createPofsisAuth(config: PofsisAuthClientConfig) {\r\n return new PofsisAuthClient(config)\r\n}\r\n"],"mappings":"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"}