@strivacity/sdk-core 4.0.0-beta.0 → 4.0.0-beta.1
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.
- package/README.md +1 -0
- package/dist/assets/oidc.cjs +1 -1
- package/dist/assets/oidc.cjs.map +1 -1
- package/dist/assets/oidc.mjs +1 -1
- package/dist/assets/oidc.mjs.map +1 -1
- package/dist/flows/base.cjs +1 -1
- package/dist/flows/base.cjs.map +1 -1
- package/dist/flows/base.mjs +1 -1
- package/dist/flows/base.mjs.map +1 -1
- package/dist/server/base.cjs +1 -1
- package/dist/server/base.cjs.map +1 -1
- package/dist/server/base.mjs +1 -1
- package/dist/server/base.mjs.map +1 -1
- package/dist/types/oidc.cjs.map +1 -1
- package/dist/types/oidc.d.ts +6 -0
- package/dist/types/oidc.mjs.map +1 -1
- package/dist/utils/session.cjs +1 -1
- package/dist/utils/session.cjs.map +1 -1
- package/dist/utils/session.d.ts +2 -1
- package/dist/utils/session.mjs +1 -1
- package/dist/utils/session.mjs.map +1 -1
- package/package.json +1 -1
- package/testing/tests/utils/oidc.spec.ts +1 -0
- package/testing/tests/utils/session.spec.ts +87 -0
package/dist/server/base.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.cjs","names":[],"sources":["../../src/server/base.ts"],"sourcesContent":["import type { SDKStorage } from '../types/common';\nimport type { SessionData, LogoutTokenClaims } from '../types/oidc';\nimport type { BaseServerSDK, ServerAdapter, ServerStorage, ServerSDKInitConfig } from '../types/server';\nimport {\n\tbuildEndSessionUrl,\n\tbuildAuthorizationUrl,\n\trevokeToken,\n\trefreshToken,\n\texchangeCode,\n\tverifyJwt,\n\tfetchFlowEntry,\n\tgetDiscoveryDocument,\n} from '../utils/oidc';\nimport { loadSession, serializeSession } from '../utils/session';\nimport { parseState } from '../utils/state';\nimport { timestamp } from '../utils/common';\nimport { ConfigurationError, OidcError, ProtocolError, type FailureCategory } from '../utils/errors';\nimport {\n\tpushSetCookie,\n\tflushSetCookies,\n\tparseCookieHeader,\n\tserializeCookie,\n\tproxyResponse,\n\ttoSafeRedirect,\n\tgetServerSDKOptions,\n\tBACKCHANNEL_LOGOUT_EVENT,\n} from '../utils/server';\n\nexport const COOKIE_CONTEXT = 'strivacity-session-v1';\nexport const COOKIE_CHUNK_SIZE = 3900;\nexport const DISALLOWED_PROXY_HEADERS = new Set(['transfer-encoding', 'connection', 'keep-alive', 'content-encoding']);\nexport const RETURN_TO_COOKIE = 'sty.returnTo';\nexport const BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS = 120;\n\n/**\n * Creates the framework-agnostic Strivacity base server SDK.\n *\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter converting `TEvent` to a standard `Request`.\n * @param {ServerSDKOptions<TEvent, Storage, StateStorage>} initConfig - The initial configuration for the server SDK.\n * @returns {BaseServerSDK<TEvent>} The initialized, framework-agnostic server SDK core.\n */\nexport function createBaseServerSDK<\n\tTEvent = unknown,\n\tStorage extends ServerStorage<TEvent> = ServerStorage<TEvent>,\n\tStateStorage extends SDKStorage = SDKStorage,\n>(adapter: ServerAdapter<TEvent>, initConfig: ServerSDKInitConfig<TEvent, Storage, StateStorage>): BaseServerSDK<TEvent> {\n\tconst options = getServerSDKOptions(adapter, initConfig);\n\tconst seenLogoutTokenIds = new Map<string, number>();\n\n\tfunction init() {\n\t\tif (!options.issuer) {\n\t\t\tconst error = new ConfigurationError('Missing option: issuer');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (!options.clientId) {\n\t\t\tconst error = new ConfigurationError('Missing option: clientId');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (!options.redirectUri) {\n\t\t\tconst error = new ConfigurationError('Missing option: redirectUri');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (options.scopes && !Array.isArray(options.scopes)) {\n\t\t\tconst error = new ConfigurationError('Invalid option: scopes');\n\t\t\toptions.logging?.error('Invalid option provided', error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function redirect(url: string | URL, status = 302, event?: TEvent): Promise<Response> {\n\t\tif (adapter.redirect) {\n\t\t\treturn await adapter.redirect(url, status, event);\n\t\t}\n\n\t\treturn new Response(null, { status, headers: { location: url.toString() } });\n\t}\n\n\tasync function errorRedirect(origin: string, error: unknown, event?: TEvent): Promise<Response> {\n\t\tconst url = new URL('/error', origin);\n\n\t\tif (error instanceof OidcError) {\n\t\t\turl.searchParams.set('type', error.category.toLowerCase());\n\t\t\turl.searchParams.set('error', error.error);\n\t\t\tif (error.errorDescription) {\n\t\t\t\turl.searchParams.set('error_description', error.errorDescription);\n\t\t\t}\n\t\t} else if (error instanceof Error && 'category' in error) {\n\t\t\turl.searchParams.set('type', (error as { category: FailureCategory }).category.toLowerCase());\n\t\t\turl.searchParams.set('error', error.name);\n\t\t\turl.searchParams.set('error_description', error.message);\n\t\t} else {\n\t\t\turl.searchParams.set('type', 'unknown');\n\t\t\turl.searchParams.set('error', 'unknown_error');\n\t\t\turl.searchParams.set('error_description', error instanceof Error ? error.message : 'Unknown error');\n\t\t}\n\n\t\treturn redirect(url, 302, event);\n\t}\n\n\tasync function getSession(event?: TEvent): Promise<SessionData | null> {\n\t\treturn loadSession(await options.storage.get(options.storageTokenName, event));\n\t}\n\n\tasync function updateSession(session: SessionData, event?: TEvent): Promise<void> {\n\t\tawait options.storage.set(options.storageTokenName, serializeSession(session), event);\n\t}\n\n\tasync function cleanupSession(event?: TEvent): Promise<void> {\n\t\tawait options.storage.delete(options.storageTokenName, event);\n\t}\n\n\tasync function refreshSession(event?: TEvent): Promise<SessionData> {\n\t\toptions.logging?.debug('Attempting to refresh session');\n\n\t\tconst currentSession = await getSession(event);\n\n\t\tif (!currentSession) {\n\t\t\tthrow new ProtocolError('No session available to refresh');\n\t\t}\n\n\t\tif (typeof currentSession.refresh_token !== 'string') {\n\t\t\tthrow new ConfigurationError('No refresh token available');\n\t\t}\n\n\t\ttry {\n\t\t\tconst newSession = await refreshToken({ refreshToken: currentSession.refresh_token, options, expectedSub: currentSession.claims?.sub });\n\t\t\tawait updateSession(newSession, event);\n\n\t\t\toptions.logging?.debug('Session refresh successful');\n\n\t\t\treturn newSession;\n\t\t} catch (error) {\n\t\t\tawait cleanupSession(event);\n\t\t\toptions.logging?.error('Session refresh failed', error as Error);\n\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function revokeSession(event?: TEvent): Promise<void> {\n\t\tconst currentSession = await getSession(event);\n\n\t\tif (currentSession?.refresh_token) {\n\t\t\toptions.logging?.debug('Attempting to revoke refresh token');\n\t\t} else {\n\t\t\toptions.logging?.debug('Attempting to revoke access token');\n\t\t}\n\n\t\t// NOTE: Cleanup session before revocation\n\t\tawait cleanupSession(event);\n\n\t\tif (!currentSession?.access_token && !currentSession?.refresh_token) {\n\t\t\toptions.logging?.debug('Revoke called without session');\n\t\t\treturn;\n\t\t}\n\n\t\tconst tokenTypeHint = currentSession.refresh_token ? 'refresh_token' : 'access_token';\n\t\tconst token = (tokenTypeHint === 'refresh_token' ? currentSession.refresh_token : currentSession.access_token)!;\n\n\t\ttry {\n\t\t\tawait revokeToken({ tokenTypeHint, token, options });\n\n\t\t\tif (tokenTypeHint === 'refresh_token') {\n\t\t\t\toptions.logging?.info('Refresh token successfully revoked');\n\t\t\t} else {\n\t\t\t\toptions.logging?.info('Access token successfully revoked');\n\t\t\t}\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Token revocation failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function getEntrySession(entryUrl: string | URL): Promise<Record<string, string>> {\n\t\toptions.logging?.debug('Attempting entry request');\n\n\t\tconst { searchParams: params } = new URL(entryUrl);\n\n\t\ttry {\n\t\t\tconst url = new URL('/provider/flow/entry', options.issuer);\n\t\t\tconst data = await fetchFlowEntry({\n\t\t\t\turl,\n\t\t\t\tparams,\n\t\t\t\tsdkMode: options.mode === 'embedded' ? 'web-embedded' : 'web',\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\toptions.logging?.debug(`Entry request successful - ${JSON.stringify(data)}`);\n\n\t\t\treturn data;\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Entry request failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function completeLogin(params: Record<string, string>, event?: TEvent): Promise<SessionData> {\n\t\toptions.logging?.debug('Exchanging authorization code for tokens');\n\n\t\ttry {\n\t\t\tconst session = await exchangeCode({ params, options });\n\n\t\t\tif (!session.access_token) {\n\t\t\t\tthrow new ProtocolError('Missing access_token');\n\t\t\t}\n\n\t\t\tawait updateSession(session, event);\n\n\t\t\toptions.logging?.debug('Token exchange successful');\n\n\t\t\tif (options.logging) {\n\t\t\t\toptions.logging.xEventId = undefined;\n\t\t\t\toptions.logging.info('Login successful');\n\t\t\t}\n\n\t\t\treturn session;\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Token exchange failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function logout(postLogoutRedirectUri: string | URL, event?: TEvent): Promise<URL> {\n\t\toptions.logging?.debug('Attempting to logout');\n\n\t\t// NOTE: Cleanup session before logout\n\t\tconst currentSession = await getSession(event);\n\t\tawait cleanupSession(event);\n\n\t\toptions.logging?.debug('Logout initiated');\n\n\t\tif (!currentSession?.id_token) {\n\t\t\toptions.logging?.debug('Logout called without id token');\n\t\t\treturn new URL(postLogoutRedirectUri);\n\t\t}\n\n\t\tconst metadata = await getDiscoveryDocument(options);\n\n\t\treturn buildEndSessionUrl({\n\t\t\turl: metadata.end_session_endpoint,\n\t\t\tidToken: currentSession.id_token,\n\t\t\tpostLogoutRedirectUri: new URL(postLogoutRedirectUri).toString(),\n\t\t});\n\t}\n\n\tasync function handleLogin(event: TEvent, extraParams: Record<string, unknown> = {}): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst { returnTo, ...params } = Object.fromEntries(requestUrl.searchParams);\n\t\tconst safeReturnTo = toSafeRedirect(returnTo, requestUrl.origin);\n\t\tconst url = await buildAuthorizationUrl({ params: { ...params, ...extraParams }, options });\n\n\t\tif (returnTo && !safeReturnTo) {\n\t\t\tthrow new ProtocolError(`Invalid returnTo URL: ${returnTo}. Expected a URL with the same origin as the request: ${requestUrl.origin}`);\n\t\t}\n\n\t\tif (['embedded', 'native'].includes(options.mode) && params.sdk) {\n\t\t\turl.searchParams.set('sdk', params.sdk);\n\t\t}\n\n\t\tconst startResponse = await options.httpClient.request<string>(url, {\n\t\t\tmethod: 'GET',\n\t\t\tcredentials: 'include',\n\t\t\tredirect: 'manual',\n\t\t});\n\n\t\toptions.logging?.debug('Attempting to redirect for login');\n\n\t\tif (safeReturnTo) {\n\t\t\tpushSetCookie(event, serializeCookie(RETURN_TO_COOKIE, safeReturnTo));\n\t\t}\n\n\t\treturn flushSetCookies(event, proxyResponse(startResponse));\n\t}\n\n\tasync function handleRegister(event: TEvent): Promise<Response> {\n\t\treturn handleLogin(event, { prompt: 'create' });\n\t}\n\n\tasync function handleCallback(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst params = Object.fromEntries(requestUrl.searchParams);\n\n\t\ttry {\n\t\t\tconst serializedState = await options.stateStorage.get(`sty.${params.state}`);\n\n\t\t\tif (!serializedState) {\n\t\t\t\tthrow new ProtocolError('State not found or expired. Please try logging in again.');\n\t\t\t}\n\n\t\t\tawait completeLogin(params, event);\n\n\t\t\tconst state = parseState(serializedState);\n\t\t\tconst returnTo = parseCookieHeader(request.headers.get('cookie'))[RETURN_TO_COOKIE] ?? options.postLoginRedirectUri;\n\n\t\t\tpushSetCookie(event, serializeCookie(RETURN_TO_COOKIE, '', { expires: new Date(0) }));\n\n\t\t\tif (state.metadata?.display === 'popup') {\n\t\t\t\t// NOTE: If the login was initiated from a popup, we return a HTML page that will close the popup and notify the opener window.\n\t\t\t\treturn flushSetCookies(\n\t\t\t\t\tevent,\n\t\t\t\t\tnew Response(`<!DOCTYPE html><html><body><script>window.opener?.postMessage({}, '*');window.close();</script></body></html>`, {\n\t\t\t\t\t\theaders: { 'content-type': 'text/html; charset=utf-8' },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn flushSetCookies(event, await redirect(new URL(returnTo, requestUrl.origin), 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(requestUrl.origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleRefresh(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst origin = requestUrl.origin;\n\t\tconst returnTo = requestUrl.searchParams.get('returnTo');\n\t\tconst safeReturnTo = toSafeRedirect(returnTo, origin);\n\n\t\tif (returnTo && !safeReturnTo) {\n\t\t\tthrow new ProtocolError(`Invalid returnTo URL: ${returnTo}. Expected a URL with the same origin as the request: ${requestUrl.origin}`);\n\t\t}\n\n\t\ttry {\n\t\t\tawait refreshSession(event);\n\n\t\t\tif (safeReturnTo) {\n\t\t\t\treturn flushSetCookies(event, await redirect(new URL(safeReturnTo, origin), 302, event));\n\t\t\t}\n\n\t\t\treturn flushSetCookies(event, new Response(null, { status: 204 }));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleRevoke(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tawait revokeSession(event);\n\n\t\t\treturn flushSetCookies(event, await redirect(new URL(options.postLogoutRedirectUri, origin), 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleEntry(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tconst data = await getEntrySession(request.url);\n\t\t\tconst uri = new URL(options.loginUri, origin);\n\t\t\turi.searchParams.set('session_id', data.session_id);\n\t\t\turi.searchParams.set('short_app_id', data.short_app_id);\n\t\t\turi.searchParams.set('language', data.language);\n\n\t\t\treturn flushSetCookies(event, await redirect(uri, 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleLogout(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tconst logoutUrl = await logout(new URL(options.postLogoutRedirectUri, origin), event);\n\t\t\treturn flushSetCookies(event, await redirect(logoutUrl, 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleBackChannelLogout(event: TEvent): Promise<Response> {\n\t\tif (typeof options.storage.deleteByLogoutToken !== 'function') {\n\t\t\treturn new Response('Back-channel logout requires a storage with deleteByLogoutToken', { status: 501 });\n\t\t}\n\n\t\tconst request = await adapter.toRequest(event);\n\t\tlet logoutToken: string | null;\n\n\t\ttry {\n\t\t\tconst contentType = request.headers.get('content-type') ?? '';\n\n\t\t\tif (contentType.includes('application/x-www-form-urlencoded')) {\n\t\t\t\tconst body = await request.formData();\n\t\t\t\tlogoutToken = body.get('logout_token') as string | null;\n\t\t\t} else {\n\t\t\t\treturn new Response('Invalid content type: expected application/x-www-form-urlencoded', { status: 400 });\n\t\t\t}\n\t\t} catch {\n\t\t\treturn new Response('Failed to parse request body', { status: 400 });\n\t\t}\n\n\t\tif (!logoutToken) {\n\t\t\treturn new Response('Missing logout_token', { status: 400 });\n\t\t}\n\n\t\tconst now = timestamp();\n\n\t\tfor (const [token, expiresAt] of seenLogoutTokenIds) {\n\t\t\tif (expiresAt <= now) {\n\t\t\t\tseenLogoutTokenIds.delete(token);\n\t\t\t}\n\t\t}\n\n\t\tif (seenLogoutTokenIds.has(logoutToken)) {\n\t\t\treturn new Response('Invalid logout_token: token already used', { status: 400 });\n\t\t}\n\n\t\tseenLogoutTokenIds.set(logoutToken, now + BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS);\n\n\t\tlet claims;\n\t\tlet metadata;\n\n\t\ttry {\n\t\t\tmetadata = await getDiscoveryDocument(options);\n\t\t\tclaims = await verifyJwt<LogoutTokenClaims>({ token: logoutToken, jwksUri: metadata.jwks_uri, options });\n\t\t} catch (error) {\n\t\t\treturn new Response(`Invalid logout_token: ${error.message}`, { status: 400 });\n\t\t}\n\n\t\tif (claims.iss !== metadata.issuer) {\n\t\t\treturn new Response('Invalid logout_token: invalid iss claim', { status: 400 });\n\t\t}\n\n\t\tif (Array.isArray(claims.aud) ? !claims.aud.includes(options.clientId) : claims.aud !== options.clientId) {\n\t\t\treturn new Response('Invalid logout_token: invalid aud claim', { status: 400 });\n\t\t}\n\n\t\tif (typeof claims.iat !== 'number' || Math.abs(now - claims.iat) > BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS) {\n\t\t\treturn new Response('Invalid logout_token: invalid or stale iat claim', { status: 400 });\n\t\t}\n\n\t\tif (!claims.jti) {\n\t\t\treturn new Response('Invalid logout_token: missing jti claim', { status: 400 });\n\t\t}\n\n\t\tif (claims.nonce !== undefined) {\n\t\t\treturn new Response('Invalid logout_token: nonce claim must not be present', { status: 400 });\n\t\t}\n\n\t\tif (!claims.events || !(BACKCHANNEL_LOGOUT_EVENT in claims.events)) {\n\t\t\treturn new Response(`Invalid logout_token: missing ${BACKCHANNEL_LOGOUT_EVENT} in events`, { status: 400 });\n\t\t}\n\n\t\tif (!claims.sid && !claims.sub) {\n\t\t\treturn new Response('Invalid logout_token: must contain sid or sub claim', { status: 400 });\n\t\t}\n\n\t\tconst token: LogoutTokenClaims = {} as never;\n\n\t\tif (claims.sid) {\n\t\t\ttoken.sid = claims.sid;\n\t\t}\n\t\tif (claims.sub) {\n\t\t\ttoken.sub = claims.sub;\n\t\t}\n\n\t\ttry {\n\t\t\tawait options.storage.deleteByLogoutToken(token);\n\t\t} catch (error) {\n\t\t\treturn new Response(`Failed to delete session: ${error.message}`, { status: 500 });\n\t\t}\n\n\t\treturn new Response(null, { status: 200 });\n\t}\n\n\tasync function handler(event: TEvent): Promise<Response | null> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/login`) {\n\t\t\treturn handleLogin(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/register`) {\n\t\t\treturn handleRegister(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/callback`) {\n\t\t\treturn handleCallback(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/refresh`) {\n\t\t\treturn handleRefresh(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/revoke`) {\n\t\t\treturn handleRevoke(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/entry`) {\n\t\t\treturn handleEntry(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/logout`) {\n\t\t\treturn handleLogout(event);\n\t\t}\n\t\tif (request.method === 'POST' && requestUrl.pathname === `${options.authUrlPrefix}/backchannel-logout`) {\n\t\t\treturn handleBackChannelLogout(event);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// endregion\n\n\tinit();\n\n\treturn {\n\t\tget options() {\n\t\t\treturn options;\n\t\t},\n\t\tgetSession,\n\t\tupdateSession,\n\t\trefreshSession,\n\t\trevokeSession,\n\t\tgetEntrySession,\n\t\tcompleteLogin,\n\t\tlogout,\n\t\thandleLogin,\n\t\thandleRegister,\n\t\thandleCallback,\n\t\thandleRefresh,\n\t\thandleRevoke,\n\t\thandleEntry,\n\t\thandleLogout,\n\t\thandleBackChannelLogout,\n\t\thandler,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"base.cjs","names":[],"sources":["../../src/server/base.ts"],"sourcesContent":["import type { SDKStorage } from '../types/common';\nimport type { SessionData, LogoutTokenClaims } from '../types/oidc';\nimport type { BaseServerSDK, ServerAdapter, ServerStorage, ServerSDKInitConfig } from '../types/server';\nimport {\n\tbuildEndSessionUrl,\n\tbuildAuthorizationUrl,\n\trevokeToken,\n\trefreshToken,\n\texchangeCode,\n\tverifyJwt,\n\tfetchFlowEntry,\n\tgetDiscoveryDocument,\n} from '../utils/oidc';\nimport { loadSession, serializeSession } from '../utils/session';\nimport { parseState } from '../utils/state';\nimport { timestamp } from '../utils/common';\nimport { ConfigurationError, OidcError, ProtocolError, type FailureCategory } from '../utils/errors';\nimport {\n\tpushSetCookie,\n\tflushSetCookies,\n\tparseCookieHeader,\n\tserializeCookie,\n\tproxyResponse,\n\ttoSafeRedirect,\n\tgetServerSDKOptions,\n\tBACKCHANNEL_LOGOUT_EVENT,\n} from '../utils/server';\n\nexport const COOKIE_CONTEXT = 'strivacity-session-v1';\nexport const COOKIE_CHUNK_SIZE = 3900;\nexport const DISALLOWED_PROXY_HEADERS = new Set(['transfer-encoding', 'connection', 'keep-alive', 'content-encoding']);\nexport const RETURN_TO_COOKIE = 'sty.returnTo';\nexport const BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS = 120;\n\n/**\n * Creates the framework-agnostic Strivacity base server SDK.\n *\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter converting `TEvent` to a standard `Request`.\n * @param {ServerSDKOptions<TEvent, Storage, StateStorage>} initConfig - The initial configuration for the server SDK.\n * @returns {BaseServerSDK<TEvent>} The initialized, framework-agnostic server SDK core.\n */\nexport function createBaseServerSDK<\n\tTEvent = unknown,\n\tStorage extends ServerStorage<TEvent> = ServerStorage<TEvent>,\n\tStateStorage extends SDKStorage = SDKStorage,\n>(adapter: ServerAdapter<TEvent>, initConfig: ServerSDKInitConfig<TEvent, Storage, StateStorage>): BaseServerSDK<TEvent> {\n\tconst options = getServerSDKOptions(adapter, initConfig);\n\tconst seenLogoutTokenIds = new Map<string, number>();\n\n\tfunction init() {\n\t\tif (!options.issuer) {\n\t\t\tconst error = new ConfigurationError('Missing option: issuer');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (!options.clientId) {\n\t\t\tconst error = new ConfigurationError('Missing option: clientId');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (!options.redirectUri) {\n\t\t\tconst error = new ConfigurationError('Missing option: redirectUri');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (options.scopes && !Array.isArray(options.scopes)) {\n\t\t\tconst error = new ConfigurationError('Invalid option: scopes');\n\t\t\toptions.logging?.error('Invalid option provided', error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function redirect(url: string | URL, status = 302, event?: TEvent): Promise<Response> {\n\t\tif (adapter.redirect) {\n\t\t\treturn await adapter.redirect(url, status, event);\n\t\t}\n\n\t\treturn new Response(null, { status, headers: { location: url.toString() } });\n\t}\n\n\tasync function errorRedirect(origin: string, error: unknown, event?: TEvent): Promise<Response> {\n\t\tconst url = new URL('/error', origin);\n\n\t\tif (error instanceof OidcError) {\n\t\t\turl.searchParams.set('type', error.category.toLowerCase());\n\t\t\turl.searchParams.set('error', error.error);\n\t\t\tif (error.errorDescription) {\n\t\t\t\turl.searchParams.set('error_description', error.errorDescription);\n\t\t\t}\n\t\t} else if (error instanceof Error && 'category' in error) {\n\t\t\turl.searchParams.set('type', (error as { category: FailureCategory }).category.toLowerCase());\n\t\t\turl.searchParams.set('error', error.name);\n\t\t\turl.searchParams.set('error_description', error.message);\n\t\t} else {\n\t\t\turl.searchParams.set('type', 'unknown');\n\t\t\turl.searchParams.set('error', 'unknown_error');\n\t\t\turl.searchParams.set('error_description', error instanceof Error ? error.message : 'Unknown error');\n\t\t}\n\n\t\treturn redirect(url, 302, event);\n\t}\n\n\tasync function getSession(event?: TEvent): Promise<SessionData | null> {\n\t\treturn loadSession(await options.storage.get(options.storageTokenName, event));\n\t}\n\n\tasync function updateSession(session: SessionData, event?: TEvent): Promise<void> {\n\t\tawait options.storage.set(options.storageTokenName, serializeSession(session), event);\n\t}\n\n\tasync function cleanupSession(event?: TEvent): Promise<void> {\n\t\tawait options.storage.delete(options.storageTokenName, event);\n\t}\n\n\tasync function refreshSession(event?: TEvent): Promise<SessionData> {\n\t\toptions.logging?.debug('Attempting to refresh session');\n\n\t\tconst currentSession = await getSession(event);\n\n\t\tif (!currentSession) {\n\t\t\tthrow new ProtocolError('No session available to refresh');\n\t\t}\n\n\t\tif (typeof currentSession.refresh_token !== 'string') {\n\t\t\tthrow new ConfigurationError('No refresh token available');\n\t\t}\n\n\t\ttry {\n\t\t\tconst newSession = await refreshToken({ refreshToken: currentSession.refresh_token, options, expectedSub: currentSession.claims?.sub });\n\t\t\tawait updateSession(newSession, event);\n\n\t\t\toptions.logging?.debug('Session refresh successful');\n\n\t\t\treturn newSession;\n\t\t} catch (error) {\n\t\t\tawait cleanupSession(event);\n\t\t\toptions.logging?.error('Session refresh failed', error as Error);\n\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function revokeSession(event?: TEvent): Promise<void> {\n\t\tconst currentSession = await getSession(event);\n\n\t\tif (currentSession?.refresh_token) {\n\t\t\toptions.logging?.debug('Attempting to revoke refresh token');\n\t\t} else {\n\t\t\toptions.logging?.debug('Attempting to revoke access token');\n\t\t}\n\n\t\t// NOTE: Cleanup session before revocation\n\t\tawait cleanupSession(event);\n\n\t\tif (!currentSession?.access_token && !currentSession?.refresh_token) {\n\t\t\toptions.logging?.debug('Revoke called without session');\n\t\t\treturn;\n\t\t}\n\n\t\tconst tokenTypeHint = currentSession.refresh_token ? 'refresh_token' : 'access_token';\n\t\tconst token = (tokenTypeHint === 'refresh_token' ? currentSession.refresh_token : currentSession.access_token)!;\n\n\t\ttry {\n\t\t\tawait revokeToken({ tokenTypeHint, token, options });\n\n\t\t\tif (tokenTypeHint === 'refresh_token') {\n\t\t\t\toptions.logging?.info('Refresh token successfully revoked');\n\t\t\t} else {\n\t\t\t\toptions.logging?.info('Access token successfully revoked');\n\t\t\t}\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Token revocation failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function getEntrySession(entryUrl: string | URL): Promise<Record<string, string>> {\n\t\toptions.logging?.debug('Attempting entry request');\n\n\t\tconst { searchParams: params } = new URL(entryUrl);\n\n\t\ttry {\n\t\t\tconst url = new URL('/provider/flow/entry', options.issuer);\n\t\t\tconst data = await fetchFlowEntry({\n\t\t\t\turl,\n\t\t\t\tparams,\n\t\t\t\tsdkMode: options.mode === 'embedded' ? 'web-embedded' : 'web',\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\toptions.logging?.debug(`Entry request successful - ${JSON.stringify(data)}`);\n\n\t\t\treturn data;\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Entry request failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function completeLogin(params: Record<string, string>, event?: TEvent): Promise<SessionData> {\n\t\toptions.logging?.debug('Exchanging authorization code for tokens');\n\n\t\ttry {\n\t\t\tconst session = await exchangeCode({ params, options });\n\n\t\t\tif (!session.access_token) {\n\t\t\t\tthrow new ProtocolError('Missing access_token');\n\t\t\t}\n\n\t\t\tawait updateSession(session, event);\n\n\t\t\toptions.logging?.debug('Token exchange successful');\n\n\t\t\tif (options.logging) {\n\t\t\t\toptions.logging.xEventId = undefined;\n\t\t\t\toptions.logging.info('Login successful');\n\t\t\t}\n\n\t\t\treturn session;\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Token exchange failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function logout(postLogoutRedirectUri: string | URL, event?: TEvent): Promise<URL> {\n\t\toptions.logging?.debug('Attempting to logout');\n\n\t\t// NOTE: Cleanup session before logout\n\t\tconst currentSession = await getSession(event);\n\t\tawait cleanupSession(event);\n\n\t\toptions.logging?.debug('Logout initiated');\n\n\t\tif (!currentSession?.id_token) {\n\t\t\toptions.logging?.debug('Logout called without id token');\n\t\t\treturn new URL(postLogoutRedirectUri);\n\t\t}\n\n\t\tconst metadata = await getDiscoveryDocument(options);\n\n\t\treturn buildEndSessionUrl({\n\t\t\turl: metadata.end_session_endpoint,\n\t\t\tidToken: currentSession.id_token,\n\t\t\tpostLogoutRedirectUri: new URL(postLogoutRedirectUri).toString(),\n\t\t});\n\t}\n\n\tasync function handleLogin(event: TEvent, extraParams: Record<string, unknown> = {}): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst { returnTo, prompt, display, login_hint, acr_values, ui_locales, audience, ...params } = Object.fromEntries(requestUrl.searchParams);\n\t\tconst safeReturnTo = toSafeRedirect(returnTo, requestUrl.origin);\n\t\tconst url = await buildAuthorizationUrl({\n\t\t\tparams: {\n\t\t\t\tprompt: prompt ?? params.prompt,\n\t\t\t\tdisplay: display ?? params.display,\n\t\t\t\tloginHint: login_hint ?? params.loginHint,\n\t\t\t\tacrValues: (acr_values ?? params.acrValues)?.split(' '),\n\t\t\t\tuiLocales: (ui_locales ?? params.uiLocales)?.split(' '),\n\t\t\t\taudiences: (audience ?? params.audiences)?.split(' '),\n\t\t\t\t...extraParams,\n\t\t\t},\n\t\t\toptions,\n\t\t});\n\n\t\tif (returnTo && !safeReturnTo) {\n\t\t\tthrow new ProtocolError(`Invalid returnTo URL: ${returnTo}. Expected a URL with the same origin as the request: ${requestUrl.origin}`);\n\t\t}\n\n\t\tif (['embedded', 'native'].includes(options.mode) && params.sdk) {\n\t\t\turl.searchParams.set('sdk', params.sdk);\n\t\t}\n\n\t\tconst startResponse = await options.httpClient.request<string>(url, {\n\t\t\tmethod: 'GET',\n\t\t\tcredentials: 'include',\n\t\t\tredirect: 'manual',\n\t\t});\n\n\t\toptions.logging?.debug('Attempting to redirect for login');\n\n\t\tif (safeReturnTo) {\n\t\t\tpushSetCookie(event, serializeCookie(RETURN_TO_COOKIE, safeReturnTo));\n\t\t}\n\n\t\treturn flushSetCookies(event, proxyResponse(startResponse));\n\t}\n\n\tasync function handleRegister(event: TEvent): Promise<Response> {\n\t\treturn handleLogin(event, { prompt: 'create' });\n\t}\n\n\tasync function handleCallback(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst params = Object.fromEntries(requestUrl.searchParams);\n\n\t\ttry {\n\t\t\tconst serializedState = await options.stateStorage.get(`sty.${params.state}`);\n\n\t\t\tif (!serializedState) {\n\t\t\t\tthrow new ProtocolError('State not found or expired. Please try logging in again.');\n\t\t\t}\n\n\t\t\tawait completeLogin(params, event);\n\n\t\t\tconst state = parseState(serializedState);\n\t\t\tconst returnTo = parseCookieHeader(request.headers.get('cookie'))[RETURN_TO_COOKIE] ?? options.postLoginRedirectUri;\n\n\t\t\tpushSetCookie(event, serializeCookie(RETURN_TO_COOKIE, '', { expires: new Date(0) }));\n\n\t\t\tif (state.metadata?.display === 'popup') {\n\t\t\t\t// NOTE: If the login was initiated from a popup, we return a HTML page that will close the popup and notify the opener window.\n\t\t\t\treturn flushSetCookies(\n\t\t\t\t\tevent,\n\t\t\t\t\tnew Response(`<!DOCTYPE html><html><body><script>window.opener?.postMessage({}, '*');window.close();</script></body></html>`, {\n\t\t\t\t\t\theaders: { 'content-type': 'text/html; charset=utf-8' },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn flushSetCookies(event, await redirect(new URL(returnTo, requestUrl.origin), 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(requestUrl.origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleRefresh(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst origin = requestUrl.origin;\n\t\tconst returnTo = requestUrl.searchParams.get('returnTo');\n\t\tconst safeReturnTo = toSafeRedirect(returnTo, origin);\n\n\t\tif (returnTo && !safeReturnTo) {\n\t\t\tthrow new ProtocolError(`Invalid returnTo URL: ${returnTo}. Expected a URL with the same origin as the request: ${requestUrl.origin}`);\n\t\t}\n\n\t\ttry {\n\t\t\tawait refreshSession(event);\n\n\t\t\tif (safeReturnTo) {\n\t\t\t\treturn flushSetCookies(event, await redirect(new URL(safeReturnTo, origin), 302, event));\n\t\t\t}\n\n\t\t\treturn flushSetCookies(event, new Response(null, { status: 204 }));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleRevoke(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tawait revokeSession(event);\n\n\t\t\treturn flushSetCookies(event, await redirect(new URL(options.postLogoutRedirectUri, origin), 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleEntry(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tconst data = await getEntrySession(request.url);\n\t\t\tconst uri = new URL(options.loginUri, origin);\n\t\t\turi.searchParams.set('session_id', data.session_id);\n\t\t\turi.searchParams.set('short_app_id', data.short_app_id);\n\t\t\turi.searchParams.set('language', data.language);\n\n\t\t\treturn flushSetCookies(event, await redirect(uri, 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleLogout(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tconst logoutUrl = await logout(new URL(options.postLogoutRedirectUri, origin), event);\n\t\t\treturn flushSetCookies(event, await redirect(logoutUrl, 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleBackChannelLogout(event: TEvent): Promise<Response> {\n\t\tif (typeof options.storage.deleteByLogoutToken !== 'function') {\n\t\t\treturn new Response('Back-channel logout requires a storage with deleteByLogoutToken', { status: 501 });\n\t\t}\n\n\t\tconst request = await adapter.toRequest(event);\n\t\tlet logoutToken: string | null;\n\n\t\ttry {\n\t\t\tconst contentType = request.headers.get('content-type') ?? '';\n\n\t\t\tif (contentType.includes('application/x-www-form-urlencoded')) {\n\t\t\t\tconst body = await request.formData();\n\t\t\t\tlogoutToken = body.get('logout_token') as string | null;\n\t\t\t} else {\n\t\t\t\treturn new Response('Invalid content type: expected application/x-www-form-urlencoded', { status: 400 });\n\t\t\t}\n\t\t} catch {\n\t\t\treturn new Response('Failed to parse request body', { status: 400 });\n\t\t}\n\n\t\tif (!logoutToken) {\n\t\t\treturn new Response('Missing logout_token', { status: 400 });\n\t\t}\n\n\t\tconst now = timestamp();\n\n\t\tfor (const [token, expiresAt] of seenLogoutTokenIds) {\n\t\t\tif (expiresAt <= now) {\n\t\t\t\tseenLogoutTokenIds.delete(token);\n\t\t\t}\n\t\t}\n\n\t\tif (seenLogoutTokenIds.has(logoutToken)) {\n\t\t\treturn new Response('Invalid logout_token: token already used', { status: 400 });\n\t\t}\n\n\t\tseenLogoutTokenIds.set(logoutToken, now + BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS);\n\n\t\tlet claims;\n\t\tlet metadata;\n\n\t\ttry {\n\t\t\tmetadata = await getDiscoveryDocument(options);\n\t\t\tclaims = await verifyJwt<LogoutTokenClaims>({ token: logoutToken, jwksUri: metadata.jwks_uri, options });\n\t\t} catch (error) {\n\t\t\treturn new Response(`Invalid logout_token: ${error.message}`, { status: 400 });\n\t\t}\n\n\t\tif (claims.iss !== metadata.issuer) {\n\t\t\treturn new Response('Invalid logout_token: invalid iss claim', { status: 400 });\n\t\t}\n\n\t\tif (Array.isArray(claims.aud) ? !claims.aud.includes(options.clientId) : claims.aud !== options.clientId) {\n\t\t\treturn new Response('Invalid logout_token: invalid aud claim', { status: 400 });\n\t\t}\n\n\t\tif (typeof claims.iat !== 'number' || Math.abs(now - claims.iat) > BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS) {\n\t\t\treturn new Response('Invalid logout_token: invalid or stale iat claim', { status: 400 });\n\t\t}\n\n\t\tif (!claims.jti) {\n\t\t\treturn new Response('Invalid logout_token: missing jti claim', { status: 400 });\n\t\t}\n\n\t\tif (claims.nonce !== undefined) {\n\t\t\treturn new Response('Invalid logout_token: nonce claim must not be present', { status: 400 });\n\t\t}\n\n\t\tif (!claims.events || !(BACKCHANNEL_LOGOUT_EVENT in claims.events)) {\n\t\t\treturn new Response(`Invalid logout_token: missing ${BACKCHANNEL_LOGOUT_EVENT} in events`, { status: 400 });\n\t\t}\n\n\t\tif (!claims.sid && !claims.sub) {\n\t\t\treturn new Response('Invalid logout_token: must contain sid or sub claim', { status: 400 });\n\t\t}\n\n\t\tconst token: LogoutTokenClaims = {} as never;\n\n\t\tif (claims.sid) {\n\t\t\ttoken.sid = claims.sid;\n\t\t}\n\t\tif (claims.sub) {\n\t\t\ttoken.sub = claims.sub;\n\t\t}\n\n\t\ttry {\n\t\t\tawait options.storage.deleteByLogoutToken(token);\n\t\t} catch (error) {\n\t\t\treturn new Response(`Failed to delete session: ${error.message}`, { status: 500 });\n\t\t}\n\n\t\treturn new Response(null, { status: 200 });\n\t}\n\n\tasync function handler(event: TEvent): Promise<Response | null> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/login`) {\n\t\t\treturn handleLogin(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/register`) {\n\t\t\treturn handleRegister(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/callback`) {\n\t\t\treturn handleCallback(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/refresh`) {\n\t\t\treturn handleRefresh(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/revoke`) {\n\t\t\treturn handleRevoke(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/entry`) {\n\t\t\treturn handleEntry(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/logout`) {\n\t\t\treturn handleLogout(event);\n\t\t}\n\t\tif (request.method === 'POST' && requestUrl.pathname === `${options.authUrlPrefix}/backchannel-logout`) {\n\t\t\treturn handleBackChannelLogout(event);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// endregion\n\n\tinit();\n\n\treturn {\n\t\tget options() {\n\t\t\treturn options;\n\t\t},\n\t\tgetSession,\n\t\tupdateSession,\n\t\trefreshSession,\n\t\trevokeSession,\n\t\tgetEntrySession,\n\t\tcompleteLogin,\n\t\tlogout,\n\t\thandleLogin,\n\t\thandleRegister,\n\t\thandleCallback,\n\t\thandleRefresh,\n\t\thandleRevoke,\n\t\thandleEntry,\n\t\thandleLogout,\n\t\thandleBackChannelLogout,\n\t\thandler,\n\t};\n}\n"],"mappings":"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"}
|
package/dist/server/base.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ConfigurationError as e,OidcError as t,ProtocolError as n}from"../utils/errors.mjs";import{timestamp as r}from"../utils/common.mjs";import{loadSession as i,serializeSession as a}from"../utils/session.mjs";import{a as o,g as s,h as c,n as l,o as u,p as d,t as f,x as p,y as m}from"../assets/oidc.mjs";import{a as h,c as g,d as _,l as v,o as y,s as b,t as x,u as S}from"../assets/server.mjs";var C=`strivacity-session-v1`,w=3900,T=new Set([`transfer-encoding`,`connection`,`keep-alive`,`content-encoding`]),E=`sty.returnTo`,D=120;function O(C,w){let T=y(C,w),D=new Map;function O(){if(!T.issuer){let t=new e(`Missing option: issuer`);throw T.logging?.error(`Required option missing`,t),t}if(!T.clientId){let t=new e(`Missing option: clientId`);throw T.logging?.error(`Required option missing`,t),t}if(!T.redirectUri){let t=new e(`Missing option: redirectUri`);throw T.logging?.error(`Required option missing`,t),t}if(T.scopes&&!Array.isArray(T.scopes)){let t=new e(`Invalid option: scopes`);throw T.logging?.error(`Invalid option provided`,t),t}}async function k(e,t=302,n){return C.redirect?await C.redirect(e,t,n):new Response(null,{status:t,headers:{location:e.toString()}})}async function A(e,n,r){let i=new URL(`/error`,e);return n instanceof t?(i.searchParams.set(`type`,n.category.toLowerCase()),i.searchParams.set(`error`,n.error),n.errorDescription&&i.searchParams.set(`error_description`,n.errorDescription)):n instanceof Error&&`category`in n?(i.searchParams.set(`type`,n.category.toLowerCase()),i.searchParams.set(`error`,n.name),i.searchParams.set(`error_description`,n.message)):(i.searchParams.set(`type`,`unknown`),i.searchParams.set(`error`,`unknown_error`),i.searchParams.set(`error_description`,n instanceof Error?n.message:`Unknown error`)),k(i,302,r)}async function j(e){return i(await T.storage.get(T.storageTokenName,e))}async function M(e,t){await T.storage.set(T.storageTokenName,a(e),t)}async function N(e){await T.storage.delete(T.storageTokenName,e)}async function P(t){T.logging?.debug(`Attempting to refresh session`);let r=await j(t);if(!r)throw new n(`No session available to refresh`);if(typeof r.refresh_token!=`string`)throw new e(`No refresh token available`);try{let e=await c({refreshToken:r.refresh_token,options:T,expectedSub:r.claims?.sub});return await M(e,t),T.logging?.debug(`Session refresh successful`),e}catch(e){throw await N(t),T.logging?.error(`Session refresh failed`,e),e}}async function F(e){let t=await j(e);if(t?.refresh_token?T.logging?.debug(`Attempting to revoke refresh token`):T.logging?.debug(`Attempting to revoke access token`),await N(e),!t?.access_token&&!t?.refresh_token){T.logging?.debug(`Revoke called without session`);return}let n=t.refresh_token?`refresh_token`:`access_token`,r=n===`refresh_token`?t.refresh_token:t.access_token;try{await s({tokenTypeHint:n,token:r,options:T}),n===`refresh_token`?T.logging?.info(`Refresh token successfully revoked`):T.logging?.info(`Access token successfully revoked`)}catch(e){throw T.logging?.error(`Token revocation failed`,e),e}}async function I(e){T.logging?.debug(`Attempting entry request`);let{searchParams:t}=new URL(e);try{let e=new URL(`/provider/flow/entry`,T.issuer),n=await u({url:e,params:t,sdkMode:T.mode===`embedded`?`web-embedded`:`web`,options:T});return T.logging?.debug(`Entry request successful - ${JSON.stringify(n)}`),n}catch(e){throw T.logging?.error(`Entry request failed`,e),e}}async function L(e,t){T.logging?.debug(`Exchanging authorization code for tokens`);try{let r=await o({params:e,options:T});if(!r.access_token)throw new n(`Missing access_token`);return await M(r,t),T.logging?.debug(`Token exchange successful`),T.logging&&(T.logging.xEventId=void 0,T.logging.info(`Login successful`)),r}catch(e){throw T.logging?.error(`Token exchange failed`,e),e}}async function R(e,t){T.logging?.debug(`Attempting to logout`);let n=await j(t);if(await N(t),T.logging?.debug(`Logout initiated`),!n?.id_token)return T.logging?.debug(`Logout called without id token`),new URL(e);let r=await d(T);return l({url:r.end_session_endpoint,idToken:n.id_token,postLogoutRedirectUri:new URL(e).toString()})}async function z(e,t={}){let r=await C.toRequest(e),i=new URL(r.url),{returnTo:a,...
|
|
1
|
+
import{ConfigurationError as e,OidcError as t,ProtocolError as n}from"../utils/errors.mjs";import{timestamp as r}from"../utils/common.mjs";import{loadSession as i,serializeSession as a}from"../utils/session.mjs";import{a as o,g as s,h as c,n as l,o as u,p as d,t as f,x as p,y as m}from"../assets/oidc.mjs";import{a as h,c as g,d as _,l as v,o as y,s as b,t as x,u as S}from"../assets/server.mjs";var C=`strivacity-session-v1`,w=3900,T=new Set([`transfer-encoding`,`connection`,`keep-alive`,`content-encoding`]),E=`sty.returnTo`,D=120;function O(C,w){let T=y(C,w),D=new Map;function O(){if(!T.issuer){let t=new e(`Missing option: issuer`);throw T.logging?.error(`Required option missing`,t),t}if(!T.clientId){let t=new e(`Missing option: clientId`);throw T.logging?.error(`Required option missing`,t),t}if(!T.redirectUri){let t=new e(`Missing option: redirectUri`);throw T.logging?.error(`Required option missing`,t),t}if(T.scopes&&!Array.isArray(T.scopes)){let t=new e(`Invalid option: scopes`);throw T.logging?.error(`Invalid option provided`,t),t}}async function k(e,t=302,n){return C.redirect?await C.redirect(e,t,n):new Response(null,{status:t,headers:{location:e.toString()}})}async function A(e,n,r){let i=new URL(`/error`,e);return n instanceof t?(i.searchParams.set(`type`,n.category.toLowerCase()),i.searchParams.set(`error`,n.error),n.errorDescription&&i.searchParams.set(`error_description`,n.errorDescription)):n instanceof Error&&`category`in n?(i.searchParams.set(`type`,n.category.toLowerCase()),i.searchParams.set(`error`,n.name),i.searchParams.set(`error_description`,n.message)):(i.searchParams.set(`type`,`unknown`),i.searchParams.set(`error`,`unknown_error`),i.searchParams.set(`error_description`,n instanceof Error?n.message:`Unknown error`)),k(i,302,r)}async function j(e){return i(await T.storage.get(T.storageTokenName,e))}async function M(e,t){await T.storage.set(T.storageTokenName,a(e),t)}async function N(e){await T.storage.delete(T.storageTokenName,e)}async function P(t){T.logging?.debug(`Attempting to refresh session`);let r=await j(t);if(!r)throw new n(`No session available to refresh`);if(typeof r.refresh_token!=`string`)throw new e(`No refresh token available`);try{let e=await c({refreshToken:r.refresh_token,options:T,expectedSub:r.claims?.sub});return await M(e,t),T.logging?.debug(`Session refresh successful`),e}catch(e){throw await N(t),T.logging?.error(`Session refresh failed`,e),e}}async function F(e){let t=await j(e);if(t?.refresh_token?T.logging?.debug(`Attempting to revoke refresh token`):T.logging?.debug(`Attempting to revoke access token`),await N(e),!t?.access_token&&!t?.refresh_token){T.logging?.debug(`Revoke called without session`);return}let n=t.refresh_token?`refresh_token`:`access_token`,r=n===`refresh_token`?t.refresh_token:t.access_token;try{await s({tokenTypeHint:n,token:r,options:T}),n===`refresh_token`?T.logging?.info(`Refresh token successfully revoked`):T.logging?.info(`Access token successfully revoked`)}catch(e){throw T.logging?.error(`Token revocation failed`,e),e}}async function I(e){T.logging?.debug(`Attempting entry request`);let{searchParams:t}=new URL(e);try{let e=new URL(`/provider/flow/entry`,T.issuer),n=await u({url:e,params:t,sdkMode:T.mode===`embedded`?`web-embedded`:`web`,options:T});return T.logging?.debug(`Entry request successful - ${JSON.stringify(n)}`),n}catch(e){throw T.logging?.error(`Entry request failed`,e),e}}async function L(e,t){T.logging?.debug(`Exchanging authorization code for tokens`);try{let r=await o({params:e,options:T});if(!r.access_token)throw new n(`Missing access_token`);return await M(r,t),T.logging?.debug(`Token exchange successful`),T.logging&&(T.logging.xEventId=void 0,T.logging.info(`Login successful`)),r}catch(e){throw T.logging?.error(`Token exchange failed`,e),e}}async function R(e,t){T.logging?.debug(`Attempting to logout`);let n=await j(t);if(await N(t),T.logging?.debug(`Logout initiated`),!n?.id_token)return T.logging?.debug(`Logout called without id token`),new URL(e);let r=await d(T);return l({url:r.end_session_endpoint,idToken:n.id_token,postLogoutRedirectUri:new URL(e).toString()})}async function z(e,t={}){let r=await C.toRequest(e),i=new URL(r.url),{returnTo:a,prompt:o,display:s,login_hint:c,acr_values:l,ui_locales:u,audience:d,...p}=Object.fromEntries(i.searchParams),m=_(a,i.origin),y=await f({params:{prompt:o??p.prompt,display:s??p.display,loginHint:c??p.loginHint,acrValues:(l??p.acrValues)?.split(` `),uiLocales:(u??p.uiLocales)?.split(` `),audiences:(d??p.audiences)?.split(` `),...t},options:T});if(a&&!m)throw new n(`Invalid returnTo URL: ${a}. Expected a URL with the same origin as the request: ${i.origin}`);[`embedded`,`native`].includes(T.mode)&&p.sdk&&y.searchParams.set(`sdk`,p.sdk);let b=await T.httpClient.request(y,{method:`GET`,credentials:`include`,redirect:`manual`});return T.logging?.debug(`Attempting to redirect for login`),m&&v(e,S(E,m)),h(e,g(b))}async function B(e){return z(e,{prompt:`create`})}async function V(e){let t=await C.toRequest(e),r=new URL(t.url),i=Object.fromEntries(r.searchParams);try{let a=await T.stateStorage.get(`sty.${i.state}`);if(!a)throw new n(`State not found or expired. Please try logging in again.`);await L(i,e);let o=p(a),s=b(t.headers.get(`cookie`))[`sty.returnTo`]??T.postLoginRedirectUri;return v(e,S(E,``,{expires:new Date(0)})),o.metadata?.display===`popup`?h(e,new Response(`<!DOCTYPE html><html><body><script>window.opener?.postMessage({}, '*');window.close();<\/script></body></html>`,{headers:{"content-type":`text/html; charset=utf-8`}})):h(e,await k(new URL(s,r.origin),302,e))}catch(t){return h(e,await A(r.origin,t,e))}}async function H(e){let t=await C.toRequest(e),r=new URL(t.url),i=r.origin,a=r.searchParams.get(`returnTo`),o=_(a,i);if(a&&!o)throw new n(`Invalid returnTo URL: ${a}. Expected a URL with the same origin as the request: ${r.origin}`);try{return await P(e),o?h(e,await k(new URL(o,i),302,e)):h(e,new Response(null,{status:204}))}catch(t){return h(e,await A(i,t,e))}}async function U(e){let t=await C.toRequest(e),n=new URL(t.url).origin;try{return await F(e),h(e,await k(new URL(T.postLogoutRedirectUri,n),302,e))}catch(t){return h(e,await A(n,t,e))}}async function W(e){let t=await C.toRequest(e),n=new URL(t.url).origin;try{let r=await I(t.url),i=new URL(T.loginUri,n);return i.searchParams.set(`session_id`,r.session_id),i.searchParams.set(`short_app_id`,r.short_app_id),i.searchParams.set(`language`,r.language),h(e,await k(i,302,e))}catch(t){return h(e,await A(n,t,e))}}async function G(e){let t=await C.toRequest(e),n=new URL(t.url).origin;try{let t=await R(new URL(T.postLogoutRedirectUri,n),e);return h(e,await k(t,302,e))}catch(t){return h(e,await A(n,t,e))}}async function K(e){if(typeof T.storage.deleteByLogoutToken!=`function`)return new Response(`Back-channel logout requires a storage with deleteByLogoutToken`,{status:501});let t=await C.toRequest(e),n;try{if((t.headers.get(`content-type`)??``).includes(`application/x-www-form-urlencoded`))n=(await t.formData()).get(`logout_token`);else return new Response(`Invalid content type: expected application/x-www-form-urlencoded`,{status:400})}catch{return new Response(`Failed to parse request body`,{status:400})}if(!n)return new Response(`Missing logout_token`,{status:400});let i=r();for(let[e,t]of D)t<=i&&D.delete(e);if(D.has(n))return new Response(`Invalid logout_token: token already used`,{status:400});D.set(n,i+120);let a,o;try{o=await d(T),a=await m({token:n,jwksUri:o.jwks_uri,options:T})}catch(e){return new Response(`Invalid logout_token: ${e.message}`,{status:400})}if(a.iss!==o.issuer)return new Response(`Invalid logout_token: invalid iss claim`,{status:400});if(Array.isArray(a.aud)?!a.aud.includes(T.clientId):a.aud!==T.clientId)return new Response(`Invalid logout_token: invalid aud claim`,{status:400});if(typeof a.iat!=`number`||Math.abs(i-a.iat)>120)return new Response(`Invalid logout_token: invalid or stale iat claim`,{status:400});if(!a.jti)return new Response(`Invalid logout_token: missing jti claim`,{status:400});if(a.nonce!==void 0)return new Response(`Invalid logout_token: nonce claim must not be present`,{status:400});if(!a.events||!(`http://schemas.openid.net/event/backchannel-logout`in a.events))return new Response(`Invalid logout_token: missing ${x} in events`,{status:400});if(!a.sid&&!a.sub)return new Response(`Invalid logout_token: must contain sid or sub claim`,{status:400});let s={};a.sid&&(s.sid=a.sid),a.sub&&(s.sub=a.sub);try{await T.storage.deleteByLogoutToken(s)}catch(e){return new Response(`Failed to delete session: ${e.message}`,{status:500})}return new Response(null,{status:200})}async function q(e){let t=await C.toRequest(e),n=new URL(t.url);return t.method===`GET`&&n.pathname===`${T.authUrlPrefix}/login`?z(e):t.method===`GET`&&n.pathname===`${T.authUrlPrefix}/register`?B(e):t.method===`GET`&&n.pathname===`${T.authUrlPrefix}/callback`?V(e):t.method===`GET`&&n.pathname===`${T.authUrlPrefix}/refresh`?H(e):t.method===`GET`&&n.pathname===`${T.authUrlPrefix}/revoke`?U(e):t.method===`GET`&&n.pathname===`${T.authUrlPrefix}/entry`?W(e):t.method===`GET`&&n.pathname===`${T.authUrlPrefix}/logout`?G(e):t.method===`POST`&&n.pathname===`${T.authUrlPrefix}/backchannel-logout`?K(e):null}return O(),{get options(){return T},getSession:j,updateSession:M,refreshSession:P,revokeSession:F,getEntrySession:I,completeLogin:L,logout:R,handleLogin:z,handleRegister:B,handleCallback:V,handleRefresh:H,handleRevoke:U,handleEntry:W,handleLogout:G,handleBackChannelLogout:K,handler:q}}export{D as BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS,w as COOKIE_CHUNK_SIZE,C as COOKIE_CONTEXT,T as DISALLOWED_PROXY_HEADERS,E as RETURN_TO_COOKIE,O as createBaseServerSDK};
|
|
2
2
|
//# sourceMappingURL=base.mjs.map
|
package/dist/server/base.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.mjs","names":[],"sources":["../../src/server/base.ts"],"sourcesContent":["import type { SDKStorage } from '../types/common';\nimport type { SessionData, LogoutTokenClaims } from '../types/oidc';\nimport type { BaseServerSDK, ServerAdapter, ServerStorage, ServerSDKInitConfig } from '../types/server';\nimport {\n\tbuildEndSessionUrl,\n\tbuildAuthorizationUrl,\n\trevokeToken,\n\trefreshToken,\n\texchangeCode,\n\tverifyJwt,\n\tfetchFlowEntry,\n\tgetDiscoveryDocument,\n} from '../utils/oidc';\nimport { loadSession, serializeSession } from '../utils/session';\nimport { parseState } from '../utils/state';\nimport { timestamp } from '../utils/common';\nimport { ConfigurationError, OidcError, ProtocolError, type FailureCategory } from '../utils/errors';\nimport {\n\tpushSetCookie,\n\tflushSetCookies,\n\tparseCookieHeader,\n\tserializeCookie,\n\tproxyResponse,\n\ttoSafeRedirect,\n\tgetServerSDKOptions,\n\tBACKCHANNEL_LOGOUT_EVENT,\n} from '../utils/server';\n\nexport const COOKIE_CONTEXT = 'strivacity-session-v1';\nexport const COOKIE_CHUNK_SIZE = 3900;\nexport const DISALLOWED_PROXY_HEADERS = new Set(['transfer-encoding', 'connection', 'keep-alive', 'content-encoding']);\nexport const RETURN_TO_COOKIE = 'sty.returnTo';\nexport const BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS = 120;\n\n/**\n * Creates the framework-agnostic Strivacity base server SDK.\n *\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter converting `TEvent` to a standard `Request`.\n * @param {ServerSDKOptions<TEvent, Storage, StateStorage>} initConfig - The initial configuration for the server SDK.\n * @returns {BaseServerSDK<TEvent>} The initialized, framework-agnostic server SDK core.\n */\nexport function createBaseServerSDK<\n\tTEvent = unknown,\n\tStorage extends ServerStorage<TEvent> = ServerStorage<TEvent>,\n\tStateStorage extends SDKStorage = SDKStorage,\n>(adapter: ServerAdapter<TEvent>, initConfig: ServerSDKInitConfig<TEvent, Storage, StateStorage>): BaseServerSDK<TEvent> {\n\tconst options = getServerSDKOptions(adapter, initConfig);\n\tconst seenLogoutTokenIds = new Map<string, number>();\n\n\tfunction init() {\n\t\tif (!options.issuer) {\n\t\t\tconst error = new ConfigurationError('Missing option: issuer');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (!options.clientId) {\n\t\t\tconst error = new ConfigurationError('Missing option: clientId');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (!options.redirectUri) {\n\t\t\tconst error = new ConfigurationError('Missing option: redirectUri');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (options.scopes && !Array.isArray(options.scopes)) {\n\t\t\tconst error = new ConfigurationError('Invalid option: scopes');\n\t\t\toptions.logging?.error('Invalid option provided', error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function redirect(url: string | URL, status = 302, event?: TEvent): Promise<Response> {\n\t\tif (adapter.redirect) {\n\t\t\treturn await adapter.redirect(url, status, event);\n\t\t}\n\n\t\treturn new Response(null, { status, headers: { location: url.toString() } });\n\t}\n\n\tasync function errorRedirect(origin: string, error: unknown, event?: TEvent): Promise<Response> {\n\t\tconst url = new URL('/error', origin);\n\n\t\tif (error instanceof OidcError) {\n\t\t\turl.searchParams.set('type', error.category.toLowerCase());\n\t\t\turl.searchParams.set('error', error.error);\n\t\t\tif (error.errorDescription) {\n\t\t\t\turl.searchParams.set('error_description', error.errorDescription);\n\t\t\t}\n\t\t} else if (error instanceof Error && 'category' in error) {\n\t\t\turl.searchParams.set('type', (error as { category: FailureCategory }).category.toLowerCase());\n\t\t\turl.searchParams.set('error', error.name);\n\t\t\turl.searchParams.set('error_description', error.message);\n\t\t} else {\n\t\t\turl.searchParams.set('type', 'unknown');\n\t\t\turl.searchParams.set('error', 'unknown_error');\n\t\t\turl.searchParams.set('error_description', error instanceof Error ? error.message : 'Unknown error');\n\t\t}\n\n\t\treturn redirect(url, 302, event);\n\t}\n\n\tasync function getSession(event?: TEvent): Promise<SessionData | null> {\n\t\treturn loadSession(await options.storage.get(options.storageTokenName, event));\n\t}\n\n\tasync function updateSession(session: SessionData, event?: TEvent): Promise<void> {\n\t\tawait options.storage.set(options.storageTokenName, serializeSession(session), event);\n\t}\n\n\tasync function cleanupSession(event?: TEvent): Promise<void> {\n\t\tawait options.storage.delete(options.storageTokenName, event);\n\t}\n\n\tasync function refreshSession(event?: TEvent): Promise<SessionData> {\n\t\toptions.logging?.debug('Attempting to refresh session');\n\n\t\tconst currentSession = await getSession(event);\n\n\t\tif (!currentSession) {\n\t\t\tthrow new ProtocolError('No session available to refresh');\n\t\t}\n\n\t\tif (typeof currentSession.refresh_token !== 'string') {\n\t\t\tthrow new ConfigurationError('No refresh token available');\n\t\t}\n\n\t\ttry {\n\t\t\tconst newSession = await refreshToken({ refreshToken: currentSession.refresh_token, options, expectedSub: currentSession.claims?.sub });\n\t\t\tawait updateSession(newSession, event);\n\n\t\t\toptions.logging?.debug('Session refresh successful');\n\n\t\t\treturn newSession;\n\t\t} catch (error) {\n\t\t\tawait cleanupSession(event);\n\t\t\toptions.logging?.error('Session refresh failed', error as Error);\n\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function revokeSession(event?: TEvent): Promise<void> {\n\t\tconst currentSession = await getSession(event);\n\n\t\tif (currentSession?.refresh_token) {\n\t\t\toptions.logging?.debug('Attempting to revoke refresh token');\n\t\t} else {\n\t\t\toptions.logging?.debug('Attempting to revoke access token');\n\t\t}\n\n\t\t// NOTE: Cleanup session before revocation\n\t\tawait cleanupSession(event);\n\n\t\tif (!currentSession?.access_token && !currentSession?.refresh_token) {\n\t\t\toptions.logging?.debug('Revoke called without session');\n\t\t\treturn;\n\t\t}\n\n\t\tconst tokenTypeHint = currentSession.refresh_token ? 'refresh_token' : 'access_token';\n\t\tconst token = (tokenTypeHint === 'refresh_token' ? currentSession.refresh_token : currentSession.access_token)!;\n\n\t\ttry {\n\t\t\tawait revokeToken({ tokenTypeHint, token, options });\n\n\t\t\tif (tokenTypeHint === 'refresh_token') {\n\t\t\t\toptions.logging?.info('Refresh token successfully revoked');\n\t\t\t} else {\n\t\t\t\toptions.logging?.info('Access token successfully revoked');\n\t\t\t}\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Token revocation failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function getEntrySession(entryUrl: string | URL): Promise<Record<string, string>> {\n\t\toptions.logging?.debug('Attempting entry request');\n\n\t\tconst { searchParams: params } = new URL(entryUrl);\n\n\t\ttry {\n\t\t\tconst url = new URL('/provider/flow/entry', options.issuer);\n\t\t\tconst data = await fetchFlowEntry({\n\t\t\t\turl,\n\t\t\t\tparams,\n\t\t\t\tsdkMode: options.mode === 'embedded' ? 'web-embedded' : 'web',\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\toptions.logging?.debug(`Entry request successful - ${JSON.stringify(data)}`);\n\n\t\t\treturn data;\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Entry request failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function completeLogin(params: Record<string, string>, event?: TEvent): Promise<SessionData> {\n\t\toptions.logging?.debug('Exchanging authorization code for tokens');\n\n\t\ttry {\n\t\t\tconst session = await exchangeCode({ params, options });\n\n\t\t\tif (!session.access_token) {\n\t\t\t\tthrow new ProtocolError('Missing access_token');\n\t\t\t}\n\n\t\t\tawait updateSession(session, event);\n\n\t\t\toptions.logging?.debug('Token exchange successful');\n\n\t\t\tif (options.logging) {\n\t\t\t\toptions.logging.xEventId = undefined;\n\t\t\t\toptions.logging.info('Login successful');\n\t\t\t}\n\n\t\t\treturn session;\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Token exchange failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function logout(postLogoutRedirectUri: string | URL, event?: TEvent): Promise<URL> {\n\t\toptions.logging?.debug('Attempting to logout');\n\n\t\t// NOTE: Cleanup session before logout\n\t\tconst currentSession = await getSession(event);\n\t\tawait cleanupSession(event);\n\n\t\toptions.logging?.debug('Logout initiated');\n\n\t\tif (!currentSession?.id_token) {\n\t\t\toptions.logging?.debug('Logout called without id token');\n\t\t\treturn new URL(postLogoutRedirectUri);\n\t\t}\n\n\t\tconst metadata = await getDiscoveryDocument(options);\n\n\t\treturn buildEndSessionUrl({\n\t\t\turl: metadata.end_session_endpoint,\n\t\t\tidToken: currentSession.id_token,\n\t\t\tpostLogoutRedirectUri: new URL(postLogoutRedirectUri).toString(),\n\t\t});\n\t}\n\n\tasync function handleLogin(event: TEvent, extraParams: Record<string, unknown> = {}): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst { returnTo, ...params } = Object.fromEntries(requestUrl.searchParams);\n\t\tconst safeReturnTo = toSafeRedirect(returnTo, requestUrl.origin);\n\t\tconst url = await buildAuthorizationUrl({ params: { ...params, ...extraParams }, options });\n\n\t\tif (returnTo && !safeReturnTo) {\n\t\t\tthrow new ProtocolError(`Invalid returnTo URL: ${returnTo}. Expected a URL with the same origin as the request: ${requestUrl.origin}`);\n\t\t}\n\n\t\tif (['embedded', 'native'].includes(options.mode) && params.sdk) {\n\t\t\turl.searchParams.set('sdk', params.sdk);\n\t\t}\n\n\t\tconst startResponse = await options.httpClient.request<string>(url, {\n\t\t\tmethod: 'GET',\n\t\t\tcredentials: 'include',\n\t\t\tredirect: 'manual',\n\t\t});\n\n\t\toptions.logging?.debug('Attempting to redirect for login');\n\n\t\tif (safeReturnTo) {\n\t\t\tpushSetCookie(event, serializeCookie(RETURN_TO_COOKIE, safeReturnTo));\n\t\t}\n\n\t\treturn flushSetCookies(event, proxyResponse(startResponse));\n\t}\n\n\tasync function handleRegister(event: TEvent): Promise<Response> {\n\t\treturn handleLogin(event, { prompt: 'create' });\n\t}\n\n\tasync function handleCallback(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst params = Object.fromEntries(requestUrl.searchParams);\n\n\t\ttry {\n\t\t\tconst serializedState = await options.stateStorage.get(`sty.${params.state}`);\n\n\t\t\tif (!serializedState) {\n\t\t\t\tthrow new ProtocolError('State not found or expired. Please try logging in again.');\n\t\t\t}\n\n\t\t\tawait completeLogin(params, event);\n\n\t\t\tconst state = parseState(serializedState);\n\t\t\tconst returnTo = parseCookieHeader(request.headers.get('cookie'))[RETURN_TO_COOKIE] ?? options.postLoginRedirectUri;\n\n\t\t\tpushSetCookie(event, serializeCookie(RETURN_TO_COOKIE, '', { expires: new Date(0) }));\n\n\t\t\tif (state.metadata?.display === 'popup') {\n\t\t\t\t// NOTE: If the login was initiated from a popup, we return a HTML page that will close the popup and notify the opener window.\n\t\t\t\treturn flushSetCookies(\n\t\t\t\t\tevent,\n\t\t\t\t\tnew Response(`<!DOCTYPE html><html><body><script>window.opener?.postMessage({}, '*');window.close();</script></body></html>`, {\n\t\t\t\t\t\theaders: { 'content-type': 'text/html; charset=utf-8' },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn flushSetCookies(event, await redirect(new URL(returnTo, requestUrl.origin), 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(requestUrl.origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleRefresh(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst origin = requestUrl.origin;\n\t\tconst returnTo = requestUrl.searchParams.get('returnTo');\n\t\tconst safeReturnTo = toSafeRedirect(returnTo, origin);\n\n\t\tif (returnTo && !safeReturnTo) {\n\t\t\tthrow new ProtocolError(`Invalid returnTo URL: ${returnTo}. Expected a URL with the same origin as the request: ${requestUrl.origin}`);\n\t\t}\n\n\t\ttry {\n\t\t\tawait refreshSession(event);\n\n\t\t\tif (safeReturnTo) {\n\t\t\t\treturn flushSetCookies(event, await redirect(new URL(safeReturnTo, origin), 302, event));\n\t\t\t}\n\n\t\t\treturn flushSetCookies(event, new Response(null, { status: 204 }));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleRevoke(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tawait revokeSession(event);\n\n\t\t\treturn flushSetCookies(event, await redirect(new URL(options.postLogoutRedirectUri, origin), 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleEntry(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tconst data = await getEntrySession(request.url);\n\t\t\tconst uri = new URL(options.loginUri, origin);\n\t\t\turi.searchParams.set('session_id', data.session_id);\n\t\t\turi.searchParams.set('short_app_id', data.short_app_id);\n\t\t\turi.searchParams.set('language', data.language);\n\n\t\t\treturn flushSetCookies(event, await redirect(uri, 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleLogout(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tconst logoutUrl = await logout(new URL(options.postLogoutRedirectUri, origin), event);\n\t\t\treturn flushSetCookies(event, await redirect(logoutUrl, 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleBackChannelLogout(event: TEvent): Promise<Response> {\n\t\tif (typeof options.storage.deleteByLogoutToken !== 'function') {\n\t\t\treturn new Response('Back-channel logout requires a storage with deleteByLogoutToken', { status: 501 });\n\t\t}\n\n\t\tconst request = await adapter.toRequest(event);\n\t\tlet logoutToken: string | null;\n\n\t\ttry {\n\t\t\tconst contentType = request.headers.get('content-type') ?? '';\n\n\t\t\tif (contentType.includes('application/x-www-form-urlencoded')) {\n\t\t\t\tconst body = await request.formData();\n\t\t\t\tlogoutToken = body.get('logout_token') as string | null;\n\t\t\t} else {\n\t\t\t\treturn new Response('Invalid content type: expected application/x-www-form-urlencoded', { status: 400 });\n\t\t\t}\n\t\t} catch {\n\t\t\treturn new Response('Failed to parse request body', { status: 400 });\n\t\t}\n\n\t\tif (!logoutToken) {\n\t\t\treturn new Response('Missing logout_token', { status: 400 });\n\t\t}\n\n\t\tconst now = timestamp();\n\n\t\tfor (const [token, expiresAt] of seenLogoutTokenIds) {\n\t\t\tif (expiresAt <= now) {\n\t\t\t\tseenLogoutTokenIds.delete(token);\n\t\t\t}\n\t\t}\n\n\t\tif (seenLogoutTokenIds.has(logoutToken)) {\n\t\t\treturn new Response('Invalid logout_token: token already used', { status: 400 });\n\t\t}\n\n\t\tseenLogoutTokenIds.set(logoutToken, now + BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS);\n\n\t\tlet claims;\n\t\tlet metadata;\n\n\t\ttry {\n\t\t\tmetadata = await getDiscoveryDocument(options);\n\t\t\tclaims = await verifyJwt<LogoutTokenClaims>({ token: logoutToken, jwksUri: metadata.jwks_uri, options });\n\t\t} catch (error) {\n\t\t\treturn new Response(`Invalid logout_token: ${error.message}`, { status: 400 });\n\t\t}\n\n\t\tif (claims.iss !== metadata.issuer) {\n\t\t\treturn new Response('Invalid logout_token: invalid iss claim', { status: 400 });\n\t\t}\n\n\t\tif (Array.isArray(claims.aud) ? !claims.aud.includes(options.clientId) : claims.aud !== options.clientId) {\n\t\t\treturn new Response('Invalid logout_token: invalid aud claim', { status: 400 });\n\t\t}\n\n\t\tif (typeof claims.iat !== 'number' || Math.abs(now - claims.iat) > BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS) {\n\t\t\treturn new Response('Invalid logout_token: invalid or stale iat claim', { status: 400 });\n\t\t}\n\n\t\tif (!claims.jti) {\n\t\t\treturn new Response('Invalid logout_token: missing jti claim', { status: 400 });\n\t\t}\n\n\t\tif (claims.nonce !== undefined) {\n\t\t\treturn new Response('Invalid logout_token: nonce claim must not be present', { status: 400 });\n\t\t}\n\n\t\tif (!claims.events || !(BACKCHANNEL_LOGOUT_EVENT in claims.events)) {\n\t\t\treturn new Response(`Invalid logout_token: missing ${BACKCHANNEL_LOGOUT_EVENT} in events`, { status: 400 });\n\t\t}\n\n\t\tif (!claims.sid && !claims.sub) {\n\t\t\treturn new Response('Invalid logout_token: must contain sid or sub claim', { status: 400 });\n\t\t}\n\n\t\tconst token: LogoutTokenClaims = {} as never;\n\n\t\tif (claims.sid) {\n\t\t\ttoken.sid = claims.sid;\n\t\t}\n\t\tif (claims.sub) {\n\t\t\ttoken.sub = claims.sub;\n\t\t}\n\n\t\ttry {\n\t\t\tawait options.storage.deleteByLogoutToken(token);\n\t\t} catch (error) {\n\t\t\treturn new Response(`Failed to delete session: ${error.message}`, { status: 500 });\n\t\t}\n\n\t\treturn new Response(null, { status: 200 });\n\t}\n\n\tasync function handler(event: TEvent): Promise<Response | null> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/login`) {\n\t\t\treturn handleLogin(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/register`) {\n\t\t\treturn handleRegister(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/callback`) {\n\t\t\treturn handleCallback(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/refresh`) {\n\t\t\treturn handleRefresh(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/revoke`) {\n\t\t\treturn handleRevoke(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/entry`) {\n\t\t\treturn handleEntry(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/logout`) {\n\t\t\treturn handleLogout(event);\n\t\t}\n\t\tif (request.method === 'POST' && requestUrl.pathname === `${options.authUrlPrefix}/backchannel-logout`) {\n\t\t\treturn handleBackChannelLogout(event);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// endregion\n\n\tinit();\n\n\treturn {\n\t\tget options() {\n\t\t\treturn options;\n\t\t},\n\t\tgetSession,\n\t\tupdateSession,\n\t\trefreshSession,\n\t\trevokeSession,\n\t\tgetEntrySession,\n\t\tcompleteLogin,\n\t\tlogout,\n\t\thandleLogin,\n\t\thandleRegister,\n\t\thandleCallback,\n\t\thandleRefresh,\n\t\thandleRevoke,\n\t\thandleEntry,\n\t\thandleLogout,\n\t\thandleBackChannelLogout,\n\t\thandler,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"base.mjs","names":[],"sources":["../../src/server/base.ts"],"sourcesContent":["import type { SDKStorage } from '../types/common';\nimport type { SessionData, LogoutTokenClaims } from '../types/oidc';\nimport type { BaseServerSDK, ServerAdapter, ServerStorage, ServerSDKInitConfig } from '../types/server';\nimport {\n\tbuildEndSessionUrl,\n\tbuildAuthorizationUrl,\n\trevokeToken,\n\trefreshToken,\n\texchangeCode,\n\tverifyJwt,\n\tfetchFlowEntry,\n\tgetDiscoveryDocument,\n} from '../utils/oidc';\nimport { loadSession, serializeSession } from '../utils/session';\nimport { parseState } from '../utils/state';\nimport { timestamp } from '../utils/common';\nimport { ConfigurationError, OidcError, ProtocolError, type FailureCategory } from '../utils/errors';\nimport {\n\tpushSetCookie,\n\tflushSetCookies,\n\tparseCookieHeader,\n\tserializeCookie,\n\tproxyResponse,\n\ttoSafeRedirect,\n\tgetServerSDKOptions,\n\tBACKCHANNEL_LOGOUT_EVENT,\n} from '../utils/server';\n\nexport const COOKIE_CONTEXT = 'strivacity-session-v1';\nexport const COOKIE_CHUNK_SIZE = 3900;\nexport const DISALLOWED_PROXY_HEADERS = new Set(['transfer-encoding', 'connection', 'keep-alive', 'content-encoding']);\nexport const RETURN_TO_COOKIE = 'sty.returnTo';\nexport const BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS = 120;\n\n/**\n * Creates the framework-agnostic Strivacity base server SDK.\n *\n * @param {ServerAdapter<TEvent>} adapter - The framework adapter converting `TEvent` to a standard `Request`.\n * @param {ServerSDKOptions<TEvent, Storage, StateStorage>} initConfig - The initial configuration for the server SDK.\n * @returns {BaseServerSDK<TEvent>} The initialized, framework-agnostic server SDK core.\n */\nexport function createBaseServerSDK<\n\tTEvent = unknown,\n\tStorage extends ServerStorage<TEvent> = ServerStorage<TEvent>,\n\tStateStorage extends SDKStorage = SDKStorage,\n>(adapter: ServerAdapter<TEvent>, initConfig: ServerSDKInitConfig<TEvent, Storage, StateStorage>): BaseServerSDK<TEvent> {\n\tconst options = getServerSDKOptions(adapter, initConfig);\n\tconst seenLogoutTokenIds = new Map<string, number>();\n\n\tfunction init() {\n\t\tif (!options.issuer) {\n\t\t\tconst error = new ConfigurationError('Missing option: issuer');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (!options.clientId) {\n\t\t\tconst error = new ConfigurationError('Missing option: clientId');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (!options.redirectUri) {\n\t\t\tconst error = new ConfigurationError('Missing option: redirectUri');\n\t\t\toptions.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (options.scopes && !Array.isArray(options.scopes)) {\n\t\t\tconst error = new ConfigurationError('Invalid option: scopes');\n\t\t\toptions.logging?.error('Invalid option provided', error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function redirect(url: string | URL, status = 302, event?: TEvent): Promise<Response> {\n\t\tif (adapter.redirect) {\n\t\t\treturn await adapter.redirect(url, status, event);\n\t\t}\n\n\t\treturn new Response(null, { status, headers: { location: url.toString() } });\n\t}\n\n\tasync function errorRedirect(origin: string, error: unknown, event?: TEvent): Promise<Response> {\n\t\tconst url = new URL('/error', origin);\n\n\t\tif (error instanceof OidcError) {\n\t\t\turl.searchParams.set('type', error.category.toLowerCase());\n\t\t\turl.searchParams.set('error', error.error);\n\t\t\tif (error.errorDescription) {\n\t\t\t\turl.searchParams.set('error_description', error.errorDescription);\n\t\t\t}\n\t\t} else if (error instanceof Error && 'category' in error) {\n\t\t\turl.searchParams.set('type', (error as { category: FailureCategory }).category.toLowerCase());\n\t\t\turl.searchParams.set('error', error.name);\n\t\t\turl.searchParams.set('error_description', error.message);\n\t\t} else {\n\t\t\turl.searchParams.set('type', 'unknown');\n\t\t\turl.searchParams.set('error', 'unknown_error');\n\t\t\turl.searchParams.set('error_description', error instanceof Error ? error.message : 'Unknown error');\n\t\t}\n\n\t\treturn redirect(url, 302, event);\n\t}\n\n\tasync function getSession(event?: TEvent): Promise<SessionData | null> {\n\t\treturn loadSession(await options.storage.get(options.storageTokenName, event));\n\t}\n\n\tasync function updateSession(session: SessionData, event?: TEvent): Promise<void> {\n\t\tawait options.storage.set(options.storageTokenName, serializeSession(session), event);\n\t}\n\n\tasync function cleanupSession(event?: TEvent): Promise<void> {\n\t\tawait options.storage.delete(options.storageTokenName, event);\n\t}\n\n\tasync function refreshSession(event?: TEvent): Promise<SessionData> {\n\t\toptions.logging?.debug('Attempting to refresh session');\n\n\t\tconst currentSession = await getSession(event);\n\n\t\tif (!currentSession) {\n\t\t\tthrow new ProtocolError('No session available to refresh');\n\t\t}\n\n\t\tif (typeof currentSession.refresh_token !== 'string') {\n\t\t\tthrow new ConfigurationError('No refresh token available');\n\t\t}\n\n\t\ttry {\n\t\t\tconst newSession = await refreshToken({ refreshToken: currentSession.refresh_token, options, expectedSub: currentSession.claims?.sub });\n\t\t\tawait updateSession(newSession, event);\n\n\t\t\toptions.logging?.debug('Session refresh successful');\n\n\t\t\treturn newSession;\n\t\t} catch (error) {\n\t\t\tawait cleanupSession(event);\n\t\t\toptions.logging?.error('Session refresh failed', error as Error);\n\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function revokeSession(event?: TEvent): Promise<void> {\n\t\tconst currentSession = await getSession(event);\n\n\t\tif (currentSession?.refresh_token) {\n\t\t\toptions.logging?.debug('Attempting to revoke refresh token');\n\t\t} else {\n\t\t\toptions.logging?.debug('Attempting to revoke access token');\n\t\t}\n\n\t\t// NOTE: Cleanup session before revocation\n\t\tawait cleanupSession(event);\n\n\t\tif (!currentSession?.access_token && !currentSession?.refresh_token) {\n\t\t\toptions.logging?.debug('Revoke called without session');\n\t\t\treturn;\n\t\t}\n\n\t\tconst tokenTypeHint = currentSession.refresh_token ? 'refresh_token' : 'access_token';\n\t\tconst token = (tokenTypeHint === 'refresh_token' ? currentSession.refresh_token : currentSession.access_token)!;\n\n\t\ttry {\n\t\t\tawait revokeToken({ tokenTypeHint, token, options });\n\n\t\t\tif (tokenTypeHint === 'refresh_token') {\n\t\t\t\toptions.logging?.info('Refresh token successfully revoked');\n\t\t\t} else {\n\t\t\t\toptions.logging?.info('Access token successfully revoked');\n\t\t\t}\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Token revocation failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function getEntrySession(entryUrl: string | URL): Promise<Record<string, string>> {\n\t\toptions.logging?.debug('Attempting entry request');\n\n\t\tconst { searchParams: params } = new URL(entryUrl);\n\n\t\ttry {\n\t\t\tconst url = new URL('/provider/flow/entry', options.issuer);\n\t\t\tconst data = await fetchFlowEntry({\n\t\t\t\turl,\n\t\t\t\tparams,\n\t\t\t\tsdkMode: options.mode === 'embedded' ? 'web-embedded' : 'web',\n\t\t\t\toptions,\n\t\t\t});\n\n\t\t\toptions.logging?.debug(`Entry request successful - ${JSON.stringify(data)}`);\n\n\t\t\treturn data;\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Entry request failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function completeLogin(params: Record<string, string>, event?: TEvent): Promise<SessionData> {\n\t\toptions.logging?.debug('Exchanging authorization code for tokens');\n\n\t\ttry {\n\t\t\tconst session = await exchangeCode({ params, options });\n\n\t\t\tif (!session.access_token) {\n\t\t\t\tthrow new ProtocolError('Missing access_token');\n\t\t\t}\n\n\t\t\tawait updateSession(session, event);\n\n\t\t\toptions.logging?.debug('Token exchange successful');\n\n\t\t\tif (options.logging) {\n\t\t\t\toptions.logging.xEventId = undefined;\n\t\t\t\toptions.logging.info('Login successful');\n\t\t\t}\n\n\t\t\treturn session;\n\t\t} catch (error) {\n\t\t\toptions.logging?.error('Token exchange failed', error as Error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function logout(postLogoutRedirectUri: string | URL, event?: TEvent): Promise<URL> {\n\t\toptions.logging?.debug('Attempting to logout');\n\n\t\t// NOTE: Cleanup session before logout\n\t\tconst currentSession = await getSession(event);\n\t\tawait cleanupSession(event);\n\n\t\toptions.logging?.debug('Logout initiated');\n\n\t\tif (!currentSession?.id_token) {\n\t\t\toptions.logging?.debug('Logout called without id token');\n\t\t\treturn new URL(postLogoutRedirectUri);\n\t\t}\n\n\t\tconst metadata = await getDiscoveryDocument(options);\n\n\t\treturn buildEndSessionUrl({\n\t\t\turl: metadata.end_session_endpoint,\n\t\t\tidToken: currentSession.id_token,\n\t\t\tpostLogoutRedirectUri: new URL(postLogoutRedirectUri).toString(),\n\t\t});\n\t}\n\n\tasync function handleLogin(event: TEvent, extraParams: Record<string, unknown> = {}): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst { returnTo, prompt, display, login_hint, acr_values, ui_locales, audience, ...params } = Object.fromEntries(requestUrl.searchParams);\n\t\tconst safeReturnTo = toSafeRedirect(returnTo, requestUrl.origin);\n\t\tconst url = await buildAuthorizationUrl({\n\t\t\tparams: {\n\t\t\t\tprompt: prompt ?? params.prompt,\n\t\t\t\tdisplay: display ?? params.display,\n\t\t\t\tloginHint: login_hint ?? params.loginHint,\n\t\t\t\tacrValues: (acr_values ?? params.acrValues)?.split(' '),\n\t\t\t\tuiLocales: (ui_locales ?? params.uiLocales)?.split(' '),\n\t\t\t\taudiences: (audience ?? params.audiences)?.split(' '),\n\t\t\t\t...extraParams,\n\t\t\t},\n\t\t\toptions,\n\t\t});\n\n\t\tif (returnTo && !safeReturnTo) {\n\t\t\tthrow new ProtocolError(`Invalid returnTo URL: ${returnTo}. Expected a URL with the same origin as the request: ${requestUrl.origin}`);\n\t\t}\n\n\t\tif (['embedded', 'native'].includes(options.mode) && params.sdk) {\n\t\t\turl.searchParams.set('sdk', params.sdk);\n\t\t}\n\n\t\tconst startResponse = await options.httpClient.request<string>(url, {\n\t\t\tmethod: 'GET',\n\t\t\tcredentials: 'include',\n\t\t\tredirect: 'manual',\n\t\t});\n\n\t\toptions.logging?.debug('Attempting to redirect for login');\n\n\t\tif (safeReturnTo) {\n\t\t\tpushSetCookie(event, serializeCookie(RETURN_TO_COOKIE, safeReturnTo));\n\t\t}\n\n\t\treturn flushSetCookies(event, proxyResponse(startResponse));\n\t}\n\n\tasync function handleRegister(event: TEvent): Promise<Response> {\n\t\treturn handleLogin(event, { prompt: 'create' });\n\t}\n\n\tasync function handleCallback(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst params = Object.fromEntries(requestUrl.searchParams);\n\n\t\ttry {\n\t\t\tconst serializedState = await options.stateStorage.get(`sty.${params.state}`);\n\n\t\t\tif (!serializedState) {\n\t\t\t\tthrow new ProtocolError('State not found or expired. Please try logging in again.');\n\t\t\t}\n\n\t\t\tawait completeLogin(params, event);\n\n\t\t\tconst state = parseState(serializedState);\n\t\t\tconst returnTo = parseCookieHeader(request.headers.get('cookie'))[RETURN_TO_COOKIE] ?? options.postLoginRedirectUri;\n\n\t\t\tpushSetCookie(event, serializeCookie(RETURN_TO_COOKIE, '', { expires: new Date(0) }));\n\n\t\t\tif (state.metadata?.display === 'popup') {\n\t\t\t\t// NOTE: If the login was initiated from a popup, we return a HTML page that will close the popup and notify the opener window.\n\t\t\t\treturn flushSetCookies(\n\t\t\t\t\tevent,\n\t\t\t\t\tnew Response(`<!DOCTYPE html><html><body><script>window.opener?.postMessage({}, '*');window.close();</script></body></html>`, {\n\t\t\t\t\t\theaders: { 'content-type': 'text/html; charset=utf-8' },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn flushSetCookies(event, await redirect(new URL(returnTo, requestUrl.origin), 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(requestUrl.origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleRefresh(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\t\tconst origin = requestUrl.origin;\n\t\tconst returnTo = requestUrl.searchParams.get('returnTo');\n\t\tconst safeReturnTo = toSafeRedirect(returnTo, origin);\n\n\t\tif (returnTo && !safeReturnTo) {\n\t\t\tthrow new ProtocolError(`Invalid returnTo URL: ${returnTo}. Expected a URL with the same origin as the request: ${requestUrl.origin}`);\n\t\t}\n\n\t\ttry {\n\t\t\tawait refreshSession(event);\n\n\t\t\tif (safeReturnTo) {\n\t\t\t\treturn flushSetCookies(event, await redirect(new URL(safeReturnTo, origin), 302, event));\n\t\t\t}\n\n\t\t\treturn flushSetCookies(event, new Response(null, { status: 204 }));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleRevoke(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tawait revokeSession(event);\n\n\t\t\treturn flushSetCookies(event, await redirect(new URL(options.postLogoutRedirectUri, origin), 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleEntry(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tconst data = await getEntrySession(request.url);\n\t\t\tconst uri = new URL(options.loginUri, origin);\n\t\t\turi.searchParams.set('session_id', data.session_id);\n\t\t\turi.searchParams.set('short_app_id', data.short_app_id);\n\t\t\turi.searchParams.set('language', data.language);\n\n\t\t\treturn flushSetCookies(event, await redirect(uri, 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleLogout(event: TEvent): Promise<Response> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst origin = new URL(request.url).origin;\n\n\t\ttry {\n\t\t\tconst logoutUrl = await logout(new URL(options.postLogoutRedirectUri, origin), event);\n\t\t\treturn flushSetCookies(event, await redirect(logoutUrl, 302, event));\n\t\t} catch (error) {\n\t\t\treturn flushSetCookies(event, await errorRedirect(origin, error, event));\n\t\t}\n\t}\n\n\tasync function handleBackChannelLogout(event: TEvent): Promise<Response> {\n\t\tif (typeof options.storage.deleteByLogoutToken !== 'function') {\n\t\t\treturn new Response('Back-channel logout requires a storage with deleteByLogoutToken', { status: 501 });\n\t\t}\n\n\t\tconst request = await adapter.toRequest(event);\n\t\tlet logoutToken: string | null;\n\n\t\ttry {\n\t\t\tconst contentType = request.headers.get('content-type') ?? '';\n\n\t\t\tif (contentType.includes('application/x-www-form-urlencoded')) {\n\t\t\t\tconst body = await request.formData();\n\t\t\t\tlogoutToken = body.get('logout_token') as string | null;\n\t\t\t} else {\n\t\t\t\treturn new Response('Invalid content type: expected application/x-www-form-urlencoded', { status: 400 });\n\t\t\t}\n\t\t} catch {\n\t\t\treturn new Response('Failed to parse request body', { status: 400 });\n\t\t}\n\n\t\tif (!logoutToken) {\n\t\t\treturn new Response('Missing logout_token', { status: 400 });\n\t\t}\n\n\t\tconst now = timestamp();\n\n\t\tfor (const [token, expiresAt] of seenLogoutTokenIds) {\n\t\t\tif (expiresAt <= now) {\n\t\t\t\tseenLogoutTokenIds.delete(token);\n\t\t\t}\n\t\t}\n\n\t\tif (seenLogoutTokenIds.has(logoutToken)) {\n\t\t\treturn new Response('Invalid logout_token: token already used', { status: 400 });\n\t\t}\n\n\t\tseenLogoutTokenIds.set(logoutToken, now + BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS);\n\n\t\tlet claims;\n\t\tlet metadata;\n\n\t\ttry {\n\t\t\tmetadata = await getDiscoveryDocument(options);\n\t\t\tclaims = await verifyJwt<LogoutTokenClaims>({ token: logoutToken, jwksUri: metadata.jwks_uri, options });\n\t\t} catch (error) {\n\t\t\treturn new Response(`Invalid logout_token: ${error.message}`, { status: 400 });\n\t\t}\n\n\t\tif (claims.iss !== metadata.issuer) {\n\t\t\treturn new Response('Invalid logout_token: invalid iss claim', { status: 400 });\n\t\t}\n\n\t\tif (Array.isArray(claims.aud) ? !claims.aud.includes(options.clientId) : claims.aud !== options.clientId) {\n\t\t\treturn new Response('Invalid logout_token: invalid aud claim', { status: 400 });\n\t\t}\n\n\t\tif (typeof claims.iat !== 'number' || Math.abs(now - claims.iat) > BACKCHANNEL_LOGOUT_TOKEN_MAX_AGE_SECONDS) {\n\t\t\treturn new Response('Invalid logout_token: invalid or stale iat claim', { status: 400 });\n\t\t}\n\n\t\tif (!claims.jti) {\n\t\t\treturn new Response('Invalid logout_token: missing jti claim', { status: 400 });\n\t\t}\n\n\t\tif (claims.nonce !== undefined) {\n\t\t\treturn new Response('Invalid logout_token: nonce claim must not be present', { status: 400 });\n\t\t}\n\n\t\tif (!claims.events || !(BACKCHANNEL_LOGOUT_EVENT in claims.events)) {\n\t\t\treturn new Response(`Invalid logout_token: missing ${BACKCHANNEL_LOGOUT_EVENT} in events`, { status: 400 });\n\t\t}\n\n\t\tif (!claims.sid && !claims.sub) {\n\t\t\treturn new Response('Invalid logout_token: must contain sid or sub claim', { status: 400 });\n\t\t}\n\n\t\tconst token: LogoutTokenClaims = {} as never;\n\n\t\tif (claims.sid) {\n\t\t\ttoken.sid = claims.sid;\n\t\t}\n\t\tif (claims.sub) {\n\t\t\ttoken.sub = claims.sub;\n\t\t}\n\n\t\ttry {\n\t\t\tawait options.storage.deleteByLogoutToken(token);\n\t\t} catch (error) {\n\t\t\treturn new Response(`Failed to delete session: ${error.message}`, { status: 500 });\n\t\t}\n\n\t\treturn new Response(null, { status: 200 });\n\t}\n\n\tasync function handler(event: TEvent): Promise<Response | null> {\n\t\tconst request = await adapter.toRequest(event);\n\t\tconst requestUrl = new URL(request.url);\n\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/login`) {\n\t\t\treturn handleLogin(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/register`) {\n\t\t\treturn handleRegister(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/callback`) {\n\t\t\treturn handleCallback(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/refresh`) {\n\t\t\treturn handleRefresh(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/revoke`) {\n\t\t\treturn handleRevoke(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/entry`) {\n\t\t\treturn handleEntry(event);\n\t\t}\n\t\tif (request.method === 'GET' && requestUrl.pathname === `${options.authUrlPrefix}/logout`) {\n\t\t\treturn handleLogout(event);\n\t\t}\n\t\tif (request.method === 'POST' && requestUrl.pathname === `${options.authUrlPrefix}/backchannel-logout`) {\n\t\t\treturn handleBackChannelLogout(event);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// endregion\n\n\tinit();\n\n\treturn {\n\t\tget options() {\n\t\t\treturn options;\n\t\t},\n\t\tgetSession,\n\t\tupdateSession,\n\t\trefreshSession,\n\t\trevokeSession,\n\t\tgetEntrySession,\n\t\tcompleteLogin,\n\t\tlogout,\n\t\thandleLogin,\n\t\thandleRegister,\n\t\thandleCallback,\n\t\thandleRefresh,\n\t\thandleRevoke,\n\t\thandleEntry,\n\t\thandleLogout,\n\t\thandleBackChannelLogout,\n\t\thandler,\n\t};\n}\n"],"mappings":"6YA4BA,IAAa,EAAiB,wBACjB,EAAoB,KACpB,EAA2B,IAAI,IAAI,CAAC,oBAAqB,aAAc,aAAc,kBAAkB,CAAC,EACxG,EAAmB,eACnB,EAA2C,IASxD,SAAgB,EAId,EAAgC,EAAuF,CACxH,IAAM,EAAU,EAAoB,EAAS,CAAU,EACjD,EAAqB,IAAI,IAE/B,SAAS,GAAO,CACf,GAAI,CAAC,EAAQ,OAAQ,CACpB,IAAM,EAAQ,IAAI,EAAmB,wBAAwB,EAE7D,MADA,EAAQ,SAAS,MAAM,0BAA2B,CAAK,EACjD,CACP,CACA,GAAI,CAAC,EAAQ,SAAU,CACtB,IAAM,EAAQ,IAAI,EAAmB,0BAA0B,EAE/D,MADA,EAAQ,SAAS,MAAM,0BAA2B,CAAK,EACjD,CACP,CACA,GAAI,CAAC,EAAQ,YAAa,CACzB,IAAM,EAAQ,IAAI,EAAmB,6BAA6B,EAElE,MADA,EAAQ,SAAS,MAAM,0BAA2B,CAAK,EACjD,CACP,CACA,GAAI,EAAQ,QAAU,CAAC,MAAM,QAAQ,EAAQ,MAAM,EAAG,CACrD,IAAM,EAAQ,IAAI,EAAmB,wBAAwB,EAE7D,MADA,EAAQ,SAAS,MAAM,0BAA2B,CAAK,EACjD,CACP,CACD,CAEA,eAAe,EAAS,EAAmB,EAAS,IAAK,EAAmC,CAK3F,OAJI,EAAQ,SACJ,MAAM,EAAQ,SAAS,EAAK,EAAQ,CAAK,EAG1C,IAAI,SAAS,KAAM,CAAE,SAAQ,QAAS,CAAE,SAAU,EAAI,SAAS,CAAE,CAAE,CAAC,CAC5E,CAEA,eAAe,EAAc,EAAgB,EAAgB,EAAmC,CAC/F,IAAM,EAAM,IAAI,IAAI,SAAU,CAAM,EAkBpC,OAhBI,aAAiB,GACpB,EAAI,aAAa,IAAI,OAAQ,EAAM,SAAS,YAAY,CAAC,EACzD,EAAI,aAAa,IAAI,QAAS,EAAM,KAAK,EACrC,EAAM,kBACT,EAAI,aAAa,IAAI,oBAAqB,EAAM,gBAAgB,GAEvD,aAAiB,OAAS,aAAc,GAClD,EAAI,aAAa,IAAI,OAAS,EAAwC,SAAS,YAAY,CAAC,EAC5F,EAAI,aAAa,IAAI,QAAS,EAAM,IAAI,EACxC,EAAI,aAAa,IAAI,oBAAqB,EAAM,OAAO,IAEvD,EAAI,aAAa,IAAI,OAAQ,SAAS,EACtC,EAAI,aAAa,IAAI,QAAS,eAAe,EAC7C,EAAI,aAAa,IAAI,oBAAqB,aAAiB,MAAQ,EAAM,QAAU,eAAe,GAG5F,EAAS,EAAK,IAAK,CAAK,CAChC,CAEA,eAAe,EAAW,EAA6C,CACtE,OAAO,EAAY,MAAM,EAAQ,QAAQ,IAAI,EAAQ,iBAAkB,CAAK,CAAC,CAC9E,CAEA,eAAe,EAAc,EAAsB,EAA+B,CACjF,MAAM,EAAQ,QAAQ,IAAI,EAAQ,iBAAkB,EAAiB,CAAO,EAAG,CAAK,CACrF,CAEA,eAAe,EAAe,EAA+B,CAC5D,MAAM,EAAQ,QAAQ,OAAO,EAAQ,iBAAkB,CAAK,CAC7D,CAEA,eAAe,EAAe,EAAsC,CACnE,EAAQ,SAAS,MAAM,+BAA+B,EAEtD,IAAM,EAAiB,MAAM,EAAW,CAAK,EAE7C,GAAI,CAAC,EACJ,MAAM,IAAI,EAAc,iCAAiC,EAG1D,GAAI,OAAO,EAAe,eAAkB,SAC3C,MAAM,IAAI,EAAmB,4BAA4B,EAG1D,GAAI,CACH,IAAM,EAAa,MAAM,EAAa,CAAE,aAAc,EAAe,cAAe,UAAS,YAAa,EAAe,QAAQ,GAAI,CAAC,EAKtI,OAJA,MAAM,EAAc,EAAY,CAAK,EAErC,EAAQ,SAAS,MAAM,4BAA4B,EAE5C,CACR,OAAS,EAAO,CAIf,MAHA,MAAM,EAAe,CAAK,EAC1B,EAAQ,SAAS,MAAM,yBAA0B,CAAc,EAEzD,CACP,CACD,CAEA,eAAe,EAAc,EAA+B,CAC3D,IAAM,EAAiB,MAAM,EAAW,CAAK,EAW7C,GATI,GAAgB,cACnB,EAAQ,SAAS,MAAM,oCAAoC,EAE3D,EAAQ,SAAS,MAAM,mCAAmC,EAI3D,MAAM,EAAe,CAAK,EAEtB,CAAC,GAAgB,cAAgB,CAAC,GAAgB,cAAe,CACpE,EAAQ,SAAS,MAAM,+BAA+B,EACtD,MACD,CAEA,IAAM,EAAgB,EAAe,cAAgB,gBAAkB,eACjE,EAAS,IAAkB,gBAAkB,EAAe,cAAgB,EAAe,aAEjG,GAAI,CACH,MAAM,EAAY,CAAE,gBAAe,QAAO,SAAQ,CAAC,EAE/C,IAAkB,gBACrB,EAAQ,SAAS,KAAK,oCAAoC,EAE1D,EAAQ,SAAS,KAAK,mCAAmC,CAE3D,OAAS,EAAO,CAEf,MADA,EAAQ,SAAS,MAAM,0BAA2B,CAAc,EAC1D,CACP,CACD,CAEA,eAAe,EAAgB,EAAyD,CACvF,EAAQ,SAAS,MAAM,0BAA0B,EAEjD,GAAM,CAAE,aAAc,GAAW,IAAI,IAAI,CAAQ,EAEjD,GAAI,CACH,IAAM,EAAM,IAAI,IAAI,uBAAwB,EAAQ,MAAM,EACpD,EAAO,MAAM,EAAe,CACjC,MACA,SACA,QAAS,EAAQ,OAAS,WAAa,eAAiB,MACxD,SACD,CAAC,EAID,OAFA,EAAQ,SAAS,MAAM,8BAA8B,KAAK,UAAU,CAAI,GAAG,EAEpE,CACR,OAAS,EAAO,CAEf,MADA,EAAQ,SAAS,MAAM,uBAAwB,CAAc,EACvD,CACP,CACD,CAEA,eAAe,EAAc,EAAgC,EAAsC,CAClG,EAAQ,SAAS,MAAM,0CAA0C,EAEjE,GAAI,CACH,IAAM,EAAU,MAAM,EAAa,CAAE,SAAQ,SAAQ,CAAC,EAEtD,GAAI,CAAC,EAAQ,aACZ,MAAM,IAAI,EAAc,sBAAsB,EAY/C,OATA,MAAM,EAAc,EAAS,CAAK,EAElC,EAAQ,SAAS,MAAM,2BAA2B,EAE9C,EAAQ,UACX,EAAQ,QAAQ,SAAW,IAAA,GAC3B,EAAQ,QAAQ,KAAK,kBAAkB,GAGjC,CACR,OAAS,EAAO,CAEf,MADA,EAAQ,SAAS,MAAM,wBAAyB,CAAc,EACxD,CACP,CACD,CAEA,eAAe,EAAO,EAAqC,EAA8B,CACxF,EAAQ,SAAS,MAAM,sBAAsB,EAG7C,IAAM,EAAiB,MAAM,EAAW,CAAK,EAK7C,GAJA,MAAM,EAAe,CAAK,EAE1B,EAAQ,SAAS,MAAM,kBAAkB,EAErC,CAAC,GAAgB,SAEpB,OADA,EAAQ,SAAS,MAAM,gCAAgC,EAChD,IAAI,IAAI,CAAqB,EAGrC,IAAM,EAAW,MAAM,EAAqB,CAAO,EAEnD,OAAO,EAAmB,CACzB,IAAK,EAAS,qBACd,QAAS,EAAe,SACxB,sBAAuB,IAAI,IAAI,CAAqB,CAAC,CAAC,SAAS,CAChE,CAAC,CACF,CAEA,eAAe,EAAY,EAAe,EAAuC,CAAC,EAAsB,CACvG,IAAM,EAAU,MAAM,EAAQ,UAAU,CAAK,EACvC,EAAa,IAAI,IAAI,EAAQ,GAAG,EAChC,CAAE,WAAU,SAAQ,UAAS,aAAY,aAAY,aAAY,WAAU,GAAG,GAAW,OAAO,YAAY,EAAW,YAAY,EACnI,EAAe,EAAe,EAAU,EAAW,MAAM,EACzD,EAAM,MAAM,EAAsB,CACvC,OAAQ,CACP,OAAQ,GAAU,EAAO,OACzB,QAAS,GAAW,EAAO,QAC3B,UAAW,GAAc,EAAO,UAChC,WAAY,GAAc,EAAO,UAAA,EAAY,MAAM,GAAG,EACtD,WAAY,GAAc,EAAO,UAAA,EAAY,MAAM,GAAG,EACtD,WAAY,GAAY,EAAO,UAAA,EAAY,MAAM,GAAG,EACpD,GAAG,CACJ,EACA,SACD,CAAC,EAED,GAAI,GAAY,CAAC,EAChB,MAAM,IAAI,EAAc,yBAAyB,EAAS,wDAAwD,EAAW,QAAQ,EAGlI,CAAC,WAAY,QAAQ,CAAC,CAAC,SAAS,EAAQ,IAAI,GAAK,EAAO,KAC3D,EAAI,aAAa,IAAI,MAAO,EAAO,GAAG,EAGvC,IAAM,EAAgB,MAAM,EAAQ,WAAW,QAAgB,EAAK,CACnE,OAAQ,MACR,YAAa,UACb,SAAU,QACX,CAAC,EAQD,OANA,EAAQ,SAAS,MAAM,kCAAkC,EAErD,GACH,EAAc,EAAO,EAAgB,EAAkB,CAAY,CAAC,EAG9D,EAAgB,EAAO,EAAc,CAAa,CAAC,CAC3D,CAEA,eAAe,EAAe,EAAkC,CAC/D,OAAO,EAAY,EAAO,CAAE,OAAQ,QAAS,CAAC,CAC/C,CAEA,eAAe,EAAe,EAAkC,CAC/D,IAAM,EAAU,MAAM,EAAQ,UAAU,CAAK,EACvC,EAAa,IAAI,IAAI,EAAQ,GAAG,EAChC,EAAS,OAAO,YAAY,EAAW,YAAY,EAEzD,GAAI,CACH,IAAM,EAAkB,MAAM,EAAQ,aAAa,IAAI,OAAO,EAAO,OAAO,EAE5E,GAAI,CAAC,EACJ,MAAM,IAAI,EAAc,0DAA0D,EAGnF,MAAM,EAAc,EAAQ,CAAK,EAEjC,IAAM,EAAQ,EAAW,CAAe,EAClC,EAAW,EAAkB,EAAQ,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAA,iBAAsB,EAAQ,qBAc/F,OAZA,EAAc,EAAO,EAAgB,EAAkB,GAAI,CAAE,QAAS,IAAI,KAAK,CAAC,CAAE,CAAC,CAAC,EAEhF,EAAM,UAAU,UAAY,QAExB,EACN,EACA,IAAI,SAAS,iHAAiH,CAC7H,QAAS,CAAE,eAAgB,0BAA2B,CACvD,CAAC,CACF,EAGM,EAAgB,EAAO,MAAM,EAAS,IAAI,IAAI,EAAU,EAAW,MAAM,EAAG,IAAK,CAAK,CAAC,CAC/F,OAAS,EAAO,CACf,OAAO,EAAgB,EAAO,MAAM,EAAc,EAAW,OAAQ,EAAO,CAAK,CAAC,CACnF,CACD,CAEA,eAAe,EAAc,EAAkC,CAC9D,IAAM,EAAU,MAAM,EAAQ,UAAU,CAAK,EACvC,EAAa,IAAI,IAAI,EAAQ,GAAG,EAChC,EAAS,EAAW,OACpB,EAAW,EAAW,aAAa,IAAI,UAAU,EACjD,EAAe,EAAe,EAAU,CAAM,EAEpD,GAAI,GAAY,CAAC,EAChB,MAAM,IAAI,EAAc,yBAAyB,EAAS,wDAAwD,EAAW,QAAQ,EAGtI,GAAI,CAOH,OANA,MAAM,EAAe,CAAK,EAEtB,EACI,EAAgB,EAAO,MAAM,EAAS,IAAI,IAAI,EAAc,CAAM,EAAG,IAAK,CAAK,CAAC,EAGjF,EAAgB,EAAO,IAAI,SAAS,KAAM,CAAE,OAAQ,GAAI,CAAC,CAAC,CAClE,OAAS,EAAO,CACf,OAAO,EAAgB,EAAO,MAAM,EAAc,EAAQ,EAAO,CAAK,CAAC,CACxE,CACD,CAEA,eAAe,EAAa,EAAkC,CAC7D,IAAM,EAAU,MAAM,EAAQ,UAAU,CAAK,EACvC,EAAS,IAAI,IAAI,EAAQ,GAAG,CAAC,CAAC,OAEpC,GAAI,CAGH,OAFA,MAAM,EAAc,CAAK,EAElB,EAAgB,EAAO,MAAM,EAAS,IAAI,IAAI,EAAQ,sBAAuB,CAAM,EAAG,IAAK,CAAK,CAAC,CACzG,OAAS,EAAO,CACf,OAAO,EAAgB,EAAO,MAAM,EAAc,EAAQ,EAAO,CAAK,CAAC,CACxE,CACD,CAEA,eAAe,EAAY,EAAkC,CAC5D,IAAM,EAAU,MAAM,EAAQ,UAAU,CAAK,EACvC,EAAS,IAAI,IAAI,EAAQ,GAAG,CAAC,CAAC,OAEpC,GAAI,CACH,IAAM,EAAO,MAAM,EAAgB,EAAQ,GAAG,EACxC,EAAM,IAAI,IAAI,EAAQ,SAAU,CAAM,EAK5C,OAJA,EAAI,aAAa,IAAI,aAAc,EAAK,UAAU,EAClD,EAAI,aAAa,IAAI,eAAgB,EAAK,YAAY,EACtD,EAAI,aAAa,IAAI,WAAY,EAAK,QAAQ,EAEvC,EAAgB,EAAO,MAAM,EAAS,EAAK,IAAK,CAAK,CAAC,CAC9D,OAAS,EAAO,CACf,OAAO,EAAgB,EAAO,MAAM,EAAc,EAAQ,EAAO,CAAK,CAAC,CACxE,CACD,CAEA,eAAe,EAAa,EAAkC,CAC7D,IAAM,EAAU,MAAM,EAAQ,UAAU,CAAK,EACvC,EAAS,IAAI,IAAI,EAAQ,GAAG,CAAC,CAAC,OAEpC,GAAI,CACH,IAAM,EAAY,MAAM,EAAO,IAAI,IAAI,EAAQ,sBAAuB,CAAM,EAAG,CAAK,EACpF,OAAO,EAAgB,EAAO,MAAM,EAAS,EAAW,IAAK,CAAK,CAAC,CACpE,OAAS,EAAO,CACf,OAAO,EAAgB,EAAO,MAAM,EAAc,EAAQ,EAAO,CAAK,CAAC,CACxE,CACD,CAEA,eAAe,EAAwB,EAAkC,CACxE,GAAI,OAAO,EAAQ,QAAQ,qBAAwB,WAClD,OAAO,IAAI,SAAS,kEAAmE,CAAE,OAAQ,GAAI,CAAC,EAGvG,IAAM,EAAU,MAAM,EAAQ,UAAU,CAAK,EACzC,EAEJ,GAAI,CAGH,IAFoB,EAAQ,QAAQ,IAAI,cAAc,GAAK,GAAA,CAE3C,SAAS,mCAAmC,EAE3D,GAAc,MADK,EAAQ,SAAS,EAAA,CACjB,IAAI,cAAc,OAErC,OAAO,IAAI,SAAS,mEAAoE,CAAE,OAAQ,GAAI,CAAC,CAEzG,MAAQ,CACP,OAAO,IAAI,SAAS,+BAAgC,CAAE,OAAQ,GAAI,CAAC,CACpE,CAEA,GAAI,CAAC,EACJ,OAAO,IAAI,SAAS,uBAAwB,CAAE,OAAQ,GAAI,CAAC,EAG5D,IAAM,EAAM,EAAU,EAEtB,IAAK,GAAM,CAAC,EAAO,KAAc,EAC5B,GAAa,GAChB,EAAmB,OAAO,CAAK,EAIjC,GAAI,EAAmB,IAAI,CAAW,EACrC,OAAO,IAAI,SAAS,2CAA4C,CAAE,OAAQ,GAAI,CAAC,EAGhF,EAAmB,IAAI,EAAa,EAAA,GAA8C,EAElF,IAAI,EACA,EAEJ,GAAI,CACH,EAAW,MAAM,EAAqB,CAAO,EAC7C,EAAS,MAAM,EAA6B,CAAE,MAAO,EAAa,QAAS,EAAS,SAAU,SAAQ,CAAC,CACxG,OAAS,EAAO,CACf,OAAO,IAAI,SAAS,yBAAyB,EAAM,UAAW,CAAE,OAAQ,GAAI,CAAC,CAC9E,CAEA,GAAI,EAAO,MAAQ,EAAS,OAC3B,OAAO,IAAI,SAAS,0CAA2C,CAAE,OAAQ,GAAI,CAAC,EAG/E,GAAI,MAAM,QAAQ,EAAO,GAAG,EAAI,CAAC,EAAO,IAAI,SAAS,EAAQ,QAAQ,EAAI,EAAO,MAAQ,EAAQ,SAC/F,OAAO,IAAI,SAAS,0CAA2C,CAAE,OAAQ,GAAI,CAAC,EAG/E,GAAI,OAAO,EAAO,KAAQ,UAAY,KAAK,IAAI,EAAM,EAAO,GAAG,EAAA,IAC9D,OAAO,IAAI,SAAS,mDAAoD,CAAE,OAAQ,GAAI,CAAC,EAGxF,GAAI,CAAC,EAAO,IACX,OAAO,IAAI,SAAS,0CAA2C,CAAE,OAAQ,GAAI,CAAC,EAG/E,GAAI,EAAO,QAAU,IAAA,GACpB,OAAO,IAAI,SAAS,wDAAyD,CAAE,OAAQ,GAAI,CAAC,EAG7F,GAAI,CAAC,EAAO,QAAU,EAAA,uDAA8B,EAAO,QAC1D,OAAO,IAAI,SAAS,iCAAiC,EAAyB,YAAa,CAAE,OAAQ,GAAI,CAAC,EAG3G,GAAI,CAAC,EAAO,KAAO,CAAC,EAAO,IAC1B,OAAO,IAAI,SAAS,sDAAuD,CAAE,OAAQ,GAAI,CAAC,EAG3F,IAAM,EAA2B,CAAC,EAE9B,EAAO,MACV,EAAM,IAAM,EAAO,KAEhB,EAAO,MACV,EAAM,IAAM,EAAO,KAGpB,GAAI,CACH,MAAM,EAAQ,QAAQ,oBAAoB,CAAK,CAChD,OAAS,EAAO,CACf,OAAO,IAAI,SAAS,6BAA6B,EAAM,UAAW,CAAE,OAAQ,GAAI,CAAC,CAClF,CAEA,OAAO,IAAI,SAAS,KAAM,CAAE,OAAQ,GAAI,CAAC,CAC1C,CAEA,eAAe,EAAQ,EAAyC,CAC/D,IAAM,EAAU,MAAM,EAAQ,UAAU,CAAK,EACvC,EAAa,IAAI,IAAI,EAAQ,GAAG,EA2BtC,OAzBI,EAAQ,SAAW,OAAS,EAAW,WAAa,GAAG,EAAQ,cAAc,QACzE,EAAY,CAAK,EAErB,EAAQ,SAAW,OAAS,EAAW,WAAa,GAAG,EAAQ,cAAc,WACzE,EAAe,CAAK,EAExB,EAAQ,SAAW,OAAS,EAAW,WAAa,GAAG,EAAQ,cAAc,WACzE,EAAe,CAAK,EAExB,EAAQ,SAAW,OAAS,EAAW,WAAa,GAAG,EAAQ,cAAc,UACzE,EAAc,CAAK,EAEvB,EAAQ,SAAW,OAAS,EAAW,WAAa,GAAG,EAAQ,cAAc,SACzE,EAAa,CAAK,EAEtB,EAAQ,SAAW,OAAS,EAAW,WAAa,GAAG,EAAQ,cAAc,QACzE,EAAY,CAAK,EAErB,EAAQ,SAAW,OAAS,EAAW,WAAa,GAAG,EAAQ,cAAc,SACzE,EAAa,CAAK,EAEtB,EAAQ,SAAW,QAAU,EAAW,WAAa,GAAG,EAAQ,cAAc,qBAC1E,EAAwB,CAAK,EAG9B,IACR,CAMA,OAFA,EAAK,EAEE,CACN,IAAI,SAAU,CACb,OAAO,CACR,EACA,aACA,gBACA,iBACA,gBACA,kBACA,gBACA,SACA,cACA,iBACA,iBACA,gBACA,eACA,cACA,eACA,0BACA,SACD,CACD"}
|
package/dist/types/oidc.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oidc.cjs","names":[],"sources":["../../src/types/oidc.ts"],"sourcesContent":["import type { SDKHttpClient, SDKLogging, SDKStorage } from './common';\nimport type { RedirectOptions } from './redirect';\nimport type { BACKCHANNEL_LOGOUT_EVENT } from '../utils/server';\n\nexport const ResponseTypeList = ['code'] as const;\nexport type ResponseType = (typeof ResponseTypeList)[number];\n\nexport const ResponseModeList = ['query', 'fragment'] as const;\nexport type ResponseMode = (typeof ResponseModeList)[number];\n\nexport const TokenEndpointAuthMethodList = ['none'] as const;\nexport type TokenEndpointAuthMethod = (typeof TokenEndpointAuthMethodList)[number];\n\nexport const GrantTypeList = ['authorization_code', 'refresh_token'] as const;\nexport type GrantType = (typeof GrantTypeList)[number];\n\nexport const AlgorithmTypeList = ['RS256'] as const;\nexport type AlgorithmType = (typeof AlgorithmTypeList)[number];\n\nexport const SubjectTypeList = ['public'] as const;\nexport type SubjectType = (typeof SubjectTypeList)[number];\n\nexport type SigningKey = {\n\t/**\n\t * The intended use of the key. Common values include \"sig\" for signature and \"enc\" for encryption.\n\t */\n\tuse: string;\n\n\t/**\n\t * The key type. For example, \"RSA\" for RSA keys or \"EC\" for Elliptic Curve keys.\n\t */\n\tkty: string;\n\n\t/**\n\t * A unique identifier for the key. This is used to distinguish the key from others.\n\t */\n\tkid: string;\n\n\t/**\n\t * The algorithm used with the key. For example, \"RS256\" for RSA SHA-256.\n\t */\n\talg: AlgorithmType;\n\n\t/**\n\t * The modulus of the RSA key, encoded in base64url format. For RSA keys, this is a required property.\n\t */\n\tn: string;\n\n\t/**\n\t * The exponent of the RSA key, encoded in base64url format. For RSA keys, this is a required property.\n\t */\n\te: string;\n};\n\nexport type DiscoveryDocument = {\n\t/**\n\t * The issuer of the tokens. This is the authorization server or entity that issues the tokens.\n\t */\n\tissuer: string;\n\n\t/**\n\t * The URL of the authorization endpoint where authentication requests are sent.\n\t */\n\tauthorization_endpoint: string;\n\n\t/**\n\t * The URL of the token endpoint where tokens are exchanged.\n\t */\n\ttoken_endpoint: string;\n\n\t/**\n\t * The URL of the JSON Web Key Set (JWKS) endpoint where public keys are available.\n\t */\n\tjwks_uri: string;\n\n\t/**\n\t * The types of subjects that are supported by the authorization server.\n\t */\n\tsubject_types_supported: Array<SubjectType>;\n\n\t/**\n\t * The types of responses supported by the authorization server.\n\t */\n\tresponse_types_supported: Array<string>;\n\n\t/**\n\t * The claims supported by the authorization server.\n\t */\n\tclaims_supported: Array<string>;\n\n\t/**\n\t * The grant types supported by the authorization server.\n\t */\n\tgrant_types_supported: Array<GrantType>;\n\n\t/**\n\t * The response modes supported by the authorization server.\n\t */\n\tresponse_modes_supported: Array<ResponseMode>;\n\n\t/**\n\t * The URL of the user info endpoint where user information can be retrieved.\n\t */\n\tuserinfo_endpoint: string;\n\n\t/**\n\t * The scopes supported by the authorization server.\n\t */\n\tscopes_supported: Array<string>;\n\n\t/**\n\t * The authentication methods supported for token endpoint authentication.\n\t */\n\ttoken_endpoint_auth_methods_supported: Array<TokenEndpointAuthMethod>;\n\n\t/**\n\t * The algorithms supported for signing tokens used in the user info endpoint.\n\t */\n\tuserinfo_signing_alg_values_supported: Array<AlgorithmType>;\n\n\t/**\n\t * The algorithms supported for signing ID tokens.\n\t */\n\tid_token_signing_alg_values_supported: Array<AlgorithmType>;\n\n\t/**\n\t * The algorithms used to sign ID tokens in response.\n\t */\n\tid_token_signed_response_alg: Array<AlgorithmType>;\n\n\t/**\n\t * The algorithms used to sign responses from the user info endpoint.\n\t */\n\tuserinfo_signed_response_alg: Array<AlgorithmType>;\n\n\t/**\n\t * Indicates whether the request parameter is supported in requests.\n\t */\n\trequest_parameter_supported: boolean;\n\n\t/**\n\t * Indicates whether the request URI parameter is supported in requests.\n\t */\n\trequest_uri_parameter_supported: boolean;\n\n\t/**\n\t * Indicates whether request URI registration is required.\n\t */\n\trequire_request_uri_registration: boolean;\n\n\t/**\n\t * Indicates whether the claims parameter is supported.\n\t */\n\tclaims_parameter_supported: boolean;\n\n\t/**\n\t * The URL of the revocation endpoint for revoking tokens.\n\t */\n\trevocation_endpoint: string;\n\n\t/**\n\t * Indicates whether backchannel logout is supported.\n\t */\n\tbackchannel_logout_supported: boolean;\n\n\t/**\n\t * Indicates whether backchannel logout session support is provided.\n\t */\n\tbackchannel_logout_session_supported: boolean;\n\n\t/**\n\t * Indicates whether frontchannel logout is supported.\n\t */\n\tfrontchannel_logout_supported: boolean;\n\n\t/**\n\t * Indicates whether frontchannel logout session support is provided.\n\t */\n\tfrontchannel_logout_session_supported: boolean;\n\n\t/**\n\t * The URL of the endpoint where end-session requests can be sent.\n\t */\n\tend_session_endpoint: string;\n\n\t/**\n\t * The algorithms supported for signing request objects.\n\t */\n\trequest_object_signing_alg_values_supported: Array<AlgorithmType>;\n\n\t/**\n\t * The code challenge methods supported by the authorization server.\n\t */\n\tcode_challenge_methods_supported: Array<'S256'>;\n};\n\nexport type JwtClaims = {\n\t/**\n\t * The issuer of the token. This typically represents the authorization server or entity that issued the JWT.\n\t */\n\tiss?: string;\n\n\t/**\n\t * The subject of the token. This is the identifier for the entity the token represents, such as a user ID.\n\t */\n\tsub?: string;\n\n\t/**\n\t * The audience for which the token is intended. This can be a single identifier or an array of identifiers.\n\t */\n\taud?: string | Array<string>;\n\n\t/**\n\t * The expiration time of the token, expressed as a Unix timestamp (number of seconds since January 1, 1970).\n\t */\n\texp?: number;\n\n\t/**\n\t * The not-before time of the token, expressed as a Unix timestamp. The token must not be accepted before this time.\n\t */\n\tnbf?: number;\n\n\t/**\n\t * The issued-at time of the token, expressed as a Unix timestamp (number of seconds since January 1, 1970).\n\t */\n\tiat?: number;\n\n\t/**\n\t * A unique identifier for the token. This can be used to prevent token replay attacks.\n\t */\n\tjti?: string;\n};\n\nexport type IdTokenClaims = Required<Pick<JwtClaims, 'iss' | 'sub' | 'aud' | 'exp' | 'iat' | 'jti'>> & {\n\t/**\n\t * The authentication time, indicating when the user was authenticated.\n\t */\n\tauth_time?: number;\n\n\t/**\n\t * A nonce value used to associate a client session with an ID token, preventing replay attacks.\n\t */\n\tnonce?: string;\n\n\t/**\n\t * The Authentication Context Class Reference, indicating the authentication methods used.\n\t */\n\tacr?: string;\n\n\t/**\n\t * The Authentication Methods References, providing information about the authentication methods used.\n\t */\n\tamr?: unknown;\n\n\t/**\n\t * Authorized party, the client that the ID token is intended for.\n\t */\n\tazp?: string;\n\n\t/**\n\t * Session ID for the user, which can be used to manage user sessions.\n\t */\n\tsid?: string;\n\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t[key: string]: any;\n};\n\nexport type LogoutTokenClaims = Pick<JwtClaims, 'iss' | 'sub' | 'aud' | 'iat' | 'jti'> & {\n\t/**\n\t * Session ID for the user, which can be used to clear a specific session.\n\t */\n\tsid?: string;\n\n\t/**\n\t * Spec-compliant event signal for OpenID Connect Back-Channel Logout.\n\t */\n\tevents: Record<typeof BACKCHANNEL_LOGOUT_EVENT, Record<string, never>>;\n\n\t/**\n\t * MUST NOT contain a nonce claim according to the OIDC Back-Channel Logout spec.\n\t */\n\tnonce?: never;\n\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t[key: string]: any;\n};\n\nexport type SessionData = {\n\t/**\n\t * The state parameter used in the authentication request.\n\t */\n\tstate?: string | null;\n\n\t/**\n\t * The authorization code returned by the authorization server.\n\t */\n\tcode?: string | null;\n\n\t/**\n\t * The error returned during the authentication process, if any.\n\t */\n\terror?: string | null;\n\n\t/**\n\t * A description of the error returned during authentication.\n\t */\n\terror_description?: string | null;\n\n\t/**\n\t * A URI identifying a human-readable web page with information about the error (RFC 6749).\n\t */\n\terror_uri?: string | null;\n\n\t/**\n\t * Opaque value representing the session state at the authorization server (OIDC Session Management).\n\t */\n\tsession_state?: string | null;\n\n\t/**\n\t * The ID token issued by the authorization server.\n\t */\n\tid_token?: string | null;\n\n\t/**\n\t * The access token issued by the authorization server.\n\t */\n\taccess_token?: string | null;\n\n\t/**\n\t * The refresh token issued by the authorization server.\n\t */\n\trefresh_token?: string | null;\n\n\t/**\n\t * The type of token issued, defaulting to 'bearer'.\n\t */\n\ttoken_type?: string;\n\n\t/**\n\t * The scope of the issued token.\n\t */\n\tscope?: string | null;\n\n\t/**\n\t * The lifetime of the access token in seconds, as returned by the token endpoint.\n\t */\n\texpires_in?: number | null;\n\n\t/**\n\t * The absolute expiration time of the access token, represented as a Unix timestamp (seconds since epoch).\n\t */\n\texpires_at?: number | null;\n\n\t/**\n\t * The claims associated with the ID token.\n\t */\n\tclaims?: IdTokenClaims | null;\n};\n\nexport type LoginSessionParams = {\n\t/**\n\t * The unique identifier of the login session.\n\t */\n\tsession_id?: string;\n\n\t/**\n\t * The short application identifier associated with the login session.\n\t */\n\tshort_app_id?: string;\n\n\t/**\n\t * BCP 47 language tag representing the language preference for the login session.\n\t */\n\tlanguage?: string;\n};\n\nexport type StateData = {\n\t/**\n\t * A unique identifier for the state.\n\t */\n\tid: string;\n\n\t/**\n\t * The timestamp when the state was created, represented as a Unix timestamp (seconds since epoch).\n\t */\n\tcreatedAt: number;\n\n\t/**\n\t * The code verifier used in the PKCE flow.\n\t */\n\tcodeVerifier: string;\n\n\t/**\n\t * The code challenge derived from the code verifier, used in the PKCE flow.\n\t */\n\tcodeChallenge: string;\n\n\t/**\n\t * A unique nonce value used to associate a client session with an ID token, preventing replay attacks.\n\t */\n\tnonce: string;\n\n\t/**\n\t * Optional metadata associated with the state, which can be used to store additional information relevant to the authentication flow.\n\t */\n\tmetadata?: Record<string, unknown>;\n};\n\nexport type LogoutParams = {\n\t/**\n\t * The URL to which the user should be redirected after logging out.\n\t */\n\tpostLogoutRedirectUri?: string;\n};\n\nexport type ExtraRequestArgs = {\n\t/**\n\t * Specifies the type of prompt to display to the user during authentication or authorization.\n\t *\n\t * @example 'none' | 'login' | 'create'\n\t */\n\tprompt?: string | null;\n\n\t/**\n\t * Specifies the display mode for the authentication or authorization request.\n\t *\n\t * @example 'page' | 'popup'\n\t */\n\tdisplay?: string | null;\n\n\t/**\n\t * Provides a hint to the authorization server about the user's email or username.\n\t *\n\t * @example 'user@example.com'\n\t */\n\tloginHint?: string | null;\n\n\t/**\n\t * A list of values used to request specific authentication contexts or levels of assurance.\n\t * This parameter allows requesting specific authentication contexts (e.g., multi-factor authentication)\n\t * or other criteria that the authorization server should consider when authenticating the user.\n\t *\n\t * @example ['urn:mace:incommon:iap:bronze', 'urn:mace:incommon:iap:silver']\n\t */\n\tacrValues?: Array<string> | null;\n\n\t/**\n\t * A list of BCP 47 language tags specifying the preferred display language for the customer-facing UI.\n\t * We uses this as a fallback when determining the display language.\n\t * It is only applied if no higher-priority signal is present.\n\t *\n\t * @see https://docs.strivacity.com/docs/translations\n\t * @example ['en-US', 'fr-FR', 'de-DE']\n\t */\n\tuiLocales?: Array<string> | null;\n\n\t/**\n\t * A list of audience values to specify the intended recipients of the token.\n\t * This parameter allows requesting that the issued token is intended for specific audiences.\n\t *\n\t * @example ['https://api.example.com', 'https://service.example.com']\n\t */\n\taudiences?: Array<string> | null;\n};\n\nexport type EntryResponse = {\n\t/**\n\t * The session ID associated with the entry flow. This is a unique identifier for the session and can be used to track or manage the session.\n\t */\n\tsession_id: string;\n\n\t/**\n\t * The short application ID associated with the entry flow. This is a unique identifier for the application and can be used to identify the application in various contexts.\n\t */\n\tshort_app_id: string;\n\n\t/**\n\t * The language code associated with the entry flow. This indicates the preferred language for the user interface and can be used to provide localized content.\n\t */\n\tlanguage: string;\n\n\t[key: string]: string;\n};\n\nexport type SDKOptions<Storage extends SDKStorage = SDKStorage, StateStorage extends SDKStorage = SDKStorage> = {\n\t/**\n\t * A factory function that creates an instance of the SDK based on the provided initialization options.\n\t *\n\t * @param options - The initialization options for the SDK.\n\t * @returns The instance created by the factory function.\n\t */\n\tfactory?: (options: SDKInitConfig) => unknown;\n\n\t/**\n\t * The mode of operation for the SDK, which determines how authentication flows are handled.\n\t *\n\t * @default 'redirect'\n\t */\n\tmode: 'popup' | 'redirect' | 'native' | 'embedded';\n\n\t/**\n\t * The issuer of the tokens, typically the URL of the authorization server.\n\t */\n\tissuer: string;\n\n\t/**\n\t * The client ID issued by the authorization server, used to identify the application.\n\t */\n\tclientId: string;\n\n\t/**\n\t * The URI to which the user will be redirected after authentication or authorization.\n\t */\n\tredirectUri: string;\n\n\t/**\n\t * A list of scopes requested by the application, defining the access levels for the tokens.\n\t *\n\t * @default ['openid']\n\t */\n\tscopes: Array<string>;\n\n\t/**\n\t * The type of response expected from the authorization server.\n\t *\n\t * @default 'code'\n\t */\n\tresponseType: ResponseType;\n\n\t/**\n\t * The mode in which the response is returned from the authorization server.\n\t *\n\t * @default 'query'\n\t */\n\tresponseMode: ResponseMode;\n\n\t/**\n\t * The storage mechanism used to save and retrieve authentication information.\n\t *\n\t * @default Storage\n\t */\n\tstorage: Storage;\n\n\t/**\n\t * The storage mechanism used to save and retrieve state information, such as the state parameter in OAuth flows.\n\t *\n\t * @default StateStorage\n\t */\n\tstateStorage: StateStorage;\n\n\t/**\n\t * The name of the storage token used to store session data.\n\t *\n\t * @default 'sty.session'\n\t */\n\tstorageTokenName: string;\n\n\t/**\n\t * The HTTP client used for making requests to the authorization server and other endpoints.\n\t */\n\thttpClient: SDKHttpClient;\n\n\t/**\n\t * The logging mechanism used for logging messages and errors.\n\t */\n\tlogging?: SDKLogging;\n\n\t/**\n\t * Indicates whether the SDK should be lazily loaded, meaning that it will be initialized only when needed.\n\t *\n\t * @default false\n\t */\n\tlazyLoad: boolean;\n\n\t/**\n\t * Indicates whether the SDK should automatically refresh tokens when they are about to expire.\n\t *\n\t * @default true\n\t */\n\tautoRefresh: boolean;\n\n\t/**\n\t * The URL of your backend-for-frontend (BFF) endpoint that the SDK will route login/registration/start-session requests to instead of building the authorization URL itself.\n\t * Setting this also switches the SDK into server-managed session mode: tokens are never read from or written to client-side storage, and successful authorization responses redirect the browser instead of being exchanged for tokens client-side.\n\t * If not set, the SDK talks to the IDP directly and manages the session client-side.\n\t *\n\t * @default '/auth/login'\n\t */\n\tserverSessionUri?: boolean | string | null;\n\n\t/**\n\t * Discovery document metadata is cached for this amount of time (in seconds) before being refreshed from the authorization server.\n\t *\n\t * @default 3600 (1 hour)\n\t */\n\tdiscoveryDocumentCacheTTL: number;\n\n\t/**\n\t * JWKS (JSON Web Key Set) is cached for this amount of time (in seconds) before being refreshed from the authorization server.\n\t *\n\t * @default 600 (10 minutes)\n\t */\n\tjwksCacheTTL: number;\n\n\t/**\n\t * Handles the URL redirection to the specified target.\n\t * You can use this method to implement custom URL handling logic, such as opening a new window or navigating to a different page.\n\t *\n\t * @param {string | URL} url - The URL to handle.\n\t * @param {Record<string, unknown>} params - Optional parameters for redirection.\n\t * @returns - A promise that resolves when the redirection is handled.\n\t */\n\turlHandler: (url: string | URL, params?: Record<string, unknown>) => Promise<unknown>;\n\n\t/**\n\t * Handles the callback from the authorization server after a successful authentication or authorization.\n\t * You can use this method to implement custom logic for processing the response from the authorization server.\n\t *\n\t * @param {string | URL} url - The URL containing the response from the authorization server.\n\t * @param {ResponseMode} [responseMode] - Optional parameter specifying the response mode (query or fragment).\n\t * @returns - A promise that resolves when the callback is handled.\n\t */\n\tcallbackHandler: (url: string | URL, responseMode?: ResponseMode) => Promise<unknown>;\n};\n\nexport type SDKInitConfig = Partial<SDKOptions> & Required<Pick<SDKOptions, 'mode' | 'issuer' | 'clientId' | 'redirectUri'>>;\n\nexport type FlowState = {\n\t/**\n\t * Indicates whether the SDK has been initialized and is ready for use.\n\t */\n\tinitialized: boolean;\n\n\t/**\n\t * The current session data, which may include tokens and related information.\n\t */\n\tsession: SessionData | null;\n\n\t/**\n\t * The unique identifier for the current session, which may be used for tracking and correlation.\n\t */\n\tsessionId: string | null;\n\n\t/**\n\t * The short application identifier, which may be used for tracking and correlation.\n\t */\n\tshortAppId: string | null;\n\n\t/**\n\t * The language preference for the authentication flow, which may be used for localization.\n\t *\n\t * @default navigator.language\n\t */\n\tlanguage: string;\n};\n\nexport type EventFunctions = {\n\taccessTokenExpired: (params?: { accessToken?: string | null; refreshToken?: string | null }) => Promise<void> | void;\n\tinit: () => Promise<void> | void;\n\tloggedIn: (params?: {\n\t\tidToken?: string | null;\n\t\taccessToken?: string | null;\n\t\trefreshToken?: string | null;\n\t\tclaims?: IdTokenClaims | null;\n\t}) => Promise<void> | void;\n\tsessionUpdated: (params?: {\n\t\tidToken?: string | null;\n\t\taccessToken?: string | null;\n\t\trefreshToken?: string | null;\n\t\tclaims?: IdTokenClaims | null;\n\t}) => Promise<void> | void;\n\tsessionCleared: () => Promise<void> | void;\n\tloginInitiated: () => Promise<void> | void;\n\tflowInitiated: () => Promise<void> | void;\n\tlogoutInitiated: (params?: { idToken?: string | null; claims?: IdTokenClaims | null }) => Promise<void> | void;\n\tsessionLoaded: (params?: {\n\t\tidToken?: string | null;\n\t\taccessToken?: string | null;\n\t\trefreshToken?: string | null;\n\t\tclaims?: IdTokenClaims | null;\n\t}) => Promise<void> | void;\n\ttokenRefreshed: (params?: {\n\t\tidToken?: string | null;\n\t\taccessToken?: string | null;\n\t\trefreshToken?: string | null;\n\t\tclaims?: IdTokenClaims | null;\n\t}) => Promise<void> | void;\n\ttokenRefreshFailed: (params?: { refreshToken?: string | null }) => Promise<void> | void;\n\ttokenRevoked: (params?: { token?: string | null; tokenTypeHint?: 'refresh_token' | 'access_token' }) => Promise<void> | void;\n\ttokenRevokeFailed: (params?: { token?: string | null; tokenTypeHint?: 'refresh_token' | 'access_token' }) => Promise<void> | void;\n};\n\nexport type SDK<URLHandlerParams extends ExtraRequestArgs = ExtraRequestArgs, EntryReturnType = Promise<void>> = {\n\t/**\n\t * The resolved SDK configuration options in use.\n\t */\n\treadonly options: SDKOptions;\n\n\t/**\n\t * Whether the SDK has been fully initialized.\n\t */\n\treadonly initialized: boolean;\n\n\t/**\n\t * The storage adapter used to persist session and state data.\n\t */\n\treadonly storage: SDKStorage;\n\n\t/**\n\t * The HTTP client adapter used for making requests.\n\t */\n\treadonly httpClient: SDKHttpClient;\n\n\t/**\n\t * The optional logging adapter for SDK diagnostic output.\n\t */\n\treadonly logging?: SDKLogging;\n\n\t/**\n\t * The current session data, or `null` if no session is active.\n\t */\n\tsession: SessionData | null;\n\n\t/**\n\t * The short application ID associated with the current session, or `null` if not yet available.\n\t */\n\tshortAppId: string | null;\n\n\t/**\n\t * The unique identifier for the current session, or `null` if no session is active.\n\t */\n\tsessionId: string | null;\n\n\t/**\n\t * The language code used for the authentication UI.\n\t */\n\tlanguage: string;\n\n\t/**\n\t * A promise that resolves to `true` if the user is currently authenticated, `false` otherwise.\n\t */\n\treadonly isAuthenticated: Promise<boolean>;\n\n\t/**\n\t * A synchronous boolean indicating whether the user is currently authenticated.\n\t * This value may not reflect the most recent authentication state if the SDK has not been initialized or if a token refresh is pending.\n\t */\n\treadonly isAuthenticatedSync: boolean;\n\n\t/**\n\t * The current access token, or `null` if the user is not authenticated.\n\t */\n\treadonly accessToken: string | null;\n\n\t/**\n\t * Indicates whether the current access token has expired.\n\t */\n\treadonly accessTokenExpired: boolean;\n\n\t/**\n\t * The expiration time of the current access token, represented as a Unix timestamp (seconds since epoch), or `null` if no access token is present.\n\t */\n\treadonly accessTokenExpirationDate: number | null;\n\n\t/**\n\t * The current refresh token, or `null` if the user is not authenticated.\n\t */\n\treadonly refreshToken: string | null;\n\n\t/**\n\t * The current ID token, or `null` if the user is not authenticated.\n\t */\n\treadonly idToken: string | null;\n\n\t/**\n\t * The claims extracted from the current ID token, or `null` if no ID token is present.\n\t */\n\treadonly idTokenClaims: IdTokenClaims | null;\n\n\t/**\n\t * Subscribes to a specific SDK event by name.\n\t *\n\t * @template T - The name of the event to subscribe to.\n\t * @param {T} eventName - The name of the event.\n\t * @param {Function} callbackFn - The callback to invoke when the event fires.\n\t * @returns {{ dispose: () => void }} An object with a `dispose` method to remove the subscription.\n\t */\n\tsubscribeToEvent<T extends keyof EventFunctions>(\n\t\teventName: T,\n\t\tcallbackFn: (...params: Parameters<EventFunctions[T]>) => Promise<void> | void,\n\t): { dispose: () => void };\n\n\t/**\n\t * Subscribes to all SDK events.\n\t *\n\t * @param {Function} callbackFn - The callback to invoke whenever any event fires.\n\t * @returns {{ dispose: () => void }} An object with a `dispose` method to remove the subscription.\n\t */\n\tsubscribeToAllEvents(callbackFn: (...params: Array<unknown>) => Promise<void> | void): { dispose: () => void };\n\n\t/**\n\t * Clears the current session data from storage.\n\t *\n\t * @returns {Promise<void>}\n\t */\n\tcleanupSession(): Promise<void>;\n\n\t/**\n\t * Replaces the current session data with the provided data.\n\t *\n\t * @param {SessionData} newData - The new session data to persist.\n\t * @returns {Promise<void>}\n\t */\n\tupdateSession(newData: SessionData): Promise<void>;\n\n\t/**\n\t * Checks whether the user is currently authenticated, optionally triggering a token refresh.\n\t *\n\t * @param {{ autoRefresh: boolean }} [params] - Options for the check.\n\t * @returns {Promise<boolean>} Resolves to `true` if authenticated, `false` otherwise.\n\t */\n\tcheckAuthentication(params?: { autoRefresh: boolean }): Promise<boolean>;\n\n\t/**\n\t * Initializes the SDK, loading metadata and restoring any persisted session.\n\t *\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the stored session cannot be loaded.\n\t */\n\tinit(): Promise<void>;\n\n\t/**\n\t * Performs a token exchange using the provided parameters.\n\t *\n\t * @param {Record<string, string>} [params] - Additional parameters for the token exchange request.\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the token exchange fails or if the provided parameters are invalid.\n\t */\n\ttokenExchange(params?: Record<string, string>): Promise<void>;\n\n\t/**\n\t * Handles the authentication callback by parsing the response from the given URL.\n\t *\n\t * @param {string | URL} [url] - The callback URL to process. Defaults to the current page URL if omitted.\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the callback handling fails or if the URL is invalid.\n\t */\n\thandleCallback(url?: string | URL): Promise<void>;\n\n\t/**\n\t * Refreshes the current access token using the refresh token.\n\t *\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the refresh process fails or if no refresh token is available.\n\t */\n\trefresh(): Promise<void>;\n\n\t/**\n\t * Revokes the current tokens.\n\t *\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the revocation process fails or if no tokens are available to revoke.\n\t */\n\trevoke(): Promise<void>;\n\n\t/**\n\t * Logs the user out and optionally redirects to a post-logout URI.\n\t *\n\t * @param {LogoutParams} [params] - Optional logout and URL handler parameters.\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the logout url handling fails or if the provided parameters are invalid.\n\t */\n\tlogout(params?: LogoutParams): Promise<void>;\n\n\t/**\n\t * Initiates the login flow.\n\t *\n\t * @param {URLHandlerParams} [params] - Optional parameters for the login request.\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the login process fails or if the provided parameters are invalid.\n\t */\n\tlogin(params?: URLHandlerParams): Promise<void>;\n\n\t/**\n\t * Initiates the registration flow.\n\t *\n\t * @param {URLHandlerParams} [params] - Optional parameters for the registration request.\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the registration process fails or if the provided parameters are invalid.\n\t */\n\tregister(params?: URLHandlerParams): Promise<void>;\n\n\t/**\n\t * Handles the entry point URL of the authentication flow, typically used for embedded or native modes.\n\t *\n\t * @param {string | URL} [url] - The entry URL to process.\n\t * @param {RedirectOptions} [params] - Optional redirect options.\n\t * @returns {EntryReturnType}\n\t * @throws {Error} Throws an error if the entry URL is invalid or if the entry process fails.\n\t */\n\tentry(url?: string | URL, params?: RedirectOptions): EntryReturnType;\n};\n"],"mappings":"mEAIA,IAAa,EAAmB,CAAC,MAAM,EAG1B,EAAmB,CAAC,QAAS,UAAU,EAGvC,EAA8B,CAAC,MAAM,EAGrC,EAAgB,CAAC,qBAAsB,eAAe,EAGtD,EAAoB,CAAC,OAAO,EAG5B,EAAkB,CAAC,QAAQ"}
|
|
1
|
+
{"version":3,"file":"oidc.cjs","names":[],"sources":["../../src/types/oidc.ts"],"sourcesContent":["import type { SDKHttpClient, SDKLogging, SDKStorage } from './common';\nimport type { RedirectOptions } from './redirect';\nimport type { BACKCHANNEL_LOGOUT_EVENT } from '../utils/server';\n\nexport const ResponseTypeList = ['code'] as const;\nexport type ResponseType = (typeof ResponseTypeList)[number];\n\nexport const ResponseModeList = ['query', 'fragment'] as const;\nexport type ResponseMode = (typeof ResponseModeList)[number];\n\nexport const TokenEndpointAuthMethodList = ['none'] as const;\nexport type TokenEndpointAuthMethod = (typeof TokenEndpointAuthMethodList)[number];\n\nexport const GrantTypeList = ['authorization_code', 'refresh_token'] as const;\nexport type GrantType = (typeof GrantTypeList)[number];\n\nexport const AlgorithmTypeList = ['RS256'] as const;\nexport type AlgorithmType = (typeof AlgorithmTypeList)[number];\n\nexport const SubjectTypeList = ['public'] as const;\nexport type SubjectType = (typeof SubjectTypeList)[number];\n\nexport type SigningKey = {\n\t/**\n\t * The intended use of the key. Common values include \"sig\" for signature and \"enc\" for encryption.\n\t */\n\tuse: string;\n\n\t/**\n\t * The key type. For example, \"RSA\" for RSA keys or \"EC\" for Elliptic Curve keys.\n\t */\n\tkty: string;\n\n\t/**\n\t * A unique identifier for the key. This is used to distinguish the key from others.\n\t */\n\tkid: string;\n\n\t/**\n\t * The algorithm used with the key. For example, \"RS256\" for RSA SHA-256.\n\t */\n\talg: AlgorithmType;\n\n\t/**\n\t * The modulus of the RSA key, encoded in base64url format. For RSA keys, this is a required property.\n\t */\n\tn: string;\n\n\t/**\n\t * The exponent of the RSA key, encoded in base64url format. For RSA keys, this is a required property.\n\t */\n\te: string;\n};\n\nexport type DiscoveryDocument = {\n\t/**\n\t * The issuer of the tokens. This is the authorization server or entity that issues the tokens.\n\t */\n\tissuer: string;\n\n\t/**\n\t * The URL of the authorization endpoint where authentication requests are sent.\n\t */\n\tauthorization_endpoint: string;\n\n\t/**\n\t * The URL of the token endpoint where tokens are exchanged.\n\t */\n\ttoken_endpoint: string;\n\n\t/**\n\t * The URL of the JSON Web Key Set (JWKS) endpoint where public keys are available.\n\t */\n\tjwks_uri: string;\n\n\t/**\n\t * The types of subjects that are supported by the authorization server.\n\t */\n\tsubject_types_supported: Array<SubjectType>;\n\n\t/**\n\t * The types of responses supported by the authorization server.\n\t */\n\tresponse_types_supported: Array<string>;\n\n\t/**\n\t * The claims supported by the authorization server.\n\t */\n\tclaims_supported: Array<string>;\n\n\t/**\n\t * The grant types supported by the authorization server.\n\t */\n\tgrant_types_supported: Array<GrantType>;\n\n\t/**\n\t * The response modes supported by the authorization server.\n\t */\n\tresponse_modes_supported: Array<ResponseMode>;\n\n\t/**\n\t * The URL of the user info endpoint where user information can be retrieved.\n\t */\n\tuserinfo_endpoint: string;\n\n\t/**\n\t * The scopes supported by the authorization server.\n\t */\n\tscopes_supported: Array<string>;\n\n\t/**\n\t * The authentication methods supported for token endpoint authentication.\n\t */\n\ttoken_endpoint_auth_methods_supported: Array<TokenEndpointAuthMethod>;\n\n\t/**\n\t * The algorithms supported for signing tokens used in the user info endpoint.\n\t */\n\tuserinfo_signing_alg_values_supported: Array<AlgorithmType>;\n\n\t/**\n\t * The algorithms supported for signing ID tokens.\n\t */\n\tid_token_signing_alg_values_supported: Array<AlgorithmType>;\n\n\t/**\n\t * The algorithms used to sign ID tokens in response.\n\t */\n\tid_token_signed_response_alg: Array<AlgorithmType>;\n\n\t/**\n\t * The algorithms used to sign responses from the user info endpoint.\n\t */\n\tuserinfo_signed_response_alg: Array<AlgorithmType>;\n\n\t/**\n\t * Indicates whether the request parameter is supported in requests.\n\t */\n\trequest_parameter_supported: boolean;\n\n\t/**\n\t * Indicates whether the request URI parameter is supported in requests.\n\t */\n\trequest_uri_parameter_supported: boolean;\n\n\t/**\n\t * Indicates whether request URI registration is required.\n\t */\n\trequire_request_uri_registration: boolean;\n\n\t/**\n\t * Indicates whether the claims parameter is supported.\n\t */\n\tclaims_parameter_supported: boolean;\n\n\t/**\n\t * The URL of the revocation endpoint for revoking tokens.\n\t */\n\trevocation_endpoint: string;\n\n\t/**\n\t * Indicates whether backchannel logout is supported.\n\t */\n\tbackchannel_logout_supported: boolean;\n\n\t/**\n\t * Indicates whether backchannel logout session support is provided.\n\t */\n\tbackchannel_logout_session_supported: boolean;\n\n\t/**\n\t * Indicates whether frontchannel logout is supported.\n\t */\n\tfrontchannel_logout_supported: boolean;\n\n\t/**\n\t * Indicates whether frontchannel logout session support is provided.\n\t */\n\tfrontchannel_logout_session_supported: boolean;\n\n\t/**\n\t * The URL of the endpoint where end-session requests can be sent.\n\t */\n\tend_session_endpoint: string;\n\n\t/**\n\t * The algorithms supported for signing request objects.\n\t */\n\trequest_object_signing_alg_values_supported: Array<AlgorithmType>;\n\n\t/**\n\t * The code challenge methods supported by the authorization server.\n\t */\n\tcode_challenge_methods_supported: Array<'S256'>;\n};\n\nexport type JwtClaims = {\n\t/**\n\t * The issuer of the token. This typically represents the authorization server or entity that issued the JWT.\n\t */\n\tiss?: string;\n\n\t/**\n\t * The subject of the token. This is the identifier for the entity the token represents, such as a user ID.\n\t */\n\tsub?: string;\n\n\t/**\n\t * The audience for which the token is intended. This can be a single identifier or an array of identifiers.\n\t */\n\taud?: string | Array<string>;\n\n\t/**\n\t * The expiration time of the token, expressed as a Unix timestamp (number of seconds since January 1, 1970).\n\t */\n\texp?: number;\n\n\t/**\n\t * The not-before time of the token, expressed as a Unix timestamp. The token must not be accepted before this time.\n\t */\n\tnbf?: number;\n\n\t/**\n\t * The issued-at time of the token, expressed as a Unix timestamp (number of seconds since January 1, 1970).\n\t */\n\tiat?: number;\n\n\t/**\n\t * A unique identifier for the token. This can be used to prevent token replay attacks.\n\t */\n\tjti?: string;\n};\n\nexport type IdTokenClaims = Required<Pick<JwtClaims, 'iss' | 'sub' | 'aud' | 'exp' | 'iat' | 'jti'>> & {\n\t/**\n\t * The authentication time, indicating when the user was authenticated.\n\t */\n\tauth_time?: number;\n\n\t/**\n\t * A nonce value used to associate a client session with an ID token, preventing replay attacks.\n\t */\n\tnonce?: string;\n\n\t/**\n\t * The Authentication Context Class Reference, indicating the authentication methods used.\n\t */\n\tacr?: string;\n\n\t/**\n\t * The Authentication Methods References, providing information about the authentication methods used.\n\t */\n\tamr?: unknown;\n\n\t/**\n\t * Authorized party, the client that the ID token is intended for.\n\t */\n\tazp?: string;\n\n\t/**\n\t * Session ID for the user, which can be used to manage user sessions.\n\t */\n\tsid?: string;\n\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t[key: string]: any;\n};\n\nexport type LogoutTokenClaims = Pick<JwtClaims, 'iss' | 'sub' | 'aud' | 'iat' | 'jti'> & {\n\t/**\n\t * Session ID for the user, which can be used to clear a specific session.\n\t */\n\tsid?: string;\n\n\t/**\n\t * Spec-compliant event signal for OpenID Connect Back-Channel Logout.\n\t */\n\tevents: Record<typeof BACKCHANNEL_LOGOUT_EVENT, Record<string, never>>;\n\n\t/**\n\t * MUST NOT contain a nonce claim according to the OIDC Back-Channel Logout spec.\n\t */\n\tnonce?: never;\n\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t[key: string]: any;\n};\n\nexport type SessionData = {\n\t/**\n\t * The state parameter used in the authentication request.\n\t */\n\tstate?: string | null;\n\n\t/**\n\t * The authorization code returned by the authorization server.\n\t */\n\tcode?: string | null;\n\n\t/**\n\t * The error returned during the authentication process, if any.\n\t */\n\terror?: string | null;\n\n\t/**\n\t * A description of the error returned during authentication.\n\t */\n\terror_description?: string | null;\n\n\t/**\n\t * A URI identifying a human-readable web page with information about the error (RFC 6749).\n\t */\n\terror_uri?: string | null;\n\n\t/**\n\t * Opaque value representing the session state at the authorization server (OIDC Session Management).\n\t */\n\tsession_state?: string | null;\n\n\t/**\n\t * The ID token issued by the authorization server.\n\t */\n\tid_token?: string | null;\n\n\t/**\n\t * The access token issued by the authorization server.\n\t */\n\taccess_token?: string | null;\n\n\t/**\n\t * The refresh token issued by the authorization server.\n\t */\n\trefresh_token?: string | null;\n\n\t/**\n\t * The type of token issued, defaulting to 'bearer'.\n\t */\n\ttoken_type?: string;\n\n\t/**\n\t * The scope of the issued token.\n\t */\n\tscope?: string | null;\n\n\t/**\n\t * The lifetime of the access token in seconds, as returned by the token endpoint.\n\t */\n\texpires_in?: number | null;\n\n\t/**\n\t * The absolute expiration time of the access token, represented as a Unix timestamp (seconds since epoch).\n\t */\n\texpires_at?: number | null;\n\n\t/**\n\t * The claims associated with the ID token.\n\t */\n\tclaims?: IdTokenClaims | null;\n};\n\nexport type LoginSessionParams = {\n\t/**\n\t * The unique identifier of the login session.\n\t */\n\tsession_id?: string;\n\n\t/**\n\t * The short application identifier associated with the login session.\n\t */\n\tshort_app_id?: string;\n\n\t/**\n\t * BCP 47 language tag representing the language preference for the login session.\n\t */\n\tlanguage?: string;\n};\n\nexport type StateData = {\n\t/**\n\t * A unique identifier for the state.\n\t */\n\tid: string;\n\n\t/**\n\t * The timestamp when the state was created, represented as a Unix timestamp (seconds since epoch).\n\t */\n\tcreatedAt: number;\n\n\t/**\n\t * The code verifier used in the PKCE flow.\n\t */\n\tcodeVerifier: string;\n\n\t/**\n\t * The code challenge derived from the code verifier, used in the PKCE flow.\n\t */\n\tcodeChallenge: string;\n\n\t/**\n\t * A unique nonce value used to associate a client session with an ID token, preventing replay attacks.\n\t */\n\tnonce: string;\n\n\t/**\n\t * Optional metadata associated with the state, which can be used to store additional information relevant to the authentication flow.\n\t */\n\tmetadata?: Record<string, unknown>;\n};\n\nexport type LogoutParams = {\n\t/**\n\t * The URL to which the user should be redirected after logging out.\n\t */\n\tpostLogoutRedirectUri?: string;\n};\n\nexport type ExtraRequestArgs = {\n\t/**\n\t * Specifies the type of prompt to display to the user during authentication or authorization.\n\t *\n\t * @example 'none' | 'login' | 'create'\n\t */\n\tprompt?: string | null;\n\n\t/**\n\t * Specifies the display mode for the authentication or authorization request.\n\t *\n\t * @example 'page' | 'popup'\n\t */\n\tdisplay?: string | null;\n\n\t/**\n\t * Provides a hint to the authorization server about the user's email or username.\n\t *\n\t * @example 'user@example.com'\n\t */\n\tloginHint?: string | null;\n\n\t/**\n\t * A list of values used to request specific authentication contexts or levels of assurance.\n\t * This parameter allows requesting specific authentication contexts (e.g., multi-factor authentication)\n\t * or other criteria that the authorization server should consider when authenticating the user.\n\t *\n\t * @example ['urn:mace:incommon:iap:bronze', 'urn:mace:incommon:iap:silver']\n\t */\n\tacrValues?: Array<string> | null;\n\n\t/**\n\t * A list of BCP 47 language tags specifying the preferred display language for the customer-facing UI.\n\t * We uses this as a fallback when determining the display language.\n\t * It is only applied if no higher-priority signal is present.\n\t *\n\t * @see https://docs.strivacity.com/docs/translations\n\t * @example ['en-US', 'fr-FR', 'de-DE']\n\t */\n\tuiLocales?: Array<string> | null;\n\n\t/**\n\t * A list of audience values to specify the intended recipients of the token.\n\t * This parameter allows requesting that the issued token is intended for specific audiences.\n\t *\n\t * @example ['https://api.example.com', 'https://service.example.com']\n\t */\n\taudiences?: Array<string> | null;\n};\n\nexport type EntryResponse = {\n\t/**\n\t * The session ID associated with the entry flow. This is a unique identifier for the session and can be used to track or manage the session.\n\t */\n\tsession_id: string;\n\n\t/**\n\t * The short application ID associated with the entry flow. This is a unique identifier for the application and can be used to identify the application in various contexts.\n\t */\n\tshort_app_id: string;\n\n\t/**\n\t * The language code associated with the entry flow. This indicates the preferred language for the user interface and can be used to provide localized content.\n\t */\n\tlanguage: string;\n\n\t[key: string]: string;\n};\n\nexport type SDKOptions<Storage extends SDKStorage = SDKStorage, StateStorage extends SDKStorage = SDKStorage> = {\n\t/**\n\t * A factory function that creates an instance of the SDK based on the provided initialization options.\n\t *\n\t * @param options - The initialization options for the SDK.\n\t * @returns The instance created by the factory function.\n\t */\n\tfactory?: (options: SDKInitConfig) => unknown;\n\n\t/**\n\t * The mode of operation for the SDK, which determines how authentication flows are handled.\n\t *\n\t * @default 'redirect'\n\t */\n\tmode: 'popup' | 'redirect' | 'native' | 'embedded';\n\n\t/**\n\t * The issuer of the tokens, typically the URL of the authorization server.\n\t */\n\tissuer: string;\n\n\t/**\n\t * The client ID issued by the authorization server, used to identify the application.\n\t */\n\tclientId: string;\n\n\t/**\n\t * The URI to which the user will be redirected after authentication or authorization.\n\t */\n\tredirectUri: string;\n\n\t/**\n\t * A list of scopes requested by the application, defining the access levels for the tokens.\n\t *\n\t * @default ['openid']\n\t */\n\tscopes: Array<string>;\n\n\t/**\n\t * The type of response expected from the authorization server.\n\t *\n\t * @default 'code'\n\t */\n\tresponseType: ResponseType;\n\n\t/**\n\t * The mode in which the response is returned from the authorization server.\n\t *\n\t * @default 'query'\n\t */\n\tresponseMode: ResponseMode;\n\n\t/**\n\t * The storage mechanism used to save and retrieve authentication information.\n\t *\n\t * @default Storage\n\t */\n\tstorage: Storage;\n\n\t/**\n\t * The storage mechanism used to save and retrieve state information, such as the state parameter in OAuth flows.\n\t *\n\t * @default StateStorage\n\t */\n\tstateStorage: StateStorage;\n\n\t/**\n\t * The name of the storage token used to store session data.\n\t *\n\t * @default 'sty.session'\n\t */\n\tstorageTokenName: string;\n\n\t/**\n\t * The HTTP client used for making requests to the authorization server and other endpoints.\n\t */\n\thttpClient: SDKHttpClient;\n\n\t/**\n\t * The logging mechanism used for logging messages and errors.\n\t */\n\tlogging?: SDKLogging;\n\n\t/**\n\t * Indicates whether the SDK should be lazily loaded, meaning that it will be initialized only when needed.\n\t *\n\t * @default false\n\t */\n\tlazyLoad: boolean;\n\n\t/**\n\t * Indicates whether the SDK should automatically refresh tokens when they are about to expire.\n\t *\n\t * @default true\n\t */\n\tautoRefresh: boolean;\n\n\t/**\n\t * The amount of time (in seconds) before the access token's expiration that the SDK should attempt to refresh it.\n\t *\n\t * @default 60\n\t */\n\trefreshSkew: number;\n\n\t/**\n\t * The URL of your backend-for-frontend (BFF) endpoint that the SDK will route login/registration/start-session requests to instead of building the authorization URL itself.\n\t * Setting this also switches the SDK into server-managed session mode: tokens are never read from or written to client-side storage, and successful authorization responses redirect the browser instead of being exchanged for tokens client-side.\n\t * If not set, the SDK talks to the IDP directly and manages the session client-side.\n\t *\n\t * @default '/auth/login'\n\t */\n\tserverSessionUri?: boolean | string | null;\n\n\t/**\n\t * Discovery document metadata is cached for this amount of time (in seconds) before being refreshed from the authorization server.\n\t *\n\t * @default 3600 (1 hour)\n\t */\n\tdiscoveryDocumentCacheTTL: number;\n\n\t/**\n\t * JWKS (JSON Web Key Set) is cached for this amount of time (in seconds) before being refreshed from the authorization server.\n\t *\n\t * @default 600 (10 minutes)\n\t */\n\tjwksCacheTTL: number;\n\n\t/**\n\t * Handles the URL redirection to the specified target.\n\t * You can use this method to implement custom URL handling logic, such as opening a new window or navigating to a different page.\n\t *\n\t * @param {string | URL} url - The URL to handle.\n\t * @param {Record<string, unknown>} params - Optional parameters for redirection.\n\t * @returns - A promise that resolves when the redirection is handled.\n\t */\n\turlHandler: (url: string | URL, params?: Record<string, unknown>) => Promise<unknown>;\n\n\t/**\n\t * Handles the callback from the authorization server after a successful authentication or authorization.\n\t * You can use this method to implement custom logic for processing the response from the authorization server.\n\t *\n\t * @param {string | URL} url - The URL containing the response from the authorization server.\n\t * @param {ResponseMode} [responseMode] - Optional parameter specifying the response mode (query or fragment).\n\t * @returns - A promise that resolves when the callback is handled.\n\t */\n\tcallbackHandler: (url: string | URL, responseMode?: ResponseMode) => Promise<unknown>;\n};\n\nexport type SDKInitConfig = Partial<SDKOptions> & Required<Pick<SDKOptions, 'mode' | 'issuer' | 'clientId' | 'redirectUri'>>;\n\nexport type FlowState = {\n\t/**\n\t * Indicates whether the SDK has been initialized and is ready for use.\n\t */\n\tinitialized: boolean;\n\n\t/**\n\t * The current session data, which may include tokens and related information.\n\t */\n\tsession: SessionData | null;\n\n\t/**\n\t * The unique identifier for the current session, which may be used for tracking and correlation.\n\t */\n\tsessionId: string | null;\n\n\t/**\n\t * The short application identifier, which may be used for tracking and correlation.\n\t */\n\tshortAppId: string | null;\n\n\t/**\n\t * The language preference for the authentication flow, which may be used for localization.\n\t *\n\t * @default navigator.language\n\t */\n\tlanguage: string;\n};\n\nexport type EventFunctions = {\n\taccessTokenExpired: (params?: { accessToken?: string | null; refreshToken?: string | null }) => Promise<void> | void;\n\tinit: () => Promise<void> | void;\n\tloggedIn: (params?: {\n\t\tidToken?: string | null;\n\t\taccessToken?: string | null;\n\t\trefreshToken?: string | null;\n\t\tclaims?: IdTokenClaims | null;\n\t}) => Promise<void> | void;\n\tsessionUpdated: (params?: {\n\t\tidToken?: string | null;\n\t\taccessToken?: string | null;\n\t\trefreshToken?: string | null;\n\t\tclaims?: IdTokenClaims | null;\n\t}) => Promise<void> | void;\n\tsessionCleared: () => Promise<void> | void;\n\tloginInitiated: () => Promise<void> | void;\n\tflowInitiated: () => Promise<void> | void;\n\tlogoutInitiated: (params?: { idToken?: string | null; claims?: IdTokenClaims | null }) => Promise<void> | void;\n\tsessionLoaded: (params?: {\n\t\tidToken?: string | null;\n\t\taccessToken?: string | null;\n\t\trefreshToken?: string | null;\n\t\tclaims?: IdTokenClaims | null;\n\t}) => Promise<void> | void;\n\ttokenRefreshed: (params?: {\n\t\tidToken?: string | null;\n\t\taccessToken?: string | null;\n\t\trefreshToken?: string | null;\n\t\tclaims?: IdTokenClaims | null;\n\t}) => Promise<void> | void;\n\ttokenRefreshFailed: (params?: { refreshToken?: string | null }) => Promise<void> | void;\n\ttokenRevoked: (params?: { token?: string | null; tokenTypeHint?: 'refresh_token' | 'access_token' }) => Promise<void> | void;\n\ttokenRevokeFailed: (params?: { token?: string | null; tokenTypeHint?: 'refresh_token' | 'access_token' }) => Promise<void> | void;\n};\n\nexport type SDK<URLHandlerParams extends ExtraRequestArgs = ExtraRequestArgs, EntryReturnType = Promise<void>> = {\n\t/**\n\t * The resolved SDK configuration options in use.\n\t */\n\treadonly options: SDKOptions;\n\n\t/**\n\t * Whether the SDK has been fully initialized.\n\t */\n\treadonly initialized: boolean;\n\n\t/**\n\t * The storage adapter used to persist session and state data.\n\t */\n\treadonly storage: SDKStorage;\n\n\t/**\n\t * The HTTP client adapter used for making requests.\n\t */\n\treadonly httpClient: SDKHttpClient;\n\n\t/**\n\t * The optional logging adapter for SDK diagnostic output.\n\t */\n\treadonly logging?: SDKLogging;\n\n\t/**\n\t * The current session data, or `null` if no session is active.\n\t */\n\tsession: SessionData | null;\n\n\t/**\n\t * The short application ID associated with the current session, or `null` if not yet available.\n\t */\n\tshortAppId: string | null;\n\n\t/**\n\t * The unique identifier for the current session, or `null` if no session is active.\n\t */\n\tsessionId: string | null;\n\n\t/**\n\t * The language code used for the authentication UI.\n\t */\n\tlanguage: string;\n\n\t/**\n\t * A promise that resolves to `true` if the user is currently authenticated, `false` otherwise.\n\t */\n\treadonly isAuthenticated: Promise<boolean>;\n\n\t/**\n\t * A synchronous boolean indicating whether the user is currently authenticated.\n\t * This value may not reflect the most recent authentication state if the SDK has not been initialized or if a token refresh is pending.\n\t */\n\treadonly isAuthenticatedSync: boolean;\n\n\t/**\n\t * The current access token, or `null` if the user is not authenticated.\n\t */\n\treadonly accessToken: string | null;\n\n\t/**\n\t * Indicates whether the current access token has expired.\n\t */\n\treadonly accessTokenExpired: boolean;\n\n\t/**\n\t * The expiration time of the current access token, represented as a Unix timestamp (seconds since epoch), or `null` if no access token is present.\n\t */\n\treadonly accessTokenExpirationDate: number | null;\n\n\t/**\n\t * The current refresh token, or `null` if the user is not authenticated.\n\t */\n\treadonly refreshToken: string | null;\n\n\t/**\n\t * The current ID token, or `null` if the user is not authenticated.\n\t */\n\treadonly idToken: string | null;\n\n\t/**\n\t * The claims extracted from the current ID token, or `null` if no ID token is present.\n\t */\n\treadonly idTokenClaims: IdTokenClaims | null;\n\n\t/**\n\t * Subscribes to a specific SDK event by name.\n\t *\n\t * @template T - The name of the event to subscribe to.\n\t * @param {T} eventName - The name of the event.\n\t * @param {Function} callbackFn - The callback to invoke when the event fires.\n\t * @returns {{ dispose: () => void }} An object with a `dispose` method to remove the subscription.\n\t */\n\tsubscribeToEvent<T extends keyof EventFunctions>(\n\t\teventName: T,\n\t\tcallbackFn: (...params: Parameters<EventFunctions[T]>) => Promise<void> | void,\n\t): { dispose: () => void };\n\n\t/**\n\t * Subscribes to all SDK events.\n\t *\n\t * @param {Function} callbackFn - The callback to invoke whenever any event fires.\n\t * @returns {{ dispose: () => void }} An object with a `dispose` method to remove the subscription.\n\t */\n\tsubscribeToAllEvents(callbackFn: (...params: Array<unknown>) => Promise<void> | void): { dispose: () => void };\n\n\t/**\n\t * Clears the current session data from storage.\n\t *\n\t * @returns {Promise<void>}\n\t */\n\tcleanupSession(): Promise<void>;\n\n\t/**\n\t * Replaces the current session data with the provided data.\n\t *\n\t * @param {SessionData} newData - The new session data to persist.\n\t * @returns {Promise<void>}\n\t */\n\tupdateSession(newData: SessionData): Promise<void>;\n\n\t/**\n\t * Checks whether the user is currently authenticated, optionally triggering a token refresh.\n\t *\n\t * @param {{ autoRefresh: boolean }} [params] - Options for the check.\n\t * @returns {Promise<boolean>} Resolves to `true` if authenticated, `false` otherwise.\n\t */\n\tcheckAuthentication(params?: { autoRefresh: boolean }): Promise<boolean>;\n\n\t/**\n\t * Initializes the SDK, loading metadata and restoring any persisted session.\n\t *\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the stored session cannot be loaded.\n\t */\n\tinit(): Promise<void>;\n\n\t/**\n\t * Performs a token exchange using the provided parameters.\n\t *\n\t * @param {Record<string, string>} [params] - Additional parameters for the token exchange request.\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the token exchange fails or if the provided parameters are invalid.\n\t */\n\ttokenExchange(params?: Record<string, string>): Promise<void>;\n\n\t/**\n\t * Handles the authentication callback by parsing the response from the given URL.\n\t *\n\t * @param {string | URL} [url] - The callback URL to process. Defaults to the current page URL if omitted.\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the callback handling fails or if the URL is invalid.\n\t */\n\thandleCallback(url?: string | URL): Promise<void>;\n\n\t/**\n\t * Refreshes the current access token using the refresh token.\n\t *\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the refresh process fails or if no refresh token is available.\n\t */\n\trefresh(): Promise<void>;\n\n\t/**\n\t * Revokes the current tokens.\n\t *\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the revocation process fails or if no tokens are available to revoke.\n\t */\n\trevoke(): Promise<void>;\n\n\t/**\n\t * Logs the user out and optionally redirects to a post-logout URI.\n\t *\n\t * @param {LogoutParams} [params] - Optional logout and URL handler parameters.\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the logout url handling fails or if the provided parameters are invalid.\n\t */\n\tlogout(params?: LogoutParams): Promise<void>;\n\n\t/**\n\t * Initiates the login flow.\n\t *\n\t * @param {URLHandlerParams} [params] - Optional parameters for the login request.\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the login process fails or if the provided parameters are invalid.\n\t */\n\tlogin(params?: URLHandlerParams): Promise<void>;\n\n\t/**\n\t * Initiates the registration flow.\n\t *\n\t * @param {URLHandlerParams} [params] - Optional parameters for the registration request.\n\t * @returns {Promise<void>}\n\t * @throws {Error} Throws an error if the registration process fails or if the provided parameters are invalid.\n\t */\n\tregister(params?: URLHandlerParams): Promise<void>;\n\n\t/**\n\t * Handles the entry point URL of the authentication flow, typically used for embedded or native modes.\n\t *\n\t * @param {string | URL} [url] - The entry URL to process.\n\t * @param {RedirectOptions} [params] - Optional redirect options.\n\t * @returns {EntryReturnType}\n\t * @throws {Error} Throws an error if the entry URL is invalid or if the entry process fails.\n\t */\n\tentry(url?: string | URL, params?: RedirectOptions): EntryReturnType;\n};\n"],"mappings":"mEAIA,IAAa,EAAmB,CAAC,MAAM,EAG1B,EAAmB,CAAC,QAAS,UAAU,EAGvC,EAA8B,CAAC,MAAM,EAGrC,EAAgB,CAAC,qBAAsB,eAAe,EAGtD,EAAoB,CAAC,OAAO,EAG5B,EAAkB,CAAC,QAAQ"}
|
package/dist/types/oidc.d.ts
CHANGED
|
@@ -470,6 +470,12 @@ export type SDKOptions<Storage extends SDKStorage = SDKStorage, StateStorage ext
|
|
|
470
470
|
* @default true
|
|
471
471
|
*/
|
|
472
472
|
autoRefresh: boolean;
|
|
473
|
+
/**
|
|
474
|
+
* The amount of time (in seconds) before the access token's expiration that the SDK should attempt to refresh it.
|
|
475
|
+
*
|
|
476
|
+
* @default 60
|
|
477
|
+
*/
|
|
478
|
+
refreshSkew: number;
|
|
473
479
|
/**
|
|
474
480
|
* The URL of your backend-for-frontend (BFF) endpoint that the SDK will route login/registration/start-session requests to instead of building the authorization URL itself.
|
|
475
481
|
* Setting this also switches the SDK into server-managed session mode: tokens are never read from or written to client-side storage, and successful authorization responses redirect the browser instead of being exchanged for tokens client-side.
|