@nekm/sveltekit-armor 0.3.11 → 0.4.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 CHANGED
@@ -19,7 +19,7 @@ Create a `src/hooks.server.ts` and write:
19
19
  ```js
20
20
  import { armor, armorCookieSession } from '@nekm/sveltekit-armor';
21
21
 
22
- export const handle = armor({
22
+ const { handle: armorHandle } = armor({
23
23
  oauth: {
24
24
  clientId: 'foo',
25
25
  clientSecret: 'bar',
@@ -28,6 +28,8 @@ export const handle = armor({
28
28
  },
29
29
  session: armorCookieSession,
30
30
  });
31
+
32
+ export const handle = armorHandle;
31
33
  ```
32
34
 
33
35
  Done. Entire app now requires login.
@@ -60,11 +62,11 @@ Assume you only want to protect routes prefixed by `admin`. Create a `src/hooks.
60
62
  ```js
61
63
  import { armor } from '@nekm/sveltekit-armor';
62
64
 
63
- const protect = armor({ /* config */ });
65
+ const { handle: armorHandle } = armor({ /* config */ });
64
66
 
65
67
  export const handle = ({ event, resolve }) => {
66
68
  if (event.url.pathname.startsWith('/admin')) {
67
- return protect({ event, resolve });
69
+ return armorHandle({ event, resolve });
68
70
  }
69
71
 
70
72
  return resolve(event);
package/dist/index.d.ts CHANGED
@@ -1,9 +1,13 @@
1
1
  import { type Handle } from "@sveltejs/kit";
2
2
  import type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from "./contracts";
3
+ import { ArmorRefresh } from "./utils/refresh";
3
4
  export type { ArmorConfig, ArmorTokens };
4
5
  export { armorCookieSession, armorCookieSessionGet } from "./session/cookie";
5
6
  export { armorRefreshFactory } from "./utils/refresh";
6
- export declare function armor(config: ArmorConfig): Handle;
7
+ interface Armor extends ArmorRefresh {
8
+ readonly handle: Handle;
9
+ }
10
+ export declare function armor(config: ArmorConfig): Armor;
7
11
  /**
8
12
  * Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.
9
13
  * Use that to create your config.
package/dist/index.esm.js CHANGED
@@ -302,7 +302,7 @@ function armorRefreshFactory(config) {
302
302
  const refreshEndpoint = (_config$oauth$refresh = config.oauth.refreshEndpoint) != null ? _config$oauth$refresh : urlConcat(config.oauth.baseUrl, "oauth2/token");
303
303
  const jwksUrl = new URL((_config$oauth$jwksEnd = config.oauth.jwksEndpoint) != null ? _config$oauth$jwksEnd : urlConcat(config.oauth.baseUrl, ".well-known/jwks.json"));
304
304
  const refresh = async (fetch, refreshToken) => {
305
- var _json$refresh_token;
305
+ var _json$refresh_token, _config$logger, _config$logger2;
306
306
  const body = new URLSearchParams({
307
307
  grant_type: "refresh_token",
308
308
  client_id: config.oauth.clientId,
@@ -325,10 +325,21 @@ function armorRefreshFactory(config) {
325
325
  throw new ArmorRefreshError(`Could not refresh token: ${error}`);
326
326
  }
327
327
  const json = await response.json();
328
- return {
328
+ const newExchange = {
329
329
  ...json,
330
330
  refresh_token: (_json$refresh_token = json.refresh_token) != null ? _json$refresh_token : refreshToken
331
331
  };
332
+ (_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Exchange code for tokens.", {
333
+ newExchange
334
+ });
335
+ const jwks = createRemoteJWKSet(jwksUrl);
336
+ const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, newExchange.id_token), jwtVerifyAccessToken(config, jwks, newExchange.access_token)]);
337
+ (_config$logger2 = config.logger) == null || _config$logger2.debug == null || _config$logger2.debug("Extract and verify tokens.", {
338
+ idToken,
339
+ accessToken
340
+ });
341
+ const validTokens = exchangeToTokens(newExchange, idToken, accessToken);
342
+ return validTokens;
332
343
  };
333
344
  return {
334
345
  refresh,
@@ -336,22 +347,12 @@ function armorRefreshFactory(config) {
336
347
  try {
337
348
  let validTokens = tokens;
338
349
  if (shouldRefresh(tokens)) {
339
- var _config$logger, _config$logger2, _config$logger3;
340
- (_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Tokens has expired. Refreshing...");
350
+ var _config$logger3;
351
+ (_config$logger3 = config.logger) == null || _config$logger3.debug == null || _config$logger3.debug("Tokens has expired. Refreshing...");
341
352
  if (!tokens.exchange.refresh_token) {
342
353
  throw redirect(302, ROUTE_PATH_LOGIN);
343
354
  }
344
- const newExchange = await refresh(fetch, tokens.exchange.refresh_token);
345
- (_config$logger2 = config.logger) == null || _config$logger2.debug == null || _config$logger2.debug("Exchange code for tokens.", {
346
- newExchange
347
- });
348
- const jwks = createRemoteJWKSet(jwksUrl);
349
- const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, newExchange.id_token), jwtVerifyAccessToken(config, jwks, newExchange.access_token)]);
350
- (_config$logger3 = config.logger) == null || _config$logger3.debug == null || _config$logger3.debug("Extract and verify tokens.", {
351
- idToken,
352
- accessToken
353
- });
354
- validTokens = exchangeToTokens(newExchange, idToken, accessToken);
355
+ validTokens = await refresh(fetch, tokens.exchange.refresh_token);
355
356
  await config.session.login(event, validTokens);
356
357
  }
357
358
  return fn(validTokens);
@@ -398,24 +399,27 @@ const armorCookieSession = {
398
399
  function armor(config) {
399
400
  const routeByPath = routeByPathFactory(config);
400
401
  const refresh = armorRefreshFactory(config);
401
- return async ({
402
- event,
403
- resolve
404
- }) => {
405
- const route = routeByPath.get(event.url.pathname);
406
- if (route) {
407
- return route.handle({
408
- event,
409
- resolve
410
- });
411
- }
412
- const tokens = await config.session.getTokens(event);
413
- if (!tokens) {
414
- var _config$logger;
415
- (_config$logger = config.logger) == null || _config$logger.warning == null || _config$logger.warning("Could not find tokens. Redirecting to login.");
416
- throw redirect(302, ROUTE_PATH_LOGIN);
402
+ return {
403
+ ...refresh,
404
+ async handle({
405
+ event,
406
+ resolve
407
+ }) {
408
+ const route = routeByPath.get(event.url.pathname);
409
+ if (route) {
410
+ return route.handle({
411
+ event,
412
+ resolve
413
+ });
414
+ }
415
+ const tokens = await config.session.getTokens(event);
416
+ if (!tokens) {
417
+ var _config$logger;
418
+ (_config$logger = config.logger) == null || _config$logger.warning == null || _config$logger.warning("Could not find tokens. Redirecting to login.");
419
+ throw redirect(302, ROUTE_PATH_LOGIN);
420
+ }
421
+ return refresh.ensureValidToken(event, tokens, () => resolve(event));
417
422
  }
418
- return refresh.ensureValidToken(event, tokens, () => resolve(event));
419
423
  };
420
424
  }
421
425
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/utils/utils.ts","../src/utils/jwt.ts","../src/utils/cookie.ts","../src/errors.ts","../src/utils/event.ts","../src/routes/redirect-login.ts","../src/browser/index.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/utils/refresh.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type {\n\tArmorAccessToken,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n\nconst MINUTES_MS = 60 * 1000;\n\nexport function shouldRefresh(\n\ttokens: Pick<ArmorTokens, \"idToken\" | \"accessToken\">,\n): boolean {\n\tconst idExpiry = tokens.idToken.exp * 1000;\n\n\tconst accessExpiry =\n\t\ttypeof tokens.accessToken !== \"string\" &&\n\t\ttokens.accessToken.exp !== undefined\n\t\t\t? tokens.accessToken.exp * 1000\n\t\t\t: Infinity;\n\n\treturn Math.min(idExpiry, accessExpiry) < Date.now() + 5 * MINUTES_MS;\n}\n\nexport function createExpiresAt(seconds: number): Date {\n\tconst now = new Date();\n\tnow.setSeconds(now.getSeconds() + seconds);\n\treturn now;\n}\n\nexport function exchangeToTokens(\n\texchange: ArmorTokenExchange,\n\tidToken: ArmorIdToken,\n\taccessToken?: ArmorAccessToken,\n): ArmorTokens {\n\treturn {\n\t\texchange,\n\t\tidToken: idToken as ArmorIdToken,\n\t\t// Generally, IdP's require an audience to get a JWT\n\t\t// access token. Most cases, this doesn't matter.\n\t\taccessToken: accessToken ?? exchange.access_token,\n\t\texpiresAt: createExpiresAt(exchange.expires_in),\n\t};\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\nimport { throwIfUndefined } from \"@nekm/core\";\n\nfunction jwtIsCompactJwt(token: string): boolean {\n\t// Must be three base64url segments\n\tconst parts = token.trim().split(\".\");\n\treturn parts.length === 3 && parts.every((p) => p.length > 0);\n}\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\tconst payload = jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n\tthrowIfUndefined(payload);\n\t// @ts-expect-error We're already verifying non-null above.\n\treturn payload;\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload | undefined> {\n\tconst opts: JWTVerifyOptions = { issuer: config.oauth.issuer };\n\n\tif (config.oauth.audience) {\n\t\topts.audience = config.oauth.audience;\n\t}\n\n\treturn jwtVerifyToken(jwks, opts, accessToken);\n}\n\nfunction isInvalidCompactJwt(error: unknown): boolean {\n\treturn Boolean(\n\t\ttypeof error === \"object\" &&\n\t\terror &&\n\t\t\"message\" in error &&\n\t\ttypeof error.message === \"string\" &&\n\t\t/invalid compact jws/gi.test(error.message),\n\t);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload | undefined> {\n\ttry {\n\t\tif (!jwtIsCompactJwt(token)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst { payload } = await jwtVerify(token, jwks, opts);\n\t\treturn payload;\n\t} catch (error) {\n\t\tif (isInvalidCompactJwt(error)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\" as const;\nexport const COOKIE_STATE = \"state\" as const;\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\nexport class ArmorRefreshError extends ArmorError {}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport { COOKIE_STATE, cookieGetAndDelete } from \"./cookie\";\nimport { ArmorInvalidStateError } from \"../errors\";\n\nexport function eventStateValidOrThrow(event: RequestEvent): void {\n\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\tif (state !== stateCookie) {\n\t\tthrow new ArmorInvalidStateError();\n\t}\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { queryParamsCreate, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange, exchangeToTokens } from \"../utils/utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"../utils/jwt\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\n\nexport const ROUTE_PATH_REDIRECT_LOGIN = \"/_armor/redirect/login\";\n\nexport const routeRedirectLoginFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst tokenUrl =\n\t\tconfig.oauth.tokenEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst params: Record<string, string> = {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\tcode,\n\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\tscope,\n\t\t};\n\n\t\tif (config.oauth.audience) {\n\t\t\tparams.audience = config.oauth.audience;\n\t\t}\n\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams(params).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle login redirect callback.\");\n\n\t\t\teventStateValidOrThrow(event);\n\n\t\t\tconst error = event.url.searchParams.get(\"error\") ?? undefined;\n\n\t\t\tif (error) {\n\t\t\t\tconst error_description =\n\t\t\t\t\tevent.url.searchParams.get(\"error_description\") ?? undefined;\n\n\t\t\t\tconfig.logger?.error?.(\"Login returned error.\", {\n\t\t\t\t\terror,\n\t\t\t\t\terrorDescription: error_description,\n\t\t\t\t});\n\n\t\t\t\tif (!config.oauth.errorLoginRedirectPath) {\n\t\t\t\t\treturn new Response(`${error}\\n${error_description}`.trimEnd(), {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"text/plain\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst errorParams = queryParamsCreate({ error, error_description });\n\t\t\t\tthrow redirect(\n\t\t\t\t\t302,\n\t\t\t\t\t`${config.oauth.errorLoginRedirectPath}?${errorParams}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst code = event.url.searchParams.get(\"code\") ?? undefined;\n\t\t\tconfig.logger?.debug?.(\"Get code from query params.\", { code });\n\t\t\tthrowIfUndefined(code);\n\n\t\t\tconst exchange = await exchangeCodeForToken(\n\t\t\t\tevent.fetch,\n\t\t\t\tevent.url.origin,\n\t\t\t\tcode,\n\t\t\t);\n\n\t\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { exchange });\n\n\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\tjwtVerifyIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\t\tidToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tawait config.session.login(\n\t\t\t\tevent,\n\t\t\t\texchangeToTokens(exchange, idToken as ArmorIdToken, accessToken),\n\t\t\t);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","export const ARMOR_LOGIN = \"/_armor/login\" as const;\nexport const ARMOR_LOGOUT = \"/_armor/logout\" as const;\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGIN } from \"../browser\";\n\nexport const ROUTE_PATH_LOGIN = ARMOR_LOGIN;\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = {\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t\tscope,\n\t\t\t\taudience: config.oauth.audience,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre login redirect.\", { params, state });\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle logout redirect callback.\");\n\n\t\t\tawait config.session.logout(event);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGOUT } from \"./redirect-logout\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGOUT } from \"../browser\";\n\nexport const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst returnTo = config.oauth.logoutReturnToParam ?? \"logout_uri\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = {\n\t\t\t\t[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre logout redirect.\", { params });\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import type { Handle } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { routeLoginFactory } from \"./login\";\nimport { routeLogoutFactory } from \"./logout\";\nimport { routeRedirectLogoutFactory } from \"./redirect-logout\";\nimport { routeRedirectLoginFactory } from \"./redirect-login\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n]);\n\nexport function routeByPathFactory(config: ArmorConfig): Map<string, Route> {\n\t// @ts-expect-error Incorrect typing error.\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route]),\n\t);\n}\n","import { createRemoteJWKSet } from \"jose\";\nimport {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\nimport { ArmorRefreshError } from \"../errors\";\nimport { exchangeToTokens, shouldRefresh, urlConcat } from \"./utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"./jwt\";\nimport { redirect, RequestEvent } from \"@sveltejs/kit\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ROUTE_PATH_LOGIN } from \"../routes/login\";\n\nexport function armorRefreshFactory(config: ArmorConfig) {\n\tconst refreshEndpoint =\n\t\tconfig.oauth.refreshEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst refresh = async (\n\t\tfetch: typeof global.fetch,\n\t\trefreshToken: string,\n\t): Promise<ArmorTokenExchange> => {\n\t\tconst body = new URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\trefresh_token: refreshToken,\n\t\t});\n\n\t\tif (config.oauth.scope) {\n\t\t\tbody.set(\"scope\", config.oauth.scope);\n\t\t}\n\n\t\tconst response = await fetch(refreshEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: body.toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new ArmorRefreshError(`Could not refresh token: ${error}`);\n\t\t}\n\n\t\tconst json: ArmorTokenExchange = await response.json();\n\n\t\treturn {\n\t\t\t...json,\n\t\t\trefresh_token: json.refresh_token ?? refreshToken,\n\t\t};\n\t};\n\n\treturn {\n\t\trefresh,\n\t\tasync ensureValidToken<T>(\n\t\t\tevent: RequestEvent,\n\t\t\ttokens: ArmorTokens,\n\t\t\tfn: (tokens: ArmorTokens) => T | Promise<T>,\n\t\t): Promise<T> {\n\t\t\ttry {\n\t\t\t\tlet validTokens = tokens;\n\n\t\t\t\tif (shouldRefresh(tokens)) {\n\t\t\t\t\tconfig.logger?.debug?.(\"Tokens has expired. Refreshing...\");\n\n\t\t\t\t\tif (!tokens.exchange.refresh_token) {\n\t\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst newExchange = await refresh(\n\t\t\t\t\t\tfetch,\n\t\t\t\t\t\ttokens.exchange.refresh_token,\n\t\t\t\t\t);\n\n\t\t\t\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { newExchange });\n\n\t\t\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\t\t\tjwtVerifyIdToken(config, jwks, newExchange.id_token),\n\t\t\t\t\t\tjwtVerifyAccessToken(config, jwks, newExchange.access_token),\n\t\t\t\t\t]);\n\n\t\t\t\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\t\t\t\tidToken,\n\t\t\t\t\t\taccessToken,\n\t\t\t\t\t});\n\n\t\t\t\t\tvalidTokens = exchangeToTokens(\n\t\t\t\t\t\tnewExchange,\n\t\t\t\t\t\tidToken as ArmorIdToken,\n\t\t\t\t\t\taccessToken,\n\t\t\t\t\t);\n\n\t\t\t\t\tawait config.session.login(event, validTokens);\n\t\t\t\t}\n\n\t\t\t\treturn fn(validTokens);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof ArmorRefreshError) {\n\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport {\n\tCOOKIE_TOKENS,\n\tcookieDelete,\n\tcookieGet,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport { ArmorConfig, ArmorTokens } from \"../contracts\";\nimport { ArmorAuthMissingError } from \"../errors\";\n\nfunction cookieSessionGetTokens({\n\tcookies,\n}: RequestEvent): ArmorTokens | undefined {\n\treturn cookies.get(COOKIE_TOKENS) as ArmorTokens | undefined;\n}\n\nexport function cookieSessionLogin(\n\t{ cookies }: RequestEvent,\n\ttokens: ArmorTokens,\n): void {\n\tcookieSet(cookies, COOKIE_TOKENS, tokens);\n}\n\nfunction cookieSessionLogout({ cookies }: RequestEvent): void {\n\tcookieDelete(cookies, COOKIE_TOKENS);\n}\n\nexport function armorCookieSessionGet({ cookies }: RequestEvent): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\n\tif (!tokens) {\n\t\tthrow new ArmorAuthMissingError();\n\t}\n\n\treturn tokens;\n}\n\nexport const armorCookieSession: ArmorConfig[\"session\"] = {\n\tgetTokens: cookieSessionGetTokens,\n\tlogin: cookieSessionLogin,\n\tlogout: cookieSessionLogout,\n};\n","import { redirect, type Handle } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { routeByPathFactory } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\nimport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\nexport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routeByPath = routeByPathFactory(config);\n\tconst refresh = armorRefreshFactory(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst route = routeByPath.get(event.url.pathname);\n\n\t\tif (route) {\n\t\t\treturn route.handle({ event, resolve });\n\t\t}\n\n\t\tconst tokens = await config.session.getTokens(event);\n\n\t\tif (!tokens) {\n\t\t\tconfig.logger?.warning?.(\"Could not find tokens. Redirecting to login.\");\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn refresh.ensureValidToken(event, tokens, () => resolve(event));\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.\n * Use that to create your config.\n * @param config\n * @param fetch\n */\nexport async function armorConfigFromOpenId(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n): Promise<ArmorConfig> {\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(config.oauth.openIdConfigEndpoint, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn {\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksEndpoint: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t\trefreshEndpoint: body.token_endpoint,\n\t\t},\n\t};\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","MINUTES_MS","shouldRefresh","tokens","idExpiry","idToken","exp","accessExpiry","accessToken","Infinity","Math","min","Date","now","createExpiresAt","seconds","setSeconds","getSeconds","exchangeToTokens","exchange","expiresAt","jwtIsCompactJwt","token","parts","trim","split","length","every","p","jwtVerifyIdToken","config","jwks","payload","jwtVerifyToken","issuer","oauth","audience","clientId","throwIfUndefined","jwtVerifyAccessToken","opts","isInvalidCompactJwt","error","Boolean","message","test","jwtVerify","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","cookieDelete","ArmorError","Error","ArmorOpenIdConfigError","ArmorInvalidStateError","ArmorAuthMissingError","ArmorRefreshError","eventStateValidOrThrow","event","_event$url$searchPara","state","url","searchParams","stateCookie","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksEnd","_config$oauth$tokenEn","_config$oauth$scope","jwksUrl","URL","jwksEndpoint","baseUrl","tokenUrl","tokenEndpoint","exchangeCodeForToken","fetch","code","params","grant_type","client_id","client_secret","clientSecret","redirect_uri","response","method","headers","Accept","body","URLSearchParams","toString","ok","text","json","handle","_config$logger","_event$url$searchPara3","_config$logger3","_config$logger4","_config$logger5","logger","debug","_event$url$searchPara2","_config$logger2","error_description","errorDescription","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","createRemoteJWKSet","Promise","all","session","login","ARMOR_LOGIN","ARMOR_LOGOUT","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","paramsStr","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","routeFactories","routeByPathFactory","Map","map","routeFactory","filter","route","armorRefreshFactory","_config$oauth$refresh","refreshEndpoint","refresh","refreshToken","_json$refresh_token","ensureValidToken","fn","validTokens","newExchange","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","getTokens","armor","routeByPath","resolve","pathname","warning","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/utils/utils.ts","../src/utils/jwt.ts","../src/utils/cookie.ts","../src/errors.ts","../src/utils/event.ts","../src/routes/redirect-login.ts","../src/browser/index.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/utils/refresh.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type {\n\tArmorAccessToken,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n\nconst MINUTES_MS = 60 * 1000;\n\nexport function shouldRefresh(\n\ttokens: Pick<ArmorTokens, \"idToken\" | \"accessToken\">,\n): boolean {\n\tconst idExpiry = tokens.idToken.exp * 1000;\n\n\tconst accessExpiry =\n\t\ttypeof tokens.accessToken !== \"string\" &&\n\t\ttokens.accessToken.exp !== undefined\n\t\t\t? tokens.accessToken.exp * 1000\n\t\t\t: Infinity;\n\n\treturn Math.min(idExpiry, accessExpiry) < Date.now() + 5 * MINUTES_MS;\n}\n\nexport function createExpiresAt(seconds: number): Date {\n\tconst now = new Date();\n\tnow.setSeconds(now.getSeconds() + seconds);\n\treturn now;\n}\n\nexport function exchangeToTokens(\n\texchange: ArmorTokenExchange,\n\tidToken: ArmorIdToken,\n\taccessToken?: ArmorAccessToken,\n): ArmorTokens {\n\treturn {\n\t\texchange,\n\t\tidToken: idToken as ArmorIdToken,\n\t\t// Generally, IdP's require an audience to get a JWT\n\t\t// access token. Most cases, this doesn't matter.\n\t\taccessToken: accessToken ?? exchange.access_token,\n\t\texpiresAt: createExpiresAt(exchange.expires_in),\n\t};\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\nimport { throwIfUndefined } from \"@nekm/core\";\n\nfunction jwtIsCompactJwt(token: string): boolean {\n\t// Must be three base64url segments\n\tconst parts = token.trim().split(\".\");\n\treturn parts.length === 3 && parts.every((p) => p.length > 0);\n}\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\tconst payload = jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n\tthrowIfUndefined(payload);\n\t// @ts-expect-error We're already verifying non-null above.\n\treturn payload;\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload | undefined> {\n\tconst opts: JWTVerifyOptions = { issuer: config.oauth.issuer };\n\n\tif (config.oauth.audience) {\n\t\topts.audience = config.oauth.audience;\n\t}\n\n\treturn jwtVerifyToken(jwks, opts, accessToken);\n}\n\nfunction isInvalidCompactJwt(error: unknown): boolean {\n\treturn Boolean(\n\t\ttypeof error === \"object\" &&\n\t\terror &&\n\t\t\"message\" in error &&\n\t\ttypeof error.message === \"string\" &&\n\t\t/invalid compact jws/gi.test(error.message),\n\t);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload | undefined> {\n\ttry {\n\t\tif (!jwtIsCompactJwt(token)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst { payload } = await jwtVerify(token, jwks, opts);\n\t\treturn payload;\n\t} catch (error) {\n\t\tif (isInvalidCompactJwt(error)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\" as const;\nexport const COOKIE_STATE = \"state\" as const;\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\nexport class ArmorRefreshError extends ArmorError {}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport { COOKIE_STATE, cookieGetAndDelete } from \"./cookie\";\nimport { ArmorInvalidStateError } from \"../errors\";\n\nexport function eventStateValidOrThrow(event: RequestEvent): void {\n\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\tif (state !== stateCookie) {\n\t\tthrow new ArmorInvalidStateError();\n\t}\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { queryParamsCreate, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange, exchangeToTokens } from \"../utils/utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"../utils/jwt\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\n\nexport const ROUTE_PATH_REDIRECT_LOGIN = \"/_armor/redirect/login\";\n\nexport const routeRedirectLoginFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst tokenUrl =\n\t\tconfig.oauth.tokenEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst params: Record<string, string> = {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\tcode,\n\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\tscope,\n\t\t};\n\n\t\tif (config.oauth.audience) {\n\t\t\tparams.audience = config.oauth.audience;\n\t\t}\n\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams(params).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle login redirect callback.\");\n\n\t\t\teventStateValidOrThrow(event);\n\n\t\t\tconst error = event.url.searchParams.get(\"error\") ?? undefined;\n\n\t\t\tif (error) {\n\t\t\t\tconst error_description =\n\t\t\t\t\tevent.url.searchParams.get(\"error_description\") ?? undefined;\n\n\t\t\t\tconfig.logger?.error?.(\"Login returned error.\", {\n\t\t\t\t\terror,\n\t\t\t\t\terrorDescription: error_description,\n\t\t\t\t});\n\n\t\t\t\tif (!config.oauth.errorLoginRedirectPath) {\n\t\t\t\t\treturn new Response(`${error}\\n${error_description}`.trimEnd(), {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"text/plain\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst errorParams = queryParamsCreate({ error, error_description });\n\t\t\t\tthrow redirect(\n\t\t\t\t\t302,\n\t\t\t\t\t`${config.oauth.errorLoginRedirectPath}?${errorParams}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst code = event.url.searchParams.get(\"code\") ?? undefined;\n\t\t\tconfig.logger?.debug?.(\"Get code from query params.\", { code });\n\t\t\tthrowIfUndefined(code);\n\n\t\t\tconst exchange = await exchangeCodeForToken(\n\t\t\t\tevent.fetch,\n\t\t\t\tevent.url.origin,\n\t\t\t\tcode,\n\t\t\t);\n\n\t\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { exchange });\n\n\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\tjwtVerifyIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\t\tidToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tawait config.session.login(\n\t\t\t\tevent,\n\t\t\t\texchangeToTokens(exchange, idToken as ArmorIdToken, accessToken),\n\t\t\t);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","export const ARMOR_LOGIN = \"/_armor/login\" as const;\nexport const ARMOR_LOGOUT = \"/_armor/logout\" as const;\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGIN } from \"../browser\";\n\nexport const ROUTE_PATH_LOGIN = ARMOR_LOGIN;\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = {\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t\tscope,\n\t\t\t\taudience: config.oauth.audience,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre login redirect.\", { params, state });\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle logout redirect callback.\");\n\n\t\t\tawait config.session.logout(event);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGOUT } from \"./redirect-logout\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGOUT } from \"../browser\";\n\nexport const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst returnTo = config.oauth.logoutReturnToParam ?? \"logout_uri\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = {\n\t\t\t\t[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre logout redirect.\", { params });\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import type { Handle } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { routeLoginFactory } from \"./login\";\nimport { routeLogoutFactory } from \"./logout\";\nimport { routeRedirectLogoutFactory } from \"./redirect-logout\";\nimport { routeRedirectLoginFactory } from \"./redirect-login\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n]);\n\nexport function routeByPathFactory(config: ArmorConfig): Map<string, Route> {\n\t// @ts-expect-error Incorrect typing error.\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route]),\n\t);\n}\n","import { createRemoteJWKSet } from \"jose\";\nimport {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\nimport { ArmorRefreshError } from \"../errors\";\nimport { exchangeToTokens, shouldRefresh, urlConcat } from \"./utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"./jwt\";\nimport { redirect, RequestEvent } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"../routes/login\";\n\nexport interface ArmorRefresh {\n\treadonly refresh: (\n\t\tfetch: typeof global.fetch,\n\t\trefreshToken: string,\n\t) => Promise<ArmorTokens>;\n\treadonly ensureValidToken: <T>(\n\t\tevent: RequestEvent,\n\t\ttokens: ArmorTokens,\n\t\tfn: (tokens: ArmorTokens) => T | Promise<T>,\n\t) => Promise<T>;\n}\n\nexport function armorRefreshFactory(config: ArmorConfig): ArmorRefresh {\n\tconst refreshEndpoint =\n\t\tconfig.oauth.refreshEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst refresh = async (\n\t\tfetch: typeof global.fetch,\n\t\trefreshToken: string,\n\t): Promise<ArmorTokens> => {\n\t\tconst body = new URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\trefresh_token: refreshToken,\n\t\t});\n\n\t\tif (config.oauth.scope) {\n\t\t\tbody.set(\"scope\", config.oauth.scope);\n\t\t}\n\n\t\tconst response = await fetch(refreshEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: body.toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new ArmorRefreshError(`Could not refresh token: ${error}`);\n\t\t}\n\n\t\tconst json: ArmorTokenExchange = await response.json();\n\n\t\tconst newExchange = {\n\t\t\t...json,\n\t\t\trefresh_token: json.refresh_token ?? refreshToken,\n\t\t};\n\n\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { newExchange });\n\n\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\tjwtVerifyIdToken(config, jwks, newExchange.id_token),\n\t\t\tjwtVerifyAccessToken(config, jwks, newExchange.access_token),\n\t\t]);\n\n\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\tidToken,\n\t\t\taccessToken,\n\t\t});\n\n\t\tconst validTokens = exchangeToTokens(\n\t\t\tnewExchange,\n\t\t\tidToken as ArmorIdToken,\n\t\t\taccessToken,\n\t\t);\n\n\t\treturn validTokens;\n\t};\n\n\treturn {\n\t\trefresh,\n\t\tasync ensureValidToken<T>(\n\t\t\tevent: RequestEvent,\n\t\t\ttokens: ArmorTokens,\n\t\t\tfn: (tokens: ArmorTokens) => T | Promise<T>,\n\t\t): Promise<T> {\n\t\t\ttry {\n\t\t\t\tlet validTokens = tokens;\n\n\t\t\t\tif (shouldRefresh(tokens)) {\n\t\t\t\t\tconfig.logger?.debug?.(\"Tokens has expired. Refreshing...\");\n\n\t\t\t\t\tif (!tokens.exchange.refresh_token) {\n\t\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t\t}\n\n\t\t\t\t\tvalidTokens = await refresh(fetch, tokens.exchange.refresh_token);\n\n\t\t\t\t\tawait config.session.login(event, validTokens);\n\t\t\t\t}\n\n\t\t\t\treturn fn(validTokens);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof ArmorRefreshError) {\n\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport {\n\tCOOKIE_TOKENS,\n\tcookieDelete,\n\tcookieGet,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport { ArmorConfig, ArmorTokens } from \"../contracts\";\nimport { ArmorAuthMissingError } from \"../errors\";\n\nfunction cookieSessionGetTokens({\n\tcookies,\n}: RequestEvent): ArmorTokens | undefined {\n\treturn cookies.get(COOKIE_TOKENS) as ArmorTokens | undefined;\n}\n\nexport function cookieSessionLogin(\n\t{ cookies }: RequestEvent,\n\ttokens: ArmorTokens,\n): void {\n\tcookieSet(cookies, COOKIE_TOKENS, tokens);\n}\n\nfunction cookieSessionLogout({ cookies }: RequestEvent): void {\n\tcookieDelete(cookies, COOKIE_TOKENS);\n}\n\nexport function armorCookieSessionGet({ cookies }: RequestEvent): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\n\tif (!tokens) {\n\t\tthrow new ArmorAuthMissingError();\n\t}\n\n\treturn tokens;\n}\n\nexport const armorCookieSession: ArmorConfig[\"session\"] = {\n\tgetTokens: cookieSessionGetTokens,\n\tlogin: cookieSessionLogin,\n\tlogout: cookieSessionLogout,\n};\n","import { redirect, type Handle } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { routeByPathFactory } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\nimport { ArmorRefresh, armorRefreshFactory } from \"./utils/refresh\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\nexport { armorRefreshFactory } from \"./utils/refresh\";\n\ninterface Armor extends ArmorRefresh {\n\treadonly handle: Handle;\n}\n\nexport function armor(config: ArmorConfig): Armor {\n\tconst routeByPath = routeByPathFactory(config);\n\tconst refresh = armorRefreshFactory(config);\n\n\treturn {\n\t\t...refresh,\n\t\tasync handle({ event, resolve }) {\n\t\t\tconst route = routeByPath.get(event.url.pathname);\n\n\t\t\tif (route) {\n\t\t\t\treturn route.handle({ event, resolve });\n\t\t\t}\n\n\t\t\tconst tokens = await config.session.getTokens(event);\n\n\t\t\tif (!tokens) {\n\t\t\t\tconfig.logger?.warning?.(\n\t\t\t\t\t\"Could not find tokens. Redirecting to login.\",\n\t\t\t\t);\n\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t}\n\n\t\t\treturn refresh.ensureValidToken(event, tokens, () => resolve(event));\n\t\t},\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.\n * Use that to create your config.\n * @param config\n * @param fetch\n */\nexport async function armorConfigFromOpenId(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n): Promise<ArmorConfig> {\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(config.oauth.openIdConfigEndpoint, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn {\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksEndpoint: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t\trefreshEndpoint: body.token_endpoint,\n\t\t},\n\t};\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","MINUTES_MS","shouldRefresh","tokens","idExpiry","idToken","exp","accessExpiry","accessToken","Infinity","Math","min","Date","now","createExpiresAt","seconds","setSeconds","getSeconds","exchangeToTokens","exchange","expiresAt","jwtIsCompactJwt","token","parts","trim","split","length","every","p","jwtVerifyIdToken","config","jwks","payload","jwtVerifyToken","issuer","oauth","audience","clientId","throwIfUndefined","jwtVerifyAccessToken","opts","isInvalidCompactJwt","error","Boolean","message","test","jwtVerify","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","cookieDelete","ArmorError","Error","ArmorOpenIdConfigError","ArmorInvalidStateError","ArmorAuthMissingError","ArmorRefreshError","eventStateValidOrThrow","event","_event$url$searchPara","state","url","searchParams","stateCookie","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksEnd","_config$oauth$tokenEn","_config$oauth$scope","jwksUrl","URL","jwksEndpoint","baseUrl","tokenUrl","tokenEndpoint","exchangeCodeForToken","fetch","code","params","grant_type","client_id","client_secret","clientSecret","redirect_uri","response","method","headers","Accept","body","URLSearchParams","toString","ok","text","json","handle","_config$logger","_event$url$searchPara3","_config$logger3","_config$logger4","_config$logger5","logger","debug","_event$url$searchPara2","_config$logger2","error_description","errorDescription","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","createRemoteJWKSet","Promise","all","session","login","ARMOR_LOGIN","ARMOR_LOGOUT","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","paramsStr","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","routeFactories","routeByPathFactory","Map","map","routeFactory","filter","route","armorRefreshFactory","_config$oauth$refresh","refreshEndpoint","refresh","refreshToken","_json$refresh_token","newExchange","validTokens","ensureValidToken","fn","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","getTokens","armor","routeByPath","resolve","pathname","warning","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -302,7 +302,7 @@ function armorRefreshFactory(config) {
302
302
  const refreshEndpoint = (_config$oauth$refresh = config.oauth.refreshEndpoint) != null ? _config$oauth$refresh : urlConcat(config.oauth.baseUrl, "oauth2/token");
303
303
  const jwksUrl = new URL((_config$oauth$jwksEnd = config.oauth.jwksEndpoint) != null ? _config$oauth$jwksEnd : urlConcat(config.oauth.baseUrl, ".well-known/jwks.json"));
304
304
  const refresh = async (fetch, refreshToken) => {
305
- var _json$refresh_token;
305
+ var _json$refresh_token, _config$logger, _config$logger2;
306
306
  const body = new URLSearchParams({
307
307
  grant_type: "refresh_token",
308
308
  client_id: config.oauth.clientId,
@@ -325,10 +325,21 @@ function armorRefreshFactory(config) {
325
325
  throw new ArmorRefreshError(`Could not refresh token: ${error}`);
326
326
  }
327
327
  const json = await response.json();
328
- return {
328
+ const newExchange = {
329
329
  ...json,
330
330
  refresh_token: (_json$refresh_token = json.refresh_token) != null ? _json$refresh_token : refreshToken
331
331
  };
332
+ (_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Exchange code for tokens.", {
333
+ newExchange
334
+ });
335
+ const jwks = jose.createRemoteJWKSet(jwksUrl);
336
+ const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, newExchange.id_token), jwtVerifyAccessToken(config, jwks, newExchange.access_token)]);
337
+ (_config$logger2 = config.logger) == null || _config$logger2.debug == null || _config$logger2.debug("Extract and verify tokens.", {
338
+ idToken,
339
+ accessToken
340
+ });
341
+ const validTokens = exchangeToTokens(newExchange, idToken, accessToken);
342
+ return validTokens;
332
343
  };
333
344
  return {
334
345
  refresh,
@@ -336,22 +347,12 @@ function armorRefreshFactory(config) {
336
347
  try {
337
348
  let validTokens = tokens;
338
349
  if (shouldRefresh(tokens)) {
339
- var _config$logger, _config$logger2, _config$logger3;
340
- (_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Tokens has expired. Refreshing...");
350
+ var _config$logger3;
351
+ (_config$logger3 = config.logger) == null || _config$logger3.debug == null || _config$logger3.debug("Tokens has expired. Refreshing...");
341
352
  if (!tokens.exchange.refresh_token) {
342
353
  throw kit.redirect(302, ROUTE_PATH_LOGIN);
343
354
  }
344
- const newExchange = await refresh(fetch, tokens.exchange.refresh_token);
345
- (_config$logger2 = config.logger) == null || _config$logger2.debug == null || _config$logger2.debug("Exchange code for tokens.", {
346
- newExchange
347
- });
348
- const jwks = jose.createRemoteJWKSet(jwksUrl);
349
- const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, newExchange.id_token), jwtVerifyAccessToken(config, jwks, newExchange.access_token)]);
350
- (_config$logger3 = config.logger) == null || _config$logger3.debug == null || _config$logger3.debug("Extract and verify tokens.", {
351
- idToken,
352
- accessToken
353
- });
354
- validTokens = exchangeToTokens(newExchange, idToken, accessToken);
355
+ validTokens = await refresh(fetch, tokens.exchange.refresh_token);
355
356
  await config.session.login(event, validTokens);
356
357
  }
357
358
  return fn(validTokens);
@@ -398,24 +399,27 @@ const armorCookieSession = {
398
399
  function armor(config) {
399
400
  const routeByPath = routeByPathFactory(config);
400
401
  const refresh = armorRefreshFactory(config);
401
- return async ({
402
- event,
403
- resolve
404
- }) => {
405
- const route = routeByPath.get(event.url.pathname);
406
- if (route) {
407
- return route.handle({
408
- event,
409
- resolve
410
- });
411
- }
412
- const tokens = await config.session.getTokens(event);
413
- if (!tokens) {
414
- var _config$logger;
415
- (_config$logger = config.logger) == null || _config$logger.warning == null || _config$logger.warning("Could not find tokens. Redirecting to login.");
416
- throw kit.redirect(302, ROUTE_PATH_LOGIN);
402
+ return {
403
+ ...refresh,
404
+ async handle({
405
+ event,
406
+ resolve
407
+ }) {
408
+ const route = routeByPath.get(event.url.pathname);
409
+ if (route) {
410
+ return route.handle({
411
+ event,
412
+ resolve
413
+ });
414
+ }
415
+ const tokens = await config.session.getTokens(event);
416
+ if (!tokens) {
417
+ var _config$logger;
418
+ (_config$logger = config.logger) == null || _config$logger.warning == null || _config$logger.warning("Could not find tokens. Redirecting to login.");
419
+ throw kit.redirect(302, ROUTE_PATH_LOGIN);
420
+ }
421
+ return refresh.ensureValidToken(event, tokens, () => resolve(event));
417
422
  }
418
- return refresh.ensureValidToken(event, tokens, () => resolve(event));
419
423
  };
420
424
  }
421
425
  /**
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils/utils.ts","../src/utils/jwt.ts","../src/utils/cookie.ts","../src/errors.ts","../src/utils/event.ts","../src/routes/redirect-login.ts","../src/browser/index.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/utils/refresh.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type {\n\tArmorAccessToken,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n\nconst MINUTES_MS = 60 * 1000;\n\nexport function shouldRefresh(\n\ttokens: Pick<ArmorTokens, \"idToken\" | \"accessToken\">,\n): boolean {\n\tconst idExpiry = tokens.idToken.exp * 1000;\n\n\tconst accessExpiry =\n\t\ttypeof tokens.accessToken !== \"string\" &&\n\t\ttokens.accessToken.exp !== undefined\n\t\t\t? tokens.accessToken.exp * 1000\n\t\t\t: Infinity;\n\n\treturn Math.min(idExpiry, accessExpiry) < Date.now() + 5 * MINUTES_MS;\n}\n\nexport function createExpiresAt(seconds: number): Date {\n\tconst now = new Date();\n\tnow.setSeconds(now.getSeconds() + seconds);\n\treturn now;\n}\n\nexport function exchangeToTokens(\n\texchange: ArmorTokenExchange,\n\tidToken: ArmorIdToken,\n\taccessToken?: ArmorAccessToken,\n): ArmorTokens {\n\treturn {\n\t\texchange,\n\t\tidToken: idToken as ArmorIdToken,\n\t\t// Generally, IdP's require an audience to get a JWT\n\t\t// access token. Most cases, this doesn't matter.\n\t\taccessToken: accessToken ?? exchange.access_token,\n\t\texpiresAt: createExpiresAt(exchange.expires_in),\n\t};\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\nimport { throwIfUndefined } from \"@nekm/core\";\n\nfunction jwtIsCompactJwt(token: string): boolean {\n\t// Must be three base64url segments\n\tconst parts = token.trim().split(\".\");\n\treturn parts.length === 3 && parts.every((p) => p.length > 0);\n}\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\tconst payload = jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n\tthrowIfUndefined(payload);\n\t// @ts-expect-error We're already verifying non-null above.\n\treturn payload;\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload | undefined> {\n\tconst opts: JWTVerifyOptions = { issuer: config.oauth.issuer };\n\n\tif (config.oauth.audience) {\n\t\topts.audience = config.oauth.audience;\n\t}\n\n\treturn jwtVerifyToken(jwks, opts, accessToken);\n}\n\nfunction isInvalidCompactJwt(error: unknown): boolean {\n\treturn Boolean(\n\t\ttypeof error === \"object\" &&\n\t\terror &&\n\t\t\"message\" in error &&\n\t\ttypeof error.message === \"string\" &&\n\t\t/invalid compact jws/gi.test(error.message),\n\t);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload | undefined> {\n\ttry {\n\t\tif (!jwtIsCompactJwt(token)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst { payload } = await jwtVerify(token, jwks, opts);\n\t\treturn payload;\n\t} catch (error) {\n\t\tif (isInvalidCompactJwt(error)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\" as const;\nexport const COOKIE_STATE = \"state\" as const;\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\nexport class ArmorRefreshError extends ArmorError {}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport { COOKIE_STATE, cookieGetAndDelete } from \"./cookie\";\nimport { ArmorInvalidStateError } from \"../errors\";\n\nexport function eventStateValidOrThrow(event: RequestEvent): void {\n\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\tif (state !== stateCookie) {\n\t\tthrow new ArmorInvalidStateError();\n\t}\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { queryParamsCreate, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange, exchangeToTokens } from \"../utils/utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"../utils/jwt\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\n\nexport const ROUTE_PATH_REDIRECT_LOGIN = \"/_armor/redirect/login\";\n\nexport const routeRedirectLoginFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst tokenUrl =\n\t\tconfig.oauth.tokenEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst params: Record<string, string> = {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\tcode,\n\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\tscope,\n\t\t};\n\n\t\tif (config.oauth.audience) {\n\t\t\tparams.audience = config.oauth.audience;\n\t\t}\n\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams(params).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle login redirect callback.\");\n\n\t\t\teventStateValidOrThrow(event);\n\n\t\t\tconst error = event.url.searchParams.get(\"error\") ?? undefined;\n\n\t\t\tif (error) {\n\t\t\t\tconst error_description =\n\t\t\t\t\tevent.url.searchParams.get(\"error_description\") ?? undefined;\n\n\t\t\t\tconfig.logger?.error?.(\"Login returned error.\", {\n\t\t\t\t\terror,\n\t\t\t\t\terrorDescription: error_description,\n\t\t\t\t});\n\n\t\t\t\tif (!config.oauth.errorLoginRedirectPath) {\n\t\t\t\t\treturn new Response(`${error}\\n${error_description}`.trimEnd(), {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"text/plain\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst errorParams = queryParamsCreate({ error, error_description });\n\t\t\t\tthrow redirect(\n\t\t\t\t\t302,\n\t\t\t\t\t`${config.oauth.errorLoginRedirectPath}?${errorParams}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst code = event.url.searchParams.get(\"code\") ?? undefined;\n\t\t\tconfig.logger?.debug?.(\"Get code from query params.\", { code });\n\t\t\tthrowIfUndefined(code);\n\n\t\t\tconst exchange = await exchangeCodeForToken(\n\t\t\t\tevent.fetch,\n\t\t\t\tevent.url.origin,\n\t\t\t\tcode,\n\t\t\t);\n\n\t\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { exchange });\n\n\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\tjwtVerifyIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\t\tidToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tawait config.session.login(\n\t\t\t\tevent,\n\t\t\t\texchangeToTokens(exchange, idToken as ArmorIdToken, accessToken),\n\t\t\t);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","export const ARMOR_LOGIN = \"/_armor/login\" as const;\nexport const ARMOR_LOGOUT = \"/_armor/logout\" as const;\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGIN } from \"../browser\";\n\nexport const ROUTE_PATH_LOGIN = ARMOR_LOGIN;\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = {\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t\tscope,\n\t\t\t\taudience: config.oauth.audience,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre login redirect.\", { params, state });\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle logout redirect callback.\");\n\n\t\t\tawait config.session.logout(event);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGOUT } from \"./redirect-logout\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGOUT } from \"../browser\";\n\nexport const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst returnTo = config.oauth.logoutReturnToParam ?? \"logout_uri\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = {\n\t\t\t\t[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre logout redirect.\", { params });\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import type { Handle } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { routeLoginFactory } from \"./login\";\nimport { routeLogoutFactory } from \"./logout\";\nimport { routeRedirectLogoutFactory } from \"./redirect-logout\";\nimport { routeRedirectLoginFactory } from \"./redirect-login\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n]);\n\nexport function routeByPathFactory(config: ArmorConfig): Map<string, Route> {\n\t// @ts-expect-error Incorrect typing error.\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route]),\n\t);\n}\n","import { createRemoteJWKSet } from \"jose\";\nimport {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\nimport { ArmorRefreshError } from \"../errors\";\nimport { exchangeToTokens, shouldRefresh, urlConcat } from \"./utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"./jwt\";\nimport { redirect, RequestEvent } from \"@sveltejs/kit\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ROUTE_PATH_LOGIN } from \"../routes/login\";\n\nexport function armorRefreshFactory(config: ArmorConfig) {\n\tconst refreshEndpoint =\n\t\tconfig.oauth.refreshEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst refresh = async (\n\t\tfetch: typeof global.fetch,\n\t\trefreshToken: string,\n\t): Promise<ArmorTokenExchange> => {\n\t\tconst body = new URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\trefresh_token: refreshToken,\n\t\t});\n\n\t\tif (config.oauth.scope) {\n\t\t\tbody.set(\"scope\", config.oauth.scope);\n\t\t}\n\n\t\tconst response = await fetch(refreshEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: body.toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new ArmorRefreshError(`Could not refresh token: ${error}`);\n\t\t}\n\n\t\tconst json: ArmorTokenExchange = await response.json();\n\n\t\treturn {\n\t\t\t...json,\n\t\t\trefresh_token: json.refresh_token ?? refreshToken,\n\t\t};\n\t};\n\n\treturn {\n\t\trefresh,\n\t\tasync ensureValidToken<T>(\n\t\t\tevent: RequestEvent,\n\t\t\ttokens: ArmorTokens,\n\t\t\tfn: (tokens: ArmorTokens) => T | Promise<T>,\n\t\t): Promise<T> {\n\t\t\ttry {\n\t\t\t\tlet validTokens = tokens;\n\n\t\t\t\tif (shouldRefresh(tokens)) {\n\t\t\t\t\tconfig.logger?.debug?.(\"Tokens has expired. Refreshing...\");\n\n\t\t\t\t\tif (!tokens.exchange.refresh_token) {\n\t\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst newExchange = await refresh(\n\t\t\t\t\t\tfetch,\n\t\t\t\t\t\ttokens.exchange.refresh_token,\n\t\t\t\t\t);\n\n\t\t\t\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { newExchange });\n\n\t\t\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\t\t\tjwtVerifyIdToken(config, jwks, newExchange.id_token),\n\t\t\t\t\t\tjwtVerifyAccessToken(config, jwks, newExchange.access_token),\n\t\t\t\t\t]);\n\n\t\t\t\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\t\t\t\tidToken,\n\t\t\t\t\t\taccessToken,\n\t\t\t\t\t});\n\n\t\t\t\t\tvalidTokens = exchangeToTokens(\n\t\t\t\t\t\tnewExchange,\n\t\t\t\t\t\tidToken as ArmorIdToken,\n\t\t\t\t\t\taccessToken,\n\t\t\t\t\t);\n\n\t\t\t\t\tawait config.session.login(event, validTokens);\n\t\t\t\t}\n\n\t\t\t\treturn fn(validTokens);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof ArmorRefreshError) {\n\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport {\n\tCOOKIE_TOKENS,\n\tcookieDelete,\n\tcookieGet,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport { ArmorConfig, ArmorTokens } from \"../contracts\";\nimport { ArmorAuthMissingError } from \"../errors\";\n\nfunction cookieSessionGetTokens({\n\tcookies,\n}: RequestEvent): ArmorTokens | undefined {\n\treturn cookies.get(COOKIE_TOKENS) as ArmorTokens | undefined;\n}\n\nexport function cookieSessionLogin(\n\t{ cookies }: RequestEvent,\n\ttokens: ArmorTokens,\n): void {\n\tcookieSet(cookies, COOKIE_TOKENS, tokens);\n}\n\nfunction cookieSessionLogout({ cookies }: RequestEvent): void {\n\tcookieDelete(cookies, COOKIE_TOKENS);\n}\n\nexport function armorCookieSessionGet({ cookies }: RequestEvent): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\n\tif (!tokens) {\n\t\tthrow new ArmorAuthMissingError();\n\t}\n\n\treturn tokens;\n}\n\nexport const armorCookieSession: ArmorConfig[\"session\"] = {\n\tgetTokens: cookieSessionGetTokens,\n\tlogin: cookieSessionLogin,\n\tlogout: cookieSessionLogout,\n};\n","import { redirect, type Handle } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { routeByPathFactory } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\nimport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\nexport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routeByPath = routeByPathFactory(config);\n\tconst refresh = armorRefreshFactory(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst route = routeByPath.get(event.url.pathname);\n\n\t\tif (route) {\n\t\t\treturn route.handle({ event, resolve });\n\t\t}\n\n\t\tconst tokens = await config.session.getTokens(event);\n\n\t\tif (!tokens) {\n\t\t\tconfig.logger?.warning?.(\"Could not find tokens. Redirecting to login.\");\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn refresh.ensureValidToken(event, tokens, () => resolve(event));\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.\n * Use that to create your config.\n * @param config\n * @param fetch\n */\nexport async function armorConfigFromOpenId(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n): Promise<ArmorConfig> {\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(config.oauth.openIdConfigEndpoint, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn {\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksEndpoint: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t\trefreshEndpoint: body.token_endpoint,\n\t\t},\n\t};\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","MINUTES_MS","shouldRefresh","tokens","idExpiry","idToken","exp","accessExpiry","accessToken","Infinity","Math","min","Date","now","createExpiresAt","seconds","setSeconds","getSeconds","exchangeToTokens","exchange","expiresAt","jwtIsCompactJwt","token","parts","trim","split","length","every","p","jwtVerifyIdToken","config","jwks","payload","jwtVerifyToken","issuer","oauth","audience","clientId","throwIfUndefined","jwtVerifyAccessToken","opts","isInvalidCompactJwt","error","Boolean","message","test","jwtVerify","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","cookieDelete","ArmorError","Error","ArmorOpenIdConfigError","ArmorInvalidStateError","ArmorAuthMissingError","ArmorRefreshError","eventStateValidOrThrow","event","_event$url$searchPara","state","url","searchParams","stateCookie","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksEnd","_config$oauth$tokenEn","_config$oauth$scope","jwksUrl","URL","jwksEndpoint","baseUrl","tokenUrl","tokenEndpoint","exchangeCodeForToken","fetch","code","params","grant_type","client_id","client_secret","clientSecret","redirect_uri","response","method","headers","Accept","body","URLSearchParams","toString","ok","text","json","handle","_config$logger","_event$url$searchPara3","_config$logger3","_config$logger4","_config$logger5","logger","debug","_event$url$searchPara2","_config$logger2","error_description","errorDescription","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","createRemoteJWKSet","Promise","all","session","login","ARMOR_LOGIN","ARMOR_LOGOUT","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","paramsStr","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","routeFactories","routeByPathFactory","Map","map","routeFactory","filter","route","armorRefreshFactory","_config$oauth$refresh","refreshEndpoint","refresh","refreshToken","_json$refresh_token","ensureValidToken","fn","validTokens","newExchange","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","getTokens","armor","routeByPath","resolve","pathname","warning","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/utils/utils.ts","../src/utils/jwt.ts","../src/utils/cookie.ts","../src/errors.ts","../src/utils/event.ts","../src/routes/redirect-login.ts","../src/browser/index.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/utils/refresh.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type {\n\tArmorAccessToken,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n\nconst MINUTES_MS = 60 * 1000;\n\nexport function shouldRefresh(\n\ttokens: Pick<ArmorTokens, \"idToken\" | \"accessToken\">,\n): boolean {\n\tconst idExpiry = tokens.idToken.exp * 1000;\n\n\tconst accessExpiry =\n\t\ttypeof tokens.accessToken !== \"string\" &&\n\t\ttokens.accessToken.exp !== undefined\n\t\t\t? tokens.accessToken.exp * 1000\n\t\t\t: Infinity;\n\n\treturn Math.min(idExpiry, accessExpiry) < Date.now() + 5 * MINUTES_MS;\n}\n\nexport function createExpiresAt(seconds: number): Date {\n\tconst now = new Date();\n\tnow.setSeconds(now.getSeconds() + seconds);\n\treturn now;\n}\n\nexport function exchangeToTokens(\n\texchange: ArmorTokenExchange,\n\tidToken: ArmorIdToken,\n\taccessToken?: ArmorAccessToken,\n): ArmorTokens {\n\treturn {\n\t\texchange,\n\t\tidToken: idToken as ArmorIdToken,\n\t\t// Generally, IdP's require an audience to get a JWT\n\t\t// access token. Most cases, this doesn't matter.\n\t\taccessToken: accessToken ?? exchange.access_token,\n\t\texpiresAt: createExpiresAt(exchange.expires_in),\n\t};\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\nimport { throwIfUndefined } from \"@nekm/core\";\n\nfunction jwtIsCompactJwt(token: string): boolean {\n\t// Must be three base64url segments\n\tconst parts = token.trim().split(\".\");\n\treturn parts.length === 3 && parts.every((p) => p.length > 0);\n}\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\tconst payload = jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n\tthrowIfUndefined(payload);\n\t// @ts-expect-error We're already verifying non-null above.\n\treturn payload;\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload | undefined> {\n\tconst opts: JWTVerifyOptions = { issuer: config.oauth.issuer };\n\n\tif (config.oauth.audience) {\n\t\topts.audience = config.oauth.audience;\n\t}\n\n\treturn jwtVerifyToken(jwks, opts, accessToken);\n}\n\nfunction isInvalidCompactJwt(error: unknown): boolean {\n\treturn Boolean(\n\t\ttypeof error === \"object\" &&\n\t\terror &&\n\t\t\"message\" in error &&\n\t\ttypeof error.message === \"string\" &&\n\t\t/invalid compact jws/gi.test(error.message),\n\t);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload | undefined> {\n\ttry {\n\t\tif (!jwtIsCompactJwt(token)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst { payload } = await jwtVerify(token, jwks, opts);\n\t\treturn payload;\n\t} catch (error) {\n\t\tif (isInvalidCompactJwt(error)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\" as const;\nexport const COOKIE_STATE = \"state\" as const;\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\nexport class ArmorRefreshError extends ArmorError {}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport { COOKIE_STATE, cookieGetAndDelete } from \"./cookie\";\nimport { ArmorInvalidStateError } from \"../errors\";\n\nexport function eventStateValidOrThrow(event: RequestEvent): void {\n\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\tif (state !== stateCookie) {\n\t\tthrow new ArmorInvalidStateError();\n\t}\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { queryParamsCreate, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange, exchangeToTokens } from \"../utils/utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"../utils/jwt\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\n\nexport const ROUTE_PATH_REDIRECT_LOGIN = \"/_armor/redirect/login\";\n\nexport const routeRedirectLoginFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst tokenUrl =\n\t\tconfig.oauth.tokenEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst params: Record<string, string> = {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\tcode,\n\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\tscope,\n\t\t};\n\n\t\tif (config.oauth.audience) {\n\t\t\tparams.audience = config.oauth.audience;\n\t\t}\n\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams(params).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle login redirect callback.\");\n\n\t\t\teventStateValidOrThrow(event);\n\n\t\t\tconst error = event.url.searchParams.get(\"error\") ?? undefined;\n\n\t\t\tif (error) {\n\t\t\t\tconst error_description =\n\t\t\t\t\tevent.url.searchParams.get(\"error_description\") ?? undefined;\n\n\t\t\t\tconfig.logger?.error?.(\"Login returned error.\", {\n\t\t\t\t\terror,\n\t\t\t\t\terrorDescription: error_description,\n\t\t\t\t});\n\n\t\t\t\tif (!config.oauth.errorLoginRedirectPath) {\n\t\t\t\t\treturn new Response(`${error}\\n${error_description}`.trimEnd(), {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"text/plain\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst errorParams = queryParamsCreate({ error, error_description });\n\t\t\t\tthrow redirect(\n\t\t\t\t\t302,\n\t\t\t\t\t`${config.oauth.errorLoginRedirectPath}?${errorParams}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst code = event.url.searchParams.get(\"code\") ?? undefined;\n\t\t\tconfig.logger?.debug?.(\"Get code from query params.\", { code });\n\t\t\tthrowIfUndefined(code);\n\n\t\t\tconst exchange = await exchangeCodeForToken(\n\t\t\t\tevent.fetch,\n\t\t\t\tevent.url.origin,\n\t\t\t\tcode,\n\t\t\t);\n\n\t\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { exchange });\n\n\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\tjwtVerifyIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\t\tidToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tawait config.session.login(\n\t\t\t\tevent,\n\t\t\t\texchangeToTokens(exchange, idToken as ArmorIdToken, accessToken),\n\t\t\t);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","export const ARMOR_LOGIN = \"/_armor/login\" as const;\nexport const ARMOR_LOGOUT = \"/_armor/logout\" as const;\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGIN } from \"../browser\";\n\nexport const ROUTE_PATH_LOGIN = ARMOR_LOGIN;\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = {\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t\tscope,\n\t\t\t\taudience: config.oauth.audience,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre login redirect.\", { params, state });\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle logout redirect callback.\");\n\n\t\t\tawait config.session.logout(event);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGOUT } from \"./redirect-logout\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGOUT } from \"../browser\";\n\nexport const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst returnTo = config.oauth.logoutReturnToParam ?? \"logout_uri\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = {\n\t\t\t\t[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre logout redirect.\", { params });\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import type { Handle } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { routeLoginFactory } from \"./login\";\nimport { routeLogoutFactory } from \"./logout\";\nimport { routeRedirectLogoutFactory } from \"./redirect-logout\";\nimport { routeRedirectLoginFactory } from \"./redirect-login\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n]);\n\nexport function routeByPathFactory(config: ArmorConfig): Map<string, Route> {\n\t// @ts-expect-error Incorrect typing error.\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route]),\n\t);\n}\n","import { createRemoteJWKSet } from \"jose\";\nimport {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\nimport { ArmorRefreshError } from \"../errors\";\nimport { exchangeToTokens, shouldRefresh, urlConcat } from \"./utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"./jwt\";\nimport { redirect, RequestEvent } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"../routes/login\";\n\nexport interface ArmorRefresh {\n\treadonly refresh: (\n\t\tfetch: typeof global.fetch,\n\t\trefreshToken: string,\n\t) => Promise<ArmorTokens>;\n\treadonly ensureValidToken: <T>(\n\t\tevent: RequestEvent,\n\t\ttokens: ArmorTokens,\n\t\tfn: (tokens: ArmorTokens) => T | Promise<T>,\n\t) => Promise<T>;\n}\n\nexport function armorRefreshFactory(config: ArmorConfig): ArmorRefresh {\n\tconst refreshEndpoint =\n\t\tconfig.oauth.refreshEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst refresh = async (\n\t\tfetch: typeof global.fetch,\n\t\trefreshToken: string,\n\t): Promise<ArmorTokens> => {\n\t\tconst body = new URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\trefresh_token: refreshToken,\n\t\t});\n\n\t\tif (config.oauth.scope) {\n\t\t\tbody.set(\"scope\", config.oauth.scope);\n\t\t}\n\n\t\tconst response = await fetch(refreshEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: body.toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new ArmorRefreshError(`Could not refresh token: ${error}`);\n\t\t}\n\n\t\tconst json: ArmorTokenExchange = await response.json();\n\n\t\tconst newExchange = {\n\t\t\t...json,\n\t\t\trefresh_token: json.refresh_token ?? refreshToken,\n\t\t};\n\n\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { newExchange });\n\n\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\tjwtVerifyIdToken(config, jwks, newExchange.id_token),\n\t\t\tjwtVerifyAccessToken(config, jwks, newExchange.access_token),\n\t\t]);\n\n\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\tidToken,\n\t\t\taccessToken,\n\t\t});\n\n\t\tconst validTokens = exchangeToTokens(\n\t\t\tnewExchange,\n\t\t\tidToken as ArmorIdToken,\n\t\t\taccessToken,\n\t\t);\n\n\t\treturn validTokens;\n\t};\n\n\treturn {\n\t\trefresh,\n\t\tasync ensureValidToken<T>(\n\t\t\tevent: RequestEvent,\n\t\t\ttokens: ArmorTokens,\n\t\t\tfn: (tokens: ArmorTokens) => T | Promise<T>,\n\t\t): Promise<T> {\n\t\t\ttry {\n\t\t\t\tlet validTokens = tokens;\n\n\t\t\t\tif (shouldRefresh(tokens)) {\n\t\t\t\t\tconfig.logger?.debug?.(\"Tokens has expired. Refreshing...\");\n\n\t\t\t\t\tif (!tokens.exchange.refresh_token) {\n\t\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t\t}\n\n\t\t\t\t\tvalidTokens = await refresh(fetch, tokens.exchange.refresh_token);\n\n\t\t\t\t\tawait config.session.login(event, validTokens);\n\t\t\t\t}\n\n\t\t\t\treturn fn(validTokens);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof ArmorRefreshError) {\n\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport {\n\tCOOKIE_TOKENS,\n\tcookieDelete,\n\tcookieGet,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport { ArmorConfig, ArmorTokens } from \"../contracts\";\nimport { ArmorAuthMissingError } from \"../errors\";\n\nfunction cookieSessionGetTokens({\n\tcookies,\n}: RequestEvent): ArmorTokens | undefined {\n\treturn cookies.get(COOKIE_TOKENS) as ArmorTokens | undefined;\n}\n\nexport function cookieSessionLogin(\n\t{ cookies }: RequestEvent,\n\ttokens: ArmorTokens,\n): void {\n\tcookieSet(cookies, COOKIE_TOKENS, tokens);\n}\n\nfunction cookieSessionLogout({ cookies }: RequestEvent): void {\n\tcookieDelete(cookies, COOKIE_TOKENS);\n}\n\nexport function armorCookieSessionGet({ cookies }: RequestEvent): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\n\tif (!tokens) {\n\t\tthrow new ArmorAuthMissingError();\n\t}\n\n\treturn tokens;\n}\n\nexport const armorCookieSession: ArmorConfig[\"session\"] = {\n\tgetTokens: cookieSessionGetTokens,\n\tlogin: cookieSessionLogin,\n\tlogout: cookieSessionLogout,\n};\n","import { redirect, type Handle } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { routeByPathFactory } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\nimport { ArmorRefresh, armorRefreshFactory } from \"./utils/refresh\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\nexport { armorRefreshFactory } from \"./utils/refresh\";\n\ninterface Armor extends ArmorRefresh {\n\treadonly handle: Handle;\n}\n\nexport function armor(config: ArmorConfig): Armor {\n\tconst routeByPath = routeByPathFactory(config);\n\tconst refresh = armorRefreshFactory(config);\n\n\treturn {\n\t\t...refresh,\n\t\tasync handle({ event, resolve }) {\n\t\t\tconst route = routeByPath.get(event.url.pathname);\n\n\t\t\tif (route) {\n\t\t\t\treturn route.handle({ event, resolve });\n\t\t\t}\n\n\t\t\tconst tokens = await config.session.getTokens(event);\n\n\t\t\tif (!tokens) {\n\t\t\t\tconfig.logger?.warning?.(\n\t\t\t\t\t\"Could not find tokens. Redirecting to login.\",\n\t\t\t\t);\n\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t}\n\n\t\t\treturn refresh.ensureValidToken(event, tokens, () => resolve(event));\n\t\t},\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.\n * Use that to create your config.\n * @param config\n * @param fetch\n */\nexport async function armorConfigFromOpenId(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n): Promise<ArmorConfig> {\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(config.oauth.openIdConfigEndpoint, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn {\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksEndpoint: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t\trefreshEndpoint: body.token_endpoint,\n\t\t},\n\t};\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","MINUTES_MS","shouldRefresh","tokens","idExpiry","idToken","exp","accessExpiry","accessToken","Infinity","Math","min","Date","now","createExpiresAt","seconds","setSeconds","getSeconds","exchangeToTokens","exchange","expiresAt","jwtIsCompactJwt","token","parts","trim","split","length","every","p","jwtVerifyIdToken","config","jwks","payload","jwtVerifyToken","issuer","oauth","audience","clientId","throwIfUndefined","jwtVerifyAccessToken","opts","isInvalidCompactJwt","error","Boolean","message","test","jwtVerify","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","cookieDelete","ArmorError","Error","ArmorOpenIdConfigError","ArmorInvalidStateError","ArmorAuthMissingError","ArmorRefreshError","eventStateValidOrThrow","event","_event$url$searchPara","state","url","searchParams","stateCookie","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksEnd","_config$oauth$tokenEn","_config$oauth$scope","jwksUrl","URL","jwksEndpoint","baseUrl","tokenUrl","tokenEndpoint","exchangeCodeForToken","fetch","code","params","grant_type","client_id","client_secret","clientSecret","redirect_uri","response","method","headers","Accept","body","URLSearchParams","toString","ok","text","json","handle","_config$logger","_event$url$searchPara3","_config$logger3","_config$logger4","_config$logger5","logger","debug","_event$url$searchPara2","_config$logger2","error_description","errorDescription","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","createRemoteJWKSet","Promise","all","session","login","ARMOR_LOGIN","ARMOR_LOGOUT","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","paramsStr","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","routeFactories","routeByPathFactory","Map","map","routeFactory","filter","route","armorRefreshFactory","_config$oauth$refresh","refreshEndpoint","refresh","refreshToken","_json$refresh_token","newExchange","validTokens","ensureValidToken","fn","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","getTokens","armor","routeByPath","resolve","pathname","warning","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
- import { ArmorConfig, ArmorTokenExchange, ArmorTokens } from "../contracts";
1
+ import { ArmorConfig, ArmorTokens } from "../contracts";
2
2
  import { RequestEvent } from "@sveltejs/kit";
3
- export declare function armorRefreshFactory(config: ArmorConfig): {
4
- refresh: (fetch: typeof global.fetch, refreshToken: string) => Promise<ArmorTokenExchange>;
5
- ensureValidToken<T>(event: RequestEvent, tokens: ArmorTokens, fn: (tokens: ArmorTokens) => T | Promise<T>): Promise<T>;
6
- };
3
+ export interface ArmorRefresh {
4
+ readonly refresh: (fetch: typeof global.fetch, refreshToken: string) => Promise<ArmorTokens>;
5
+ readonly ensureValidToken: <T>(event: RequestEvent, tokens: ArmorTokens, fn: (tokens: ArmorTokens) => T | Promise<T>) => Promise<T>;
6
+ }
7
+ export declare function armorRefreshFactory(config: ArmorConfig): ArmorRefresh;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nekm/sveltekit-armor",
3
- "version": "0.3.11",
3
+ "version": "0.4.1",
4
4
  "description": "Zero-config OAuth protection for SvelteKit",
5
5
  "license": "MIT",
6
6
  "source": "./src/index.ts",
@@ -68,19 +68,19 @@
68
68
  "sideEffects": false,
69
69
  "devDependencies": {
70
70
  "@eslint/js": "^10.0.1",
71
- "@sveltejs/kit": "^2.53.2",
71
+ "@sveltejs/kit": "^2.55.0",
72
72
  "@tsconfig/recommended": "^1.0.13",
73
73
  "@types/node": "^24",
74
- "@typescript-eslint/eslint-plugin": "^8.56.1",
75
- "@typescript-eslint/parser": "^8.56.1",
74
+ "@typescript-eslint/eslint-plugin": "^8.57.1",
75
+ "@typescript-eslint/parser": "^8.57.1",
76
76
  "eslint": "^10",
77
- "globals": "^17.3.0",
77
+ "globals": "^17.4.0",
78
78
  "microbundle": "^0.15.1",
79
79
  "prettier": "^3.8.1",
80
80
  "ts-jest": "^29.4.6",
81
81
  "ts-node": "^10.9.2",
82
82
  "typescript": "^5.9.3",
83
- "vitest": "^4.0.18"
83
+ "vitest": "^4.1.0"
84
84
  },
85
85
  "dependencies": {
86
86
  "@nekm/core": "^1",
package/src/index.ts CHANGED
@@ -3,31 +3,40 @@ import { ROUTE_PATH_LOGIN } from "./routes/login";
3
3
  import type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from "./contracts";
4
4
  import { routeByPathFactory } from "./routes/routes";
5
5
  import { ArmorOpenIdConfigError } from "./errors";
6
- import { armorRefreshFactory } from "./utils/refresh";
6
+ import { ArmorRefresh, armorRefreshFactory } from "./utils/refresh";
7
7
 
8
8
  export type { ArmorConfig, ArmorTokens };
9
9
  export { armorCookieSession, armorCookieSessionGet } from "./session/cookie";
10
10
  export { armorRefreshFactory } from "./utils/refresh";
11
11
 
12
- export function armor(config: ArmorConfig): Handle {
12
+ interface Armor extends ArmorRefresh {
13
+ readonly handle: Handle;
14
+ }
15
+
16
+ export function armor(config: ArmorConfig): Armor {
13
17
  const routeByPath = routeByPathFactory(config);
14
18
  const refresh = armorRefreshFactory(config);
15
19
 
16
- return async ({ event, resolve }) => {
17
- const route = routeByPath.get(event.url.pathname);
20
+ return {
21
+ ...refresh,
22
+ async handle({ event, resolve }) {
23
+ const route = routeByPath.get(event.url.pathname);
18
24
 
19
- if (route) {
20
- return route.handle({ event, resolve });
21
- }
25
+ if (route) {
26
+ return route.handle({ event, resolve });
27
+ }
22
28
 
23
- const tokens = await config.session.getTokens(event);
29
+ const tokens = await config.session.getTokens(event);
24
30
 
25
- if (!tokens) {
26
- config.logger?.warning?.("Could not find tokens. Redirecting to login.");
27
- throw redirect(302, ROUTE_PATH_LOGIN);
28
- }
31
+ if (!tokens) {
32
+ config.logger?.warning?.(
33
+ "Could not find tokens. Redirecting to login.",
34
+ );
35
+ throw redirect(302, ROUTE_PATH_LOGIN);
36
+ }
29
37
 
30
- return refresh.ensureValidToken(event, tokens, () => resolve(event));
38
+ return refresh.ensureValidToken(event, tokens, () => resolve(event));
39
+ },
31
40
  };
32
41
  }
33
42
 
@@ -9,10 +9,21 @@ import { ArmorRefreshError } from "../errors";
9
9
  import { exchangeToTokens, shouldRefresh, urlConcat } from "./utils";
10
10
  import { jwtVerifyAccessToken, jwtVerifyIdToken } from "./jwt";
11
11
  import { redirect, RequestEvent } from "@sveltejs/kit";
12
- import { throwIfUndefined } from "@nekm/core";
13
12
  import { ROUTE_PATH_LOGIN } from "../routes/login";
14
13
 
15
- export function armorRefreshFactory(config: ArmorConfig) {
14
+ export interface ArmorRefresh {
15
+ readonly refresh: (
16
+ fetch: typeof global.fetch,
17
+ refreshToken: string,
18
+ ) => Promise<ArmorTokens>;
19
+ readonly ensureValidToken: <T>(
20
+ event: RequestEvent,
21
+ tokens: ArmorTokens,
22
+ fn: (tokens: ArmorTokens) => T | Promise<T>,
23
+ ) => Promise<T>;
24
+ }
25
+
26
+ export function armorRefreshFactory(config: ArmorConfig): ArmorRefresh {
16
27
  const refreshEndpoint =
17
28
  config.oauth.refreshEndpoint ??
18
29
  urlConcat(config.oauth.baseUrl, "oauth2/token");
@@ -25,7 +36,7 @@ export function armorRefreshFactory(config: ArmorConfig) {
25
36
  const refresh = async (
26
37
  fetch: typeof global.fetch,
27
38
  refreshToken: string,
28
- ): Promise<ArmorTokenExchange> => {
39
+ ): Promise<ArmorTokens> => {
29
40
  const body = new URLSearchParams({
30
41
  grant_type: "refresh_token",
31
42
  client_id: config.oauth.clientId,
@@ -53,10 +64,32 @@ export function armorRefreshFactory(config: ArmorConfig) {
53
64
 
54
65
  const json: ArmorTokenExchange = await response.json();
55
66
 
56
- return {
67
+ const newExchange = {
57
68
  ...json,
58
69
  refresh_token: json.refresh_token ?? refreshToken,
59
70
  };
71
+
72
+ config.logger?.debug?.("Exchange code for tokens.", { newExchange });
73
+
74
+ const jwks = createRemoteJWKSet(jwksUrl);
75
+
76
+ const [idToken, accessToken] = await Promise.all([
77
+ jwtVerifyIdToken(config, jwks, newExchange.id_token),
78
+ jwtVerifyAccessToken(config, jwks, newExchange.access_token),
79
+ ]);
80
+
81
+ config.logger?.debug?.("Extract and verify tokens.", {
82
+ idToken,
83
+ accessToken,
84
+ });
85
+
86
+ const validTokens = exchangeToTokens(
87
+ newExchange,
88
+ idToken as ArmorIdToken,
89
+ accessToken,
90
+ );
91
+
92
+ return validTokens;
60
93
  };
61
94
 
62
95
  return {
@@ -76,30 +109,7 @@ export function armorRefreshFactory(config: ArmorConfig) {
76
109
  throw redirect(302, ROUTE_PATH_LOGIN);
77
110
  }
78
111
 
79
- const newExchange = await refresh(
80
- fetch,
81
- tokens.exchange.refresh_token,
82
- );
83
-
84
- config.logger?.debug?.("Exchange code for tokens.", { newExchange });
85
-
86
- const jwks = createRemoteJWKSet(jwksUrl);
87
-
88
- const [idToken, accessToken] = await Promise.all([
89
- jwtVerifyIdToken(config, jwks, newExchange.id_token),
90
- jwtVerifyAccessToken(config, jwks, newExchange.access_token),
91
- ]);
92
-
93
- config.logger?.debug?.("Extract and verify tokens.", {
94
- idToken,
95
- accessToken,
96
- });
97
-
98
- validTokens = exchangeToTokens(
99
- newExchange,
100
- idToken as ArmorIdToken,
101
- accessToken,
102
- );
112
+ validTokens = await refresh(fetch, tokens.exchange.refresh_token);
103
113
 
104
114
  await config.session.login(event, validTokens);
105
115
  }