@nekm/sveltekit-armor 0.3.7 → 0.3.8

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.
@@ -1,7 +1,2 @@
1
- import { ArmorTokens } from "../contracts";
2
- export declare const ARMOR_REFRESH = "/_armor/refresh";
3
- export declare const ARMOR_LOGIN = "/_armor/login";
4
- type ArmorBrowserTokens = Pick<ArmorTokens, "idToken" | "accessToken">;
5
- export declare function armorBrowserRefresh(): Promise<ArmorBrowserTokens>;
6
- export declare function armorBrowserEnsureValidTokens<T>(tokens: ArmorBrowserTokens, fn: (tokens: ArmorBrowserTokens) => T | Promise<T>): Promise<T>;
7
- export {};
1
+ export declare const ARMOR_LOGIN: "/_armor/login";
2
+ export declare const ARMOR_LOGOUT: "/_armor/logout";
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { type Handle } from "@sveltejs/kit";
2
2
  import type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from "./contracts";
3
3
  export type { ArmorConfig, ArmorTokens };
4
4
  export { armorCookieSession, armorCookieSessionGet } from "./session/cookie";
5
- export { armorCreateRefresh } from "./utils/refresh";
5
+ export { armorRefreshFactory } from "./utils/refresh";
6
6
  export declare function armor(config: ArmorConfig): Handle;
7
7
  /**
8
8
  * Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { redirect, error, json } from '@sveltejs/kit';
1
+ import { redirect } from '@sveltejs/kit';
2
2
  import { strTrimEnd, strTrimStart, throwIfUndefined, queryParamsCreate } from '@nekm/core';
3
3
  import { jwtVerify, createRemoteJWKSet } from 'jose';
4
4
  import { randomUUID } from 'node:crypto';
@@ -161,7 +161,6 @@ const routeRedirectLoginFactory = config => {
161
161
  }
162
162
  return {
163
163
  path: ROUTE_PATH_REDIRECT_LOGIN,
164
- method: "GET",
165
164
  async handle({
166
165
  event
167
166
  }) {
@@ -195,8 +194,8 @@ const routeRedirectLoginFactory = config => {
195
194
  };
196
195
  };
197
196
 
198
- const ARMOR_REFRESH = "/_armor/refresh";
199
197
  const ARMOR_LOGIN = "/_armor/login";
198
+ const ARMOR_LOGOUT = "/_armor/logout";
200
199
 
201
200
  const ROUTE_PATH_LOGIN = ARMOR_LOGIN;
202
201
  const routeLoginFactory = config => {
@@ -205,7 +204,6 @@ const routeLoginFactory = config => {
205
204
  const scope = (_config$oauth$scope = config.oauth.scope) != null ? _config$oauth$scope : "openid profile email";
206
205
  return {
207
206
  path: ROUTE_PATH_LOGIN,
208
- method: "GET",
209
207
  async handle({
210
208
  event
211
209
  }) {
@@ -232,7 +230,6 @@ const routeRedirectLogoutFactory = config => {
232
230
  }
233
231
  return {
234
232
  path: ROUTE_PATH_REDIRECT_LOGOUT,
235
- method: "GET",
236
233
  async handle({
237
234
  event
238
235
  }) {
@@ -243,7 +240,7 @@ const routeRedirectLogoutFactory = config => {
243
240
  };
244
241
  };
245
242
 
246
- const ROUTE_PATH_LOGOUT = "/_armor/logout";
243
+ const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;
247
244
  const routeLogoutFactory = config => {
248
245
  var _config$oauth$logoutR;
249
246
  // Check if the oauth provider supports a logout path.
@@ -269,7 +266,15 @@ const routeLogoutFactory = config => {
269
266
  };
270
267
  };
271
268
 
272
- function armorCreateRefresh(config) {
269
+ const routeFactories = Object.freeze([routeLoginFactory, routeLogoutFactory, routeRedirectLoginFactory, routeRedirectLogoutFactory]);
270
+ function routeByPathFactory(config) {
271
+ // @ts-expect-error Incorrect typing error.
272
+ return new Map(routeFactories.map(routeFactory => routeFactory(config)).filter(route => Boolean(route))
273
+ // @ts-expect-error Incorrect typing error.
274
+ .map(route => [route.path, route]));
275
+ }
276
+
277
+ function armorRefreshFactory(config) {
273
278
  var _config$oauth$refresh, _config$oauth$jwksEnd;
274
279
  const refreshEndpoint = (_config$oauth$refresh = config.oauth.refreshEndpoint) != null ? _config$oauth$refresh : urlConcat(config.oauth.baseUrl, "oauth2/token");
275
280
  const jwksUrl = new URL((_config$oauth$jwksEnd = config.oauth.jwksEndpoint) != null ? _config$oauth$jwksEnd : urlConcat(config.oauth.baseUrl, ".well-known/jwks.json"));
@@ -327,47 +332,6 @@ function armorCreateRefresh(config) {
327
332
  };
328
333
  }
329
334
 
330
- const ROUTE_PATH_REFRESH = ARMOR_REFRESH;
331
- const routeRefreshFactory = config => {
332
- const refresh = armorCreateRefresh(config);
333
- return {
334
- path: ROUTE_PATH_REFRESH,
335
- method: "POST",
336
- async handle({
337
- event
338
- }) {
339
- try {
340
- const tokens = await config.session.getTokens(event);
341
- if (!tokens) {
342
- return error(401, "Unauthorized");
343
- }
344
- return refresh.ensureValidToken(event, tokens, ({
345
- idToken,
346
- accessToken
347
- }) => {
348
- return json({
349
- idToken,
350
- accessToken
351
- });
352
- });
353
- } catch (ex) {
354
- if (ex instanceof ArmorRefreshError) {
355
- return error(401, "Unauthorized");
356
- }
357
- throw ex;
358
- }
359
- }
360
- };
361
- };
362
-
363
- const routeFactories = Object.freeze([routeLoginFactory, routeLogoutFactory, routeRedirectLoginFactory, routeRedirectLogoutFactory, routeRefreshFactory]);
364
- function routeCreate(config) {
365
- // @ts-expect-error Incorrect typing error.
366
- return new Map(routeFactories.map(routeFactory => routeFactory(config)).filter(route => Boolean(route))
367
- // @ts-expect-error Incorrect typing error.
368
- .map(route => [route.path, route]));
369
- }
370
-
371
335
  function cookieSessionGetTokens({
372
336
  cookies
373
337
  }) {
@@ -399,14 +363,14 @@ const armorCookieSession = {
399
363
  };
400
364
 
401
365
  function armor(config) {
402
- const routeByPath = routeCreate(config);
403
- const refresh = armorCreateRefresh(config);
366
+ const routeByPath = routeByPathFactory(config);
367
+ const refresh = armorRefreshFactory(config);
404
368
  return async ({
405
369
  event,
406
370
  resolve
407
371
  }) => {
408
372
  const route = routeByPath.get(event.url.pathname);
409
- if (route && route.method === event.request.method) {
373
+ if (route) {
410
374
  return route.handle({
411
375
  event,
412
376
  resolve
@@ -452,5 +416,5 @@ async function armorConfigFromOpenId(config, fetch) {
452
416
  };
453
417
  }
454
418
 
455
- export { armor, armorConfigFromOpenId, armorCookieSession, armorCookieSessionGet, armorCreateRefresh };
419
+ export { armor, armorConfigFromOpenId, armorCookieSession, armorCookieSessionGet, armorRefreshFactory };
456
420
  //# sourceMappingURL=index.esm.js.map
@@ -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/utils/refresh.ts","../src/routes/refresh.ts","../src/routes/routes.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\";\nexport const COOKIE_STATE = \"state\";\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\tmethod: \"GET\",\n\t\tasync handle({ event }) {\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\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\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\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\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","import { ArmorTokens } from \"../contracts\";\nimport { ArmorRefreshError } from \"../errors\";\nimport { shouldRefresh } from \"../utils/utils\";\n\nexport const ARMOR_REFRESH = \"/_armor/refresh\";\nexport const ARMOR_LOGIN = \"/_armor/login\";\n\ntype ArmorBrowserTokens = Pick<ArmorTokens, \"idToken\" | \"accessToken\">;\n\nexport async function armorBrowserRefresh(): Promise<ArmorBrowserTokens> {\n\tconst response = await fetch(ARMOR_REFRESH, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tif (response.status === 401) {\n\t\t\t// eslint-disable-next-line no-undef\n\t\t\twindow.location.href = ARMOR_LOGIN;\n\t\t\tthrow new ArmorRefreshError(\"Redirecting to login\");\n\t\t}\n\n\t\tconst error = await response.text();\n\t\tthrow new ArmorRefreshError(`Could not refresh token: ${error}`);\n\t}\n\n\treturn response.json();\n}\n\nexport async function armorBrowserEnsureValidTokens<T>(\n\ttokens: ArmorBrowserTokens,\n\tfn: (tokens: ArmorBrowserTokens) => T | Promise<T>,\n): Promise<T> {\n\tconst validTokens = shouldRefresh(tokens)\n\t\t? await armorBrowserRefresh()\n\t\t: tokens;\n\n\treturn fn(validTokens);\n}\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\tmethod: \"GET\",\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 = queryParamsCreate({\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\tthrow redirect(302, `${authorizeEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\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\tmethod: \"GET\",\n\t\tasync handle({ event }) {\n\t\t\teventStateValidOrThrow(event);\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 { randomUUID } from \"node:crypto\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\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\tmethod: \"GET\",\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 = queryParamsCreate({\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\tstate,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${params}`);\n\t\t},\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 armorCreateRefresh(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\tconsole.log(\"Refreshing tokens...\");\n\n\t\t\t\t\tthrowIfUndefined(tokens.exchange.refresh_token);\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\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\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 { error, json } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\nimport { armorCreateRefresh } from \"../utils/refresh\";\nimport { ARMOR_REFRESH } from \"../browser\";\nimport { ArmorRefreshError } from \"../errors\";\n\nexport const ROUTE_PATH_REFRESH = ARMOR_REFRESH;\n\nexport const routeRefreshFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst refresh = armorCreateRefresh(config);\n\n\treturn {\n\t\tpath: ROUTE_PATH_REFRESH,\n\t\tmethod: \"POST\",\n\t\tasync handle({ event }) {\n\t\t\ttry {\n\t\t\t\tconst tokens = await config.session.getTokens(event);\n\n\t\t\t\tif (!tokens) {\n\t\t\t\t\treturn error(401, \"Unauthorized\");\n\t\t\t\t}\n\n\t\t\t\treturn refresh.ensureValidToken(\n\t\t\t\t\tevent,\n\t\t\t\t\ttokens,\n\t\t\t\t\t({ idToken, accessToken }) => {\n\t\t\t\t\t\treturn json({ idToken, accessToken });\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} catch (ex) {\n\t\t\t\tif (ex instanceof ArmorRefreshError) {\n\t\t\t\t\treturn error(401, \"Unauthorized\");\n\t\t\t\t}\n\n\t\t\t\tthrow ex;\n\t\t\t}\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\";\nimport { routeRefreshFactory } from \"./refresh\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n\treadonly method: \"GET\" | \"POST\";\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n\trouteRefreshFactory,\n]);\n\nexport function routeCreate(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 { 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 { routeCreate } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\nimport { armorCreateRefresh } from \"./utils/refresh\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\nexport { armorCreateRefresh } from \"./utils/refresh\";\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routeByPath = routeCreate(config);\n\tconst refresh = armorCreateRefresh(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst route = routeByPath.get(event.url.pathname);\n\n\t\tif (route && route.method === event.request.method) {\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\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","_event$url$searchPara3","_event$url$searchPara2","error_description","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","createRemoteJWKSet","Promise","all","session","login","ARMOR_REFRESH","ARMOR_LOGIN","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","armorCreateRefresh","_config$oauth$refresh","refreshEndpoint","refresh","refreshToken","_json$refresh_token","ensureValidToken","fn","validTokens","console","log","newExchange","ROUTE_PATH_REFRESH","routeRefreshFactory","getTokens","ex","routeFactories","routeCreate","Map","map","routeFactory","filter","route","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","armor","routeByPath","resolve","pathname","request","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\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\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\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\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\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 = queryParamsCreate({\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\tthrow redirect(302, `${authorizeEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\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\teventStateValidOrThrow(event);\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 { randomUUID } from \"node:crypto\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\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\tmethod: \"GET\",\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 = queryParamsCreate({\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\tstate,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${params}`);\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\tconsole.log(\"Refreshing tokens...\");\n\n\t\t\t\t\tthrowIfUndefined(tokens.exchange.refresh_token);\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\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\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\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","_event$url$searchPara3","_event$url$searchPara2","error_description","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","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","console","log","newExchange","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","getTokens","armor","routeByPath","resolve","pathname","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
@@ -161,7 +161,6 @@ const routeRedirectLoginFactory = config => {
161
161
  }
162
162
  return {
163
163
  path: ROUTE_PATH_REDIRECT_LOGIN,
164
- method: "GET",
165
164
  async handle({
166
165
  event
167
166
  }) {
@@ -195,8 +194,8 @@ const routeRedirectLoginFactory = config => {
195
194
  };
196
195
  };
197
196
 
198
- const ARMOR_REFRESH = "/_armor/refresh";
199
197
  const ARMOR_LOGIN = "/_armor/login";
198
+ const ARMOR_LOGOUT = "/_armor/logout";
200
199
 
201
200
  const ROUTE_PATH_LOGIN = ARMOR_LOGIN;
202
201
  const routeLoginFactory = config => {
@@ -205,7 +204,6 @@ const routeLoginFactory = config => {
205
204
  const scope = (_config$oauth$scope = config.oauth.scope) != null ? _config$oauth$scope : "openid profile email";
206
205
  return {
207
206
  path: ROUTE_PATH_LOGIN,
208
- method: "GET",
209
207
  async handle({
210
208
  event
211
209
  }) {
@@ -232,7 +230,6 @@ const routeRedirectLogoutFactory = config => {
232
230
  }
233
231
  return {
234
232
  path: ROUTE_PATH_REDIRECT_LOGOUT,
235
- method: "GET",
236
233
  async handle({
237
234
  event
238
235
  }) {
@@ -243,7 +240,7 @@ const routeRedirectLogoutFactory = config => {
243
240
  };
244
241
  };
245
242
 
246
- const ROUTE_PATH_LOGOUT = "/_armor/logout";
243
+ const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;
247
244
  const routeLogoutFactory = config => {
248
245
  var _config$oauth$logoutR;
249
246
  // Check if the oauth provider supports a logout path.
@@ -269,7 +266,15 @@ const routeLogoutFactory = config => {
269
266
  };
270
267
  };
271
268
 
272
- function armorCreateRefresh(config) {
269
+ const routeFactories = Object.freeze([routeLoginFactory, routeLogoutFactory, routeRedirectLoginFactory, routeRedirectLogoutFactory]);
270
+ function routeByPathFactory(config) {
271
+ // @ts-expect-error Incorrect typing error.
272
+ return new Map(routeFactories.map(routeFactory => routeFactory(config)).filter(route => Boolean(route))
273
+ // @ts-expect-error Incorrect typing error.
274
+ .map(route => [route.path, route]));
275
+ }
276
+
277
+ function armorRefreshFactory(config) {
273
278
  var _config$oauth$refresh, _config$oauth$jwksEnd;
274
279
  const refreshEndpoint = (_config$oauth$refresh = config.oauth.refreshEndpoint) != null ? _config$oauth$refresh : urlConcat(config.oauth.baseUrl, "oauth2/token");
275
280
  const jwksUrl = new URL((_config$oauth$jwksEnd = config.oauth.jwksEndpoint) != null ? _config$oauth$jwksEnd : urlConcat(config.oauth.baseUrl, ".well-known/jwks.json"));
@@ -327,47 +332,6 @@ function armorCreateRefresh(config) {
327
332
  };
328
333
  }
329
334
 
330
- const ROUTE_PATH_REFRESH = ARMOR_REFRESH;
331
- const routeRefreshFactory = config => {
332
- const refresh = armorCreateRefresh(config);
333
- return {
334
- path: ROUTE_PATH_REFRESH,
335
- method: "POST",
336
- async handle({
337
- event
338
- }) {
339
- try {
340
- const tokens = await config.session.getTokens(event);
341
- if (!tokens) {
342
- return kit.error(401, "Unauthorized");
343
- }
344
- return refresh.ensureValidToken(event, tokens, ({
345
- idToken,
346
- accessToken
347
- }) => {
348
- return kit.json({
349
- idToken,
350
- accessToken
351
- });
352
- });
353
- } catch (ex) {
354
- if (ex instanceof ArmorRefreshError) {
355
- return kit.error(401, "Unauthorized");
356
- }
357
- throw ex;
358
- }
359
- }
360
- };
361
- };
362
-
363
- const routeFactories = Object.freeze([routeLoginFactory, routeLogoutFactory, routeRedirectLoginFactory, routeRedirectLogoutFactory, routeRefreshFactory]);
364
- function routeCreate(config) {
365
- // @ts-expect-error Incorrect typing error.
366
- return new Map(routeFactories.map(routeFactory => routeFactory(config)).filter(route => Boolean(route))
367
- // @ts-expect-error Incorrect typing error.
368
- .map(route => [route.path, route]));
369
- }
370
-
371
335
  function cookieSessionGetTokens({
372
336
  cookies
373
337
  }) {
@@ -399,14 +363,14 @@ const armorCookieSession = {
399
363
  };
400
364
 
401
365
  function armor(config) {
402
- const routeByPath = routeCreate(config);
403
- const refresh = armorCreateRefresh(config);
366
+ const routeByPath = routeByPathFactory(config);
367
+ const refresh = armorRefreshFactory(config);
404
368
  return async ({
405
369
  event,
406
370
  resolve
407
371
  }) => {
408
372
  const route = routeByPath.get(event.url.pathname);
409
- if (route && route.method === event.request.method) {
373
+ if (route) {
410
374
  return route.handle({
411
375
  event,
412
376
  resolve
@@ -456,5 +420,5 @@ exports.armor = armor;
456
420
  exports.armorConfigFromOpenId = armorConfigFromOpenId;
457
421
  exports.armorCookieSession = armorCookieSession;
458
422
  exports.armorCookieSessionGet = armorCookieSessionGet;
459
- exports.armorCreateRefresh = armorCreateRefresh;
423
+ exports.armorRefreshFactory = armorRefreshFactory;
460
424
  //# sourceMappingURL=index.js.map
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/utils/refresh.ts","../src/routes/refresh.ts","../src/routes/routes.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\";\nexport const COOKIE_STATE = \"state\";\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\tmethod: \"GET\",\n\t\tasync handle({ event }) {\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\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\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\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\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","import { ArmorTokens } from \"../contracts\";\nimport { ArmorRefreshError } from \"../errors\";\nimport { shouldRefresh } from \"../utils/utils\";\n\nexport const ARMOR_REFRESH = \"/_armor/refresh\";\nexport const ARMOR_LOGIN = \"/_armor/login\";\n\ntype ArmorBrowserTokens = Pick<ArmorTokens, \"idToken\" | \"accessToken\">;\n\nexport async function armorBrowserRefresh(): Promise<ArmorBrowserTokens> {\n\tconst response = await fetch(ARMOR_REFRESH, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tif (response.status === 401) {\n\t\t\t// eslint-disable-next-line no-undef\n\t\t\twindow.location.href = ARMOR_LOGIN;\n\t\t\tthrow new ArmorRefreshError(\"Redirecting to login\");\n\t\t}\n\n\t\tconst error = await response.text();\n\t\tthrow new ArmorRefreshError(`Could not refresh token: ${error}`);\n\t}\n\n\treturn response.json();\n}\n\nexport async function armorBrowserEnsureValidTokens<T>(\n\ttokens: ArmorBrowserTokens,\n\tfn: (tokens: ArmorBrowserTokens) => T | Promise<T>,\n): Promise<T> {\n\tconst validTokens = shouldRefresh(tokens)\n\t\t? await armorBrowserRefresh()\n\t\t: tokens;\n\n\treturn fn(validTokens);\n}\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\tmethod: \"GET\",\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 = queryParamsCreate({\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\tthrow redirect(302, `${authorizeEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\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\tmethod: \"GET\",\n\t\tasync handle({ event }) {\n\t\t\teventStateValidOrThrow(event);\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 { randomUUID } from \"node:crypto\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\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\tmethod: \"GET\",\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 = queryParamsCreate({\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\tstate,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${params}`);\n\t\t},\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 armorCreateRefresh(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\tconsole.log(\"Refreshing tokens...\");\n\n\t\t\t\t\tthrowIfUndefined(tokens.exchange.refresh_token);\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\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\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 { error, json } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\nimport { armorCreateRefresh } from \"../utils/refresh\";\nimport { ARMOR_REFRESH } from \"../browser\";\nimport { ArmorRefreshError } from \"../errors\";\n\nexport const ROUTE_PATH_REFRESH = ARMOR_REFRESH;\n\nexport const routeRefreshFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst refresh = armorCreateRefresh(config);\n\n\treturn {\n\t\tpath: ROUTE_PATH_REFRESH,\n\t\tmethod: \"POST\",\n\t\tasync handle({ event }) {\n\t\t\ttry {\n\t\t\t\tconst tokens = await config.session.getTokens(event);\n\n\t\t\t\tif (!tokens) {\n\t\t\t\t\treturn error(401, \"Unauthorized\");\n\t\t\t\t}\n\n\t\t\t\treturn refresh.ensureValidToken(\n\t\t\t\t\tevent,\n\t\t\t\t\ttokens,\n\t\t\t\t\t({ idToken, accessToken }) => {\n\t\t\t\t\t\treturn json({ idToken, accessToken });\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} catch (ex) {\n\t\t\t\tif (ex instanceof ArmorRefreshError) {\n\t\t\t\t\treturn error(401, \"Unauthorized\");\n\t\t\t\t}\n\n\t\t\t\tthrow ex;\n\t\t\t}\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\";\nimport { routeRefreshFactory } from \"./refresh\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n\treadonly method: \"GET\" | \"POST\";\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n\trouteRefreshFactory,\n]);\n\nexport function routeCreate(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 { 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 { routeCreate } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\nimport { armorCreateRefresh } from \"./utils/refresh\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\nexport { armorCreateRefresh } from \"./utils/refresh\";\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routeByPath = routeCreate(config);\n\tconst refresh = armorCreateRefresh(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst route = routeByPath.get(event.url.pathname);\n\n\t\tif (route && route.method === event.request.method) {\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\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","_event$url$searchPara3","_event$url$searchPara2","error_description","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","createRemoteJWKSet","Promise","all","session","login","ARMOR_REFRESH","ARMOR_LOGIN","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","armorCreateRefresh","_config$oauth$refresh","refreshEndpoint","refresh","refreshToken","_json$refresh_token","ensureValidToken","fn","validTokens","console","log","newExchange","ROUTE_PATH_REFRESH","routeRefreshFactory","getTokens","ex","routeFactories","routeCreate","Map","map","routeFactory","filter","route","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","armor","routeByPath","resolve","pathname","request","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\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\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\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\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\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 = queryParamsCreate({\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\tthrow redirect(302, `${authorizeEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\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\teventStateValidOrThrow(event);\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 { randomUUID } from \"node:crypto\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\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\tmethod: \"GET\",\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 = queryParamsCreate({\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\tstate,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${params}`);\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\tconsole.log(\"Refreshing tokens...\");\n\n\t\t\t\t\tthrowIfUndefined(tokens.exchange.refresh_token);\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\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\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\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","_event$url$searchPara3","_event$url$searchPara2","error_description","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","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","console","log","newExchange","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","getTokens","armor","routeByPath","resolve","pathname","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  import type { RouteFactory } from "./routes";
2
- export declare const ROUTE_PATH_LOGIN = "/_armor/login";
2
+ export declare const ROUTE_PATH_LOGIN: "/_armor/login";
3
3
  export declare const routeLoginFactory: RouteFactory;
@@ -1,3 +1,3 @@
1
1
  import type { RouteFactory } from "./routes";
2
- export declare const ROUTE_PATH_LOGOUT = "/_armor/logout";
2
+ export declare const ROUTE_PATH_LOGOUT: "/_armor/logout";
3
3
  export declare const routeLogoutFactory: RouteFactory;
@@ -3,7 +3,6 @@ import type { ArmorConfig } from "../contracts";
3
3
  export interface Route {
4
4
  readonly path: string;
5
5
  readonly handle: Handle;
6
- readonly method: "GET" | "POST";
7
6
  }
8
7
  export type RouteFactory = (config: ArmorConfig) => Route | undefined;
9
- export declare function routeCreate(config: ArmorConfig): Map<string, Route>;
8
+ export declare function routeByPathFactory(config: ArmorConfig): Map<string, Route>;
@@ -1,6 +1,6 @@
1
1
  import { Cookies } from "@sveltejs/kit";
2
- export declare const COOKIE_TOKENS = "tokens";
3
- export declare const COOKIE_STATE = "state";
2
+ export declare const COOKIE_TOKENS: "tokens";
3
+ export declare const COOKIE_STATE: "state";
4
4
  export declare function cookieSet(cookies: Cookies, key: string, value: string | object): void;
5
5
  export declare function cookieGetAndDelete<T>(cookies: Cookies, key: string): T | undefined;
6
6
  export declare function cookieGet<T>(cookies: Cookies, key: string): T | undefined;
@@ -1,6 +1,6 @@
1
1
  import { ArmorConfig, ArmorTokenExchange, ArmorTokens } from "../contracts";
2
2
  import { RequestEvent } from "@sveltejs/kit";
3
- export declare function armorCreateRefresh(config: ArmorConfig): {
3
+ export declare function armorRefreshFactory(config: ArmorConfig): {
4
4
  refresh: (fetch: typeof global.fetch, refreshToken: string) => Promise<ArmorTokenExchange>;
5
5
  ensureValidToken<T>(event: RequestEvent, tokens: ArmorTokens, fn: (tokens: ArmorTokens) => T | Promise<T>): Promise<T>;
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nekm/sveltekit-armor",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "Zero-config OAuth protection for SvelteKit",
5
5
  "license": "MIT",
6
6
  "source": "./src/index.ts",
@@ -1,41 +1,2 @@
1
- import { ArmorTokens } from "../contracts";
2
- import { ArmorRefreshError } from "../errors";
3
- import { shouldRefresh } from "../utils/utils";
4
-
5
- export const ARMOR_REFRESH = "/_armor/refresh";
6
- export const ARMOR_LOGIN = "/_armor/login";
7
-
8
- type ArmorBrowserTokens = Pick<ArmorTokens, "idToken" | "accessToken">;
9
-
10
- export async function armorBrowserRefresh(): Promise<ArmorBrowserTokens> {
11
- const response = await fetch(ARMOR_REFRESH, {
12
- method: "POST",
13
- headers: {
14
- Accept: "application/json",
15
- },
16
- });
17
-
18
- if (!response.ok) {
19
- if (response.status === 401) {
20
- // eslint-disable-next-line no-undef
21
- window.location.href = ARMOR_LOGIN;
22
- throw new ArmorRefreshError("Redirecting to login");
23
- }
24
-
25
- const error = await response.text();
26
- throw new ArmorRefreshError(`Could not refresh token: ${error}`);
27
- }
28
-
29
- return response.json();
30
- }
31
-
32
- export async function armorBrowserEnsureValidTokens<T>(
33
- tokens: ArmorBrowserTokens,
34
- fn: (tokens: ArmorBrowserTokens) => T | Promise<T>,
35
- ): Promise<T> {
36
- const validTokens = shouldRefresh(tokens)
37
- ? await armorBrowserRefresh()
38
- : tokens;
39
-
40
- return fn(validTokens);
41
- }
1
+ export const ARMOR_LOGIN = "/_armor/login" as const;
2
+ export const ARMOR_LOGOUT = "/_armor/logout" as const;
package/src/index.ts CHANGED
@@ -1,22 +1,22 @@
1
1
  import { redirect, type Handle } from "@sveltejs/kit";
2
2
  import { ROUTE_PATH_LOGIN } from "./routes/login";
3
3
  import type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from "./contracts";
4
- import { routeCreate } from "./routes/routes";
4
+ import { routeByPathFactory } from "./routes/routes";
5
5
  import { ArmorOpenIdConfigError } from "./errors";
6
- import { armorCreateRefresh } from "./utils/refresh";
6
+ import { armorRefreshFactory } from "./utils/refresh";
7
7
 
8
8
  export type { ArmorConfig, ArmorTokens };
9
9
  export { armorCookieSession, armorCookieSessionGet } from "./session/cookie";
10
- export { armorCreateRefresh } from "./utils/refresh";
10
+ export { armorRefreshFactory } from "./utils/refresh";
11
11
 
12
12
  export function armor(config: ArmorConfig): Handle {
13
- const routeByPath = routeCreate(config);
14
- const refresh = armorCreateRefresh(config);
13
+ const routeByPath = routeByPathFactory(config);
14
+ const refresh = armorRefreshFactory(config);
15
15
 
16
16
  return async ({ event, resolve }) => {
17
17
  const route = routeByPath.get(event.url.pathname);
18
18
 
19
- if (route && route.method === event.request.method) {
19
+ if (route) {
20
20
  return route.handle({ event, resolve });
21
21
  }
22
22
 
@@ -19,7 +19,6 @@ export const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {
19
19
 
20
20
  return {
21
21
  path: ROUTE_PATH_LOGIN,
22
- method: "GET",
23
22
  async handle({ event }) {
24
23
  const state = randomUUID();
25
24
  cookieSet(event.cookies, COOKIE_STATE, state);
@@ -6,8 +6,9 @@ import type { RouteFactory } from "./routes";
6
6
  import { urlConcat } from "../utils/utils";
7
7
  import { randomUUID } from "node:crypto";
8
8
  import { COOKIE_STATE, cookieSet } from "../utils/cookie";
9
+ import { ARMOR_LOGOUT } from "../browser";
9
10
 
10
- export const ROUTE_PATH_LOGOUT = "/_armor/logout";
11
+ export const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;
11
12
 
12
13
  export const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {
13
14
  // Check if the oauth provider supports a logout path.
@@ -70,7 +70,6 @@ export const routeRedirectLoginFactory: RouteFactory = (
70
70
 
71
71
  return {
72
72
  path: ROUTE_PATH_REDIRECT_LOGIN,
73
- method: "GET",
74
73
  async handle({ event }) {
75
74
  eventStateValidOrThrow(event);
76
75
 
@@ -15,7 +15,6 @@ export const routeRedirectLogoutFactory: RouteFactory = (
15
15
 
16
16
  return {
17
17
  path: ROUTE_PATH_REDIRECT_LOGOUT,
18
- method: "GET",
19
18
  async handle({ event }) {
20
19
  eventStateValidOrThrow(event);
21
20
 
@@ -4,12 +4,10 @@ import { routeLoginFactory } from "./login";
4
4
  import { routeLogoutFactory } from "./logout";
5
5
  import { routeRedirectLogoutFactory } from "./redirect-logout";
6
6
  import { routeRedirectLoginFactory } from "./redirect-login";
7
- import { routeRefreshFactory } from "./refresh";
8
7
 
9
8
  export interface Route {
10
9
  readonly path: string;
11
10
  readonly handle: Handle;
12
- readonly method: "GET" | "POST";
13
11
  }
14
12
 
15
13
  export type RouteFactory = (config: ArmorConfig) => Route | undefined;
@@ -19,10 +17,9 @@ const routeFactories = Object.freeze([
19
17
  routeLogoutFactory,
20
18
  routeRedirectLoginFactory,
21
19
  routeRedirectLogoutFactory,
22
- routeRefreshFactory,
23
20
  ]);
24
21
 
25
- export function routeCreate(config: ArmorConfig): Map<string, Route> {
22
+ export function routeByPathFactory(config: ArmorConfig): Map<string, Route> {
26
23
  // @ts-expect-error Incorrect typing error.
27
24
  return new Map(
28
25
  routeFactories
@@ -1,7 +1,7 @@
1
1
  import { Cookies } from "@sveltejs/kit";
2
2
 
3
- export const COOKIE_TOKENS = "tokens";
4
- export const COOKIE_STATE = "state";
3
+ export const COOKIE_TOKENS = "tokens" as const;
4
+ export const COOKIE_STATE = "state" as const;
5
5
 
6
6
  const cookieDeleteOptions = Object.freeze({ path: "/" });
7
7
 
@@ -12,7 +12,7 @@ import { redirect, RequestEvent } from "@sveltejs/kit";
12
12
  import { throwIfUndefined } from "@nekm/core";
13
13
  import { ROUTE_PATH_LOGIN } from "../routes/login";
14
14
 
15
- export function armorCreateRefresh(config: ArmorConfig) {
15
+ export function armorRefreshFactory(config: ArmorConfig) {
16
16
  const refreshEndpoint =
17
17
  config.oauth.refreshEndpoint ??
18
18
  urlConcat(config.oauth.baseUrl, "oauth2/token");
@@ -40,7 +40,7 @@ export function shouldRefresh(
40
40
  ? tokens.accessToken.exp * 1000
41
41
  : Infinity;
42
42
 
43
- return Math.min(idExpiry, accessExpiry) < (Date.now() + 5 * MINUTES_MS);
43
+ return Math.min(idExpiry, accessExpiry) < Date.now() + 5 * MINUTES_MS;
44
44
  }
45
45
 
46
46
  export function createExpiresAt(seconds: number): Date {
@@ -1,3 +0,0 @@
1
- import type { RouteFactory } from "./routes";
2
- export declare const ROUTE_PATH_REFRESH = "/_armor/refresh";
3
- export declare const routeRefreshFactory: RouteFactory;
@@ -1,40 +0,0 @@
1
- import { error, json } from "@sveltejs/kit";
2
- import type { ArmorConfig } from "../contracts";
3
- import type { RouteFactory } from "./routes";
4
- import { armorCreateRefresh } from "../utils/refresh";
5
- import { ARMOR_REFRESH } from "../browser";
6
- import { ArmorRefreshError } from "../errors";
7
-
8
- export const ROUTE_PATH_REFRESH = ARMOR_REFRESH;
9
-
10
- export const routeRefreshFactory: RouteFactory = (config: ArmorConfig) => {
11
- const refresh = armorCreateRefresh(config);
12
-
13
- return {
14
- path: ROUTE_PATH_REFRESH,
15
- method: "POST",
16
- async handle({ event }) {
17
- try {
18
- const tokens = await config.session.getTokens(event);
19
-
20
- if (!tokens) {
21
- return error(401, "Unauthorized");
22
- }
23
-
24
- return refresh.ensureValidToken(
25
- event,
26
- tokens,
27
- ({ idToken, accessToken }) => {
28
- return json({ idToken, accessToken });
29
- },
30
- );
31
- } catch (ex) {
32
- if (ex instanceof ArmorRefreshError) {
33
- return error(401, "Unauthorized");
34
- }
35
-
36
- throw ex;
37
- }
38
- },
39
- };
40
- };