@nekm/sveltekit-armor 0.1.3 → 0.1.5

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.
@@ -24,7 +24,7 @@ interface ArmorCredentials {
24
24
  readonly clientSecret: string;
25
25
  }
26
26
  export interface ArmorConfig {
27
- readonly session: {
27
+ readonly session?: {
28
28
  readonly exists?: (event: RequestEvent) => Promise<boolean> | boolean;
29
29
  readonly login?: (event: RequestEvent, tokens: ArmorTokens) => Promise<void> | void;
30
30
  readonly logout?: (event: RequestEvent) => Promise<void> | void;
@@ -33,9 +33,9 @@ export interface ArmorConfig {
33
33
  readonly baseUrl: string;
34
34
  readonly jwksUrl?: string;
35
35
  readonly issuer: string;
36
- readonly authorizePath?: string;
37
- readonly logoutPath?: string;
38
- readonly tokenPath?: string;
36
+ readonly authorizeEndpoint?: string;
37
+ readonly logoutEndpoint?: string;
38
+ readonly tokenEndpoint?: string;
39
39
  };
40
40
  }
41
41
  export interface ArmorOpenIdConfig extends Pick<ArmorConfig, "session"> {
package/dist/index.d.ts CHANGED
@@ -7,8 +7,8 @@ export declare function armor(config: ArmorConfig): Handle;
7
7
  /**
8
8
  * Some IdP's expose a /.well-known/openid-configuiration that specifies how to configure.
9
9
  * Use that to autoconfigure your instance.
10
- * @param fetch
11
10
  * @param config
11
+ * @param fetch
12
12
  */
13
- export declare function armorFromOpenIdConfig(fetch: typeof global.fetch, config: ArmorOpenIdConfig): Promise<Handle>;
13
+ export declare function armorFromOpenIdConfig(config: ArmorOpenIdConfig, fetch?: typeof global.fetch): Promise<Handle>;
14
14
  export declare function armorCookiesGetTokens(cookies: Cookies): ArmorTokens;
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { redirect, error } from '@sveltejs/kit';
2
2
  import { strTrimEnd, strTrimStart, throwIfUndefined, queryParamsCreate, noop } from '@nekm/core';
3
- import { jwtVerify, createRemoteJWKSet } from 'jose';
3
+ import { jwtDecrypt, jwtVerify, createRemoteJWKSet } from 'jose';
4
4
  import { randomUUID } from 'node:crypto';
5
5
 
6
6
  function urlConcat(origin, path) {
@@ -41,30 +41,41 @@ function cookieGet(cookies, key) {
41
41
  return !value ? undefined : JSON.parse(value);
42
42
  }
43
43
 
44
- function jwtVerifyIdToken(config, jwks, idToken) {
45
- return jwtVerifyToken(jwks, {
44
+ function jwtVerifyAndDecryptIdToken(config, jwks, idToken) {
45
+ return jwtVerifyAndDecryptToken(config, jwks, {
46
46
  issuer: config.oauth.issuer,
47
47
  audience: config.oauth.clientId
48
48
  }, idToken);
49
49
  }
50
- function jwtVerifyAccessToken(config, jwks, accessToken) {
51
- return jwtVerifyToken(jwks, {
50
+ function jwtVerifyAndDecryptAccessToken(config, jwks, accessToken) {
51
+ return jwtVerifyAndDecryptToken(config, jwks, {
52
52
  issuer: config.oauth.issuer
53
53
  }, accessToken);
54
54
  }
55
- async function jwtVerifyToken(jwks, options, token) {
55
+ function jwtIsEncryptedToken(token) {
56
+ const parts = token.split(".");
57
+ return parts.length === 5;
58
+ }
59
+ async function jwtVerifyAndDecryptToken(config, jwks, opts, token) {
60
+ if (jwtIsEncryptedToken(token)) {
61
+ const secret = new TextEncoder().encode(config.oauth.clientSecret);
62
+ const {
63
+ payload
64
+ } = await jwtDecrypt(token, secret, opts);
65
+ return payload;
66
+ }
56
67
  const {
57
68
  payload
58
- } = await jwtVerify(token, jwks, options);
69
+ } = await jwtVerify(token, jwks, opts);
59
70
  return payload;
60
71
  }
61
72
 
62
73
  const ROUTE_PATH_REDIRECT_LOGIN = "/_armor/redirect/login";
63
74
  const routeRedirectLoginFactory = config => {
64
- var _config$oauth$jwksUrl, _config$oauth$tokenPa, _config$session$login;
75
+ var _config$oauth$jwksUrl, _config$oauth$tokenEn, _config$session$login, _config$session;
65
76
  const jwksUrl = new URL((_config$oauth$jwksUrl = config.oauth.jwksUrl) != null ? _config$oauth$jwksUrl : `${strTrimEnd(config.oauth.issuer, "/")}/.well-known/jwks.json`);
66
- const tokenUrl = urlConcat(config.oauth.baseUrl, (_config$oauth$tokenPa = config.oauth.tokenPath) != null ? _config$oauth$tokenPa : "oauth2/token");
67
- const sessionLogin = (_config$session$login = config.session.login) != null ? _config$session$login : (event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens);
77
+ const tokenUrl = (_config$oauth$tokenEn = config.oauth.tokenEndpoint) != null ? _config$oauth$tokenEn : urlConcat(config.oauth.baseUrl, "oauth2/token");
78
+ const sessionLogin = (_config$session$login = (_config$session = config.session) == null ? void 0 : _config$session.login) != null ? _config$session$login : (event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens);
68
79
  async function exchangeCodeForToken(fetch, origin, code) {
69
80
  const response = await fetch(tokenUrl, {
70
81
  method: "POST",
@@ -105,7 +116,7 @@ const routeRedirectLoginFactory = config => {
105
116
  throwIfUndefined(code);
106
117
  const exchange = await exchangeCodeForToken(fetch, event.url.origin, code);
107
118
  const jwks = createRemoteJWKSet(jwksUrl);
108
- const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, exchange.id_token), jwtVerifyAccessToken(config, jwks, exchange.access_token)]);
119
+ const [idToken, accessToken] = await Promise.all([jwtVerifyAndDecryptIdToken(config, jwks, exchange.id_token), jwtVerifyAndDecryptAccessToken(config, jwks, exchange.access_token)]);
109
120
  await sessionLogin(event, {
110
121
  exchange,
111
122
  idToken: idToken,
@@ -119,7 +130,7 @@ const routeRedirectLoginFactory = config => {
119
130
  const ROUTE_PATH_LOGIN = "/_armor/login";
120
131
  const routeLoginFactory = config => {
121
132
  var _config$oauth$authori;
122
- const authorizeUrl = urlConcat(config.oauth.baseUrl, (_config$oauth$authori = config.oauth.authorizePath) != null ? _config$oauth$authori : "/oauth2/authorize");
133
+ const authorizeEndpoint = (_config$oauth$authori = config.oauth.authorizeEndpoint) != null ? _config$oauth$authori : urlConcat(config.oauth.baseUrl, "oauth2/authorize");
123
134
  return {
124
135
  path: ROUTE_PATH_LOGIN,
125
136
  async handle({
@@ -133,19 +144,19 @@ const routeLoginFactory = config => {
133
144
  redirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),
134
145
  state
135
146
  });
136
- throw redirect(302, `${authorizeUrl}?${params}`);
147
+ throw redirect(302, `${authorizeEndpoint}?${params}`);
137
148
  }
138
149
  };
139
150
  };
140
151
 
141
152
  const ROUTE_PATH_REDIRECT_LOGOUT = "/_armor/redirect/logout";
142
153
  const routeRedirectLogoutFactory = config => {
143
- var _config$session$logou;
154
+ var _config$session$logou, _config$session;
144
155
  // Check if the oauth provider supports a logout path.
145
- if (!config.oauth.logoutPath) {
156
+ if (!config.oauth.logoutEndpoint) {
146
157
  return undefined;
147
158
  }
148
- const logout = (_config$session$logou = config.session.logout) != null ? _config$session$logou : noop;
159
+ const logout = (_config$session$logou = (_config$session = config.session) == null ? void 0 : _config$session.logout) != null ? _config$session$logou : noop;
149
160
  return {
150
161
  path: ROUTE_PATH_REDIRECT_LOGOUT,
151
162
  async handle({
@@ -160,10 +171,9 @@ const routeRedirectLogoutFactory = config => {
160
171
  const ROUTE_PATH_LOGOUT = "/_armor/logout";
161
172
  const routeLogoutFactory = config => {
162
173
  // Check if the oauth provider supports a logout path.
163
- if (!config.oauth.logoutPath) {
174
+ if (!config.oauth.logoutEndpoint) {
164
175
  return undefined;
165
176
  }
166
- const logoutUrl = urlConcat(config.oauth.baseUrl, config.oauth.logoutPath);
167
177
  return {
168
178
  path: ROUTE_PATH_LOGOUT,
169
179
  async handle({
@@ -173,7 +183,7 @@ const routeLogoutFactory = config => {
173
183
  logout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
174
184
  client_id: config.oauth.clientId
175
185
  });
176
- throw redirect(302, `${logoutUrl}?${params}`);
186
+ throw redirect(302, `${config.oauth.logoutEndpoint}?${params}`);
177
187
  }
178
188
  };
179
189
  };
@@ -190,9 +200,9 @@ class ArmorOpenIdConfigError extends Error {}
190
200
  const ARMOR_LOGIN = ROUTE_PATH_LOGIN;
191
201
  const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;
192
202
  function armor(config) {
193
- var _config$session$exist;
203
+ var _config$session$exist, _config$session;
194
204
  const routes = routeCreate(config);
195
- const sessionExists = (_config$session$exist = config.session.exists) != null ? _config$session$exist : event => Boolean(event.cookies.get(COOKIE_TOKENS));
205
+ const sessionExists = (_config$session$exist = (_config$session = config.session) == null ? void 0 : _config$session.exists) != null ? _config$session$exist : event => Boolean(event.cookies.get(COOKIE_TOKENS));
196
206
  return async ({
197
207
  event,
198
208
  resolve
@@ -216,13 +226,14 @@ function armor(config) {
216
226
  /**
217
227
  * Some IdP's expose a /.well-known/openid-configuiration that specifies how to configure.
218
228
  * Use that to autoconfigure your instance.
219
- * @param fetch
220
229
  * @param config
230
+ * @param fetch
221
231
  */
222
- async function armorFromOpenIdConfig(fetch, config) {
232
+ async function armorFromOpenIdConfig(config, fetch) {
223
233
  var _config$oauth$openIdC, _body$end_session_end;
224
234
  const url = (_config$oauth$openIdC = config.oauth.openIdConfigUrl) != null ? _config$oauth$openIdC : `${config.oauth.baseUrl}/.well-known/openid-configuration`;
225
- const response = await fetch(url, {
235
+ const fetchToUse = fetch != null ? fetch : global.fetch;
236
+ const response = await fetchToUse(url, {
226
237
  headers: {
227
238
  Accept: "application/json"
228
239
  }
@@ -236,11 +247,11 @@ async function armorFromOpenIdConfig(fetch, config) {
236
247
  ...config,
237
248
  oauth: {
238
249
  ...config.oauth,
239
- tokenPath: body.token_endpoint,
240
- authorizePath: body.authorization_endpoint,
250
+ tokenEndpoint: body.token_endpoint,
251
+ authorizeEndpoint: body.authorization_endpoint,
241
252
  issuer: body.issuer,
242
253
  jwksUrl: body.jwks_uri,
243
- logoutPath: (_body$end_session_end = body.end_session_endpoint) != null ? _body$end_session_end : undefined
254
+ logoutEndpoint: (_body$end_session_end = body.end_session_endpoint) != null ? _body$end_session_end : undefined
244
255
  }
245
256
  });
246
257
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/utils/utils.ts","../src/utils/cookie.ts","../src/utils/jwt.ts","../src/routes/redirect-login.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/errors.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type { ArmorTokenExchange } 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","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","import { ArmorConfig } from \"../contracts\";\nimport { jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n) {\n\treturn 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}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n) {\n\treturn jwtVerifyToken(jwks, { issuer: config.oauth.issuer }, accessToken);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\toptions: JWTVerifyOptions,\n\ttoken: string,\n) {\n\tconst { payload } = await jwtVerify(token, jwks, options);\n\n\treturn payload;\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { strTrimEnd, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange } from \"../utils/utils\";\nimport {\n\tCOOKIE_STATE,\n\tCOOKIE_TOKENS,\n\tcookieGetAndDelete,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"../utils/jwt\";\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.jwksUrl ??\n\t\t\t`${strTrimEnd(config.oauth.issuer, \"/\")}/.well-known/jwks.json`,\n\t);\n\n\tconst tokenUrl = urlConcat(\n\t\tconfig.oauth.baseUrl,\n\t\tconfig.oauth.tokenPath ?? \"oauth2/token\",\n\t);\n\n\tconst sessionLogin =\n\t\tconfig.session.login ??\n\t\t((event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens));\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 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({\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\t\tcode,\n\t\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t}).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\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\t\t\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\t\t\tif (state !== stateCookie) {\n\t\t\t\tthrow new Error(\"State do not match\");\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\tfetch,\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 sessionLogin(event, {\n\t\t\t\texchange,\n\t\t\t\tidToken: idToken as ArmorIdToken,\n\t\t\t\taccessToken,\n\t\t\t});\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_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\";\n\nexport const ROUTE_PATH_LOGIN = \"/_armor/login\";\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeUrl = urlConcat(\n\t\tconfig.oauth.baseUrl,\n\t\tconfig.oauth.authorizePath ?? \"/oauth2/authorize\",\n\t);\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});\n\n\t\t\tthrow redirect(302, `${authorizeUrl}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { noop } from \"@nekm/core\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutPath) {\n\t\treturn undefined;\n\t}\n\n\tconst logout = config.session.logout ?? noop;\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tawait logout(event);\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\";\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.logoutPath) {\n\t\treturn undefined;\n\t}\n\n\tconst logoutUrl = urlConcat(config.oauth.baseUrl, config.oauth.logoutPath);\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tlogout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${logoutUrl}?${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 routeCreate(config: ArmorConfig): Map<string, Handle> {\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.handle]),\n\t);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends Error {}\n","import { error, redirect, type Handle, Cookies } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { ROUTE_PATH_LOGOUT } from \"./routes/logout\";\nimport { routeCreate } from \"./routes/routes\";\nimport { COOKIE_TOKENS, cookieGet } from \"./utils/cookie\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\n\nexport type { ArmorConfig, ArmorTokens };\n\nexport const ARMOR_LOGIN = ROUTE_PATH_LOGIN;\nexport const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routes = routeCreate(config);\n\tconst sessionExists =\n\t\tconfig.session.exists ??\n\t\t((event) => Boolean(event.cookies.get(COOKIE_TOKENS)));\n\n\treturn async ({ event, resolve }) => {\n\t\tconst routeHandle = routes.get(event.url.pathname);\n\n\t\tif (routeHandle) {\n\t\t\tawait routeHandle({ event, resolve });\n\n\t\t\t// Handle should redirect. If it doesn't, something is wrong.\n\t\t\tthrow error(500, \"Illegal state\");\n\t\t}\n\n\t\tconst exists = await sessionExists(event);\n\n\t\tif (!exists) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn resolve(event);\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuiration that specifies how to configure.\n * Use that to autoconfigure your instance.\n * @param fetch\n * @param config\n */\nexport async function armorFromOpenIdConfig(\n\tfetch: typeof global.fetch,\n\tconfig: ArmorOpenIdConfig,\n) {\n\tconst url =\n\t\tconfig.oauth.openIdConfigUrl ??\n\t\t`${config.oauth.baseUrl}/.well-known/openid-configuration`;\n\n\tconst response = await fetch(url, {\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 armor({\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenPath: body.token_endpoint,\n\t\t\tauthorizePath: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksUrl: body.jwks_uri,\n\t\t\tlogoutPath: body.end_session_endpoint ?? undefined,\n\t\t},\n\t});\n}\n\nexport function armorCookiesGetTokens(cookies: Cookies): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\tthrowIfUndefined(tokens);\n\treturn tokens;\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","jwtVerifyIdToken","config","jwks","idToken","jwtVerifyToken","issuer","oauth","audience","clientId","jwtVerifyAccessToken","accessToken","options","token","payload","jwtVerify","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksUrl","_config$oauth$tokenPa","_config$session$login","jwksUrl","URL","tokenUrl","baseUrl","tokenPath","sessionLogin","session","login","event","tokens","exchangeCodeForToken","fetch","code","response","method","headers","Accept","body","URLSearchParams","grant_type","client_id","client_secret","clientSecret","redirect_uri","toString","ok","error","text","Error","json","handle","_event$url$searchPara","_event$url$searchPara2","state","url","searchParams","stateCookie","throwIfUndefined","exchange","createRemoteJWKSet","Promise","all","redirect","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeUrl","authorizePath","randomUUID","params","queryParamsCreate","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","_config$session$logou","logoutPath","logout","noop","ROUTE_PATH_LOGOUT","routeLogoutFactory","logoutUrl","logout_uri","routeFactories","routeCreate","Map","map","routeFactory","filter","route","Boolean","ArmorOpenIdConfigError","ARMOR_LOGIN","ARMOR_LOGOUT","armor","_config$session$exist","routes","sessionExists","exists","resolve","routeHandle","pathname","armorFromOpenIdConfig","_config$oauth$openIdC","_body$end_session_end","openIdConfigUrl","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint","armorCookiesGetTokens"],"mappings":";;;;;AAGgB,SAAAA,SAASA,CAACC,MAAc,EAAEC,IAAY,EAAA;AACrD,EAAA,OAAO,CAACC,UAAU,CAACF,MAAM,EAAE,GAAG,CAAC,EAAEG,YAAY,CAACF,IAAI,EAAE,GAAG,CAAC,CAAC,CAACG,IAAI,CAAC,GAAG,CAAC,CAAA;AACpE,CAAA;AAEM,SAAUC,eAAeA,CAACC,KAAc,EAAA;EAC7C,IAAI,OAAOA,KAAK,KAAK,QAAQ,IAAIA,KAAK,KAAK,IAAI,EAAE,OAAO,KAAK,CAAA;EAE7D,MAAMC,GAAG,GAAGD,KAAgC,CAAA;AAE5C,EAAA,OACC,OAAOC,GAAG,CAACC,YAAY,KAAK,QAAQ,IACpCD,GAAG,CAACE,UAAU,KAAK,QAAQ,IAC3B,OAAOF,GAAG,CAACG,UAAU,KAAK,QAAQ;AAClC;AACC,EAAA,OAAOH,GAAG,CAACI,QAAQ,KAAK,QAAQ,IAAIJ,GAAG,CAACI,QAAQ,KAAKC,SAAS,CAAC,KAC/D,OAAOL,GAAG,CAACM,aAAa,KAAK,QAAQ,IACrCN,GAAG,CAACM,aAAa,KAAKD,SAAS,CAAC,KAChC,OAAOL,GAAG,CAACO,KAAK,KAAK,QAAQ,IAAIP,GAAG,CAACO,KAAK,KAAKF,SAAS,CAAC,CAAA;AAE5D;;ACpBO,MAAMG,aAAa,GAAG,QAAQ,CAAA;AAC9B,MAAMC,YAAY,GAAG,OAAO,CAAA;AAEnC,MAAMC,mBAAmB,GAAGC,MAAM,CAACC,MAAM,CAAC;AAAElB,EAAAA,IAAI,EAAE,GAAA;AAAK,CAAA,CAAC,CAAA;AAExD,MAAMmB,gBAAgB,GAAGF,MAAM,CAACC,MAAM,CAAC;AACtC,EAAA,GAAGF,mBAAmB;AACtBI,EAAAA,QAAQ,EAAE,IAAI;AACdC,EAAAA,MAAM,EAAE,IAAI;AACZC,EAAAA,QAAQ,EAAE,KAAK;EACfC,MAAM,EAAE,IAAI;AACZ,CAAA,CAAC,CAAA;SAEcC,SAASA,CACxBC,OAAgB,EAChBC,GAAW,EACXrB,KAAsB,EAAA;AAEtBoB,EAAAA,OAAO,CAACE,GAAG,CAACD,GAAG,EAAEE,IAAI,CAACC,SAAS,CAACxB,KAAK,CAAC,EAAEc,gBAAgB,CAAC,CAAA;AAC1D,CAAA;AAEgB,SAAAW,kBAAkBA,CACjCL,OAAgB,EAChBC,GAAW,EAAA;AAEX,EAAA,MAAMrB,KAAK,GAAG0B,SAAS,CAAIN,OAAO,EAAEC,GAAG,CAAC,CAAA;AAExC,EAAA,IAAIrB,KAAK,EAAE;AACVoB,IAAAA,OAAO,CAACO,MAAM,CAACN,GAAG,EAAEV,mBAAmB,CAAC,CAAA;AACzC,GAAA;AAEA,EAAA,OAAOX,KAAK,CAAA;AACb,CAAA;AAEgB,SAAA0B,SAASA,CAAIN,OAAgB,EAAEC,GAAW,EAAA;AACzD,EAAA,MAAMrB,KAAK,GAAGoB,OAAO,CAACQ,GAAG,CAACP,GAAG,CAAC,CAAA;EAE9B,OAAO,CAACrB,KAAK,GAAGM,SAAS,GAAGiB,IAAI,CAACM,KAAK,CAAC7B,KAAK,CAAC,CAAA;AAC9C;;SCrCgB8B,gBAAgBA,CAC/BC,MAAmB,EACnBC,IAAqB,EACrBC,OAAe,EAAA;EAEf,OAAOC,cAAc,CACpBF,IAAI,EACJ;AACCG,IAAAA,MAAM,EAAEJ,MAAM,CAACK,KAAK,CAACD,MAAM;AAC3BE,IAAAA,QAAQ,EAAEN,MAAM,CAACK,KAAK,CAACE,QAAAA;GACvB,EACDL,OAAO,CACP,CAAA;AACF,CAAA;SAEgBM,oBAAoBA,CACnCR,MAAmB,EACnBC,IAAqB,EACrBQ,WAAmB,EAAA;EAEnB,OAAON,cAAc,CAACF,IAAI,EAAE;AAAEG,IAAAA,MAAM,EAAEJ,MAAM,CAACK,KAAK,CAACD,MAAAA;GAAQ,EAAEK,WAAW,CAAC,CAAA;AAC1E,CAAA;AAEA,eAAeN,cAAcA,CAC5BF,IAAqB,EACrBS,OAAyB,EACzBC,KAAa,EAAA;EAEb,MAAM;AAAEC,IAAAA,OAAAA;GAAS,GAAG,MAAMC,SAAS,CAACF,KAAK,EAAEV,IAAI,EAAES,OAAO,CAAC,CAAA;AAEzD,EAAA,OAAOE,OAAO,CAAA;AACf;;AChBO,MAAME,yBAAyB,GAAG,wBAAwB,CAAA;AAE1D,MAAMC,yBAAyB,GACrCf,MAAmB,IAChB;AAAA,EAAA,IAAAgB,qBAAA,EAAAC,qBAAA,EAAAC,qBAAA,CAAA;EACH,MAAMC,OAAO,GAAG,IAAIC,GAAG,CAAA,CAAAJ,qBAAA,GACtBhB,MAAM,CAACK,KAAK,CAACc,OAAO,KAAA,IAAA,GAAAH,qBAAA,GACnB,CAAGnD,EAAAA,UAAU,CAACmC,MAAM,CAACK,KAAK,CAACD,MAAM,EAAE,GAAG,CAAC,CAAA,sBAAA,CAAwB,CAChE,CAAA;EAED,MAAMiB,QAAQ,GAAG3D,SAAS,CACzBsC,MAAM,CAACK,KAAK,CAACiB,OAAO,EAAA,CAAAL,qBAAA,GACpBjB,MAAM,CAACK,KAAK,CAACkB,SAAS,KAAAN,IAAAA,GAAAA,qBAAA,GAAI,cAAc,CACxC,CAAA;EAED,MAAMO,YAAY,GAAAN,CAAAA,qBAAA,GACjBlB,MAAM,CAACyB,OAAO,CAACC,KAAK,KAAAR,IAAAA,GAAAA,qBAAA,GACnB,CAACS,KAAK,EAAEC,MAAM,KAAKxC,SAAS,CAACuC,KAAK,CAACtC,OAAO,EAAEX,aAAa,EAAEkD,MAAM,CAAE,CAAA;AAErE,EAAA,eAAeC,oBAAoBA,CAClCC,KAA0B,EAC1BnE,MAAc,EACdoE,IAAY,EAAA;AAEZ,IAAA,MAAMC,QAAQ,GAAG,MAAMF,KAAK,CAACT,QAAQ,EAAE;AACtCY,MAAAA,MAAM,EAAE,MAAM;AACdC,MAAAA,OAAO,EAAE;AACR,QAAA,cAAc,EAAE,mCAAmC;AACnDC,QAAAA,MAAM,EAAE,kBAAA;OACR;MACDC,IAAI,EAAE,IAAIC,eAAe,CAAC;AACzBC,QAAAA,UAAU,EAAE,oBAAoB;AAChCC,QAAAA,SAAS,EAAEvC,MAAM,CAACK,KAAK,CAACE,QAAQ;AAChCiC,QAAAA,aAAa,EAAExC,MAAM,CAACK,KAAK,CAACoC,YAAY;QACxCV,IAAI;AACJW,QAAAA,YAAY,EAAEhF,SAAS,CAACC,MAAM,EAAEmD,yBAAyB,CAAA;OACzD,CAAC,CAAC6B,QAAQ,EAAE;AACb,KAAA,CAAC,CAAA;AAEF,IAAA,IAAI,CAACX,QAAQ,CAACY,EAAE,EAAE;AACjB,MAAA,MAAMC,KAAK,GAAG,MAAMb,QAAQ,CAACc,IAAI,EAAE,CAAA;AACnC,MAAA,MAAM,IAAIC,KAAK,CAAC,CAA0BF,uBAAAA,EAAAA,KAAK,EAAE,CAAC,CAAA;AACnD,KAAA;AAEA,IAAA,MAAMlC,KAAK,GAAG,MAAMqB,QAAQ,CAACgB,IAAI,EAAE,CAAA;AAEnC,IAAA,IAAI,CAAChF,eAAe,CAAC2C,KAAK,CAAC,EAAE;AAC5B,MAAA,MAAM,IAAIoC,KAAK,CAAC,yCAAyC,CAAC,CAAA;AAC3D,KAAA;AAEA,IAAA,OAAOpC,KAAK,CAAA;AACb,GAAA;EAEA,OAAO;AACN/C,IAAAA,IAAI,EAAEkD,yBAAyB;AAC/B,IAAA,MAAMmC,MAAMA,CAAC;AAAEtB,MAAAA,KAAAA;AAAO,KAAA,EAAA;MAAA,IAAAuB,qBAAA,EAAAC,sBAAA,CAAA;AACrB,MAAA,MAAMC,KAAK,GAAAF,CAAAA,qBAAA,GAAGvB,KAAK,CAAC0B,GAAG,CAACC,YAAY,CAACzD,GAAG,CAAC,OAAO,CAAC,KAAAqD,IAAAA,GAAAA,qBAAA,GAAI3E,SAAS,CAAA;MAC9D,MAAMgF,WAAW,GAAG7D,kBAAkB,CAACiC,KAAK,CAACtC,OAAO,EAAEV,YAAY,CAAC,CAAA;MAEnE,IAAIyE,KAAK,KAAKG,WAAW,EAAE;AAC1B,QAAA,MAAM,IAAIR,KAAK,CAAC,oBAAoB,CAAC,CAAA;AACtC,OAAA;AAEA,MAAA,MAAMhB,IAAI,GAAAoB,CAAAA,sBAAA,GAAGxB,KAAK,CAAC0B,GAAG,CAACC,YAAY,CAACzD,GAAG,CAAC,MAAM,CAAC,KAAAsD,IAAAA,GAAAA,sBAAA,GAAI5E,SAAS,CAAA;MAC5DiF,gBAAgB,CAACzB,IAAI,CAAC,CAAA;AAEtB,MAAA,MAAM0B,QAAQ,GAAG,MAAM5B,oBAAoB,CAC1CC,KAAK,EACLH,KAAK,CAAC0B,GAAG,CAAC1F,MAAM,EAChBoE,IAAI,CACJ,CAAA;AAED,MAAA,MAAM9B,IAAI,GAAGyD,kBAAkB,CAACvC,OAAO,CAAC,CAAA;AAExC,MAAA,MAAM,CAACjB,OAAO,EAAEO,WAAW,CAAC,GAAG,MAAMkD,OAAO,CAACC,GAAG,CAAC,CAChD7D,gBAAgB,CAACC,MAAM,EAAEC,IAAI,EAAEwD,QAAQ,CAACnF,QAAQ,CAAC,EACjDkC,oBAAoB,CAACR,MAAM,EAAEC,IAAI,EAAEwD,QAAQ,CAACtF,YAAY,CAAC,CACzD,CAAC,CAAA;MAEF,MAAMqD,YAAY,CAACG,KAAK,EAAE;QACzB8B,QAAQ;AACRvD,QAAAA,OAAO,EAAEA,OAAuB;AAChCO,QAAAA,WAAAA;AACA,OAAA,CAAC,CAAA;AAEF,MAAA,MAAMoD,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AACzB,KAAA;GACA,CAAA;AACF,CAAC;;ACjGM,MAAMC,gBAAgB,GAAG,eAAe,CAAA;AAExC,MAAMC,iBAAiB,GAAkB/D,MAAmB,IAAI;AAAA,EAAA,IAAAgE,qBAAA,CAAA;EACtE,MAAMC,YAAY,GAAGvG,SAAS,CAC7BsC,MAAM,CAACK,KAAK,CAACiB,OAAO,EAAA,CAAA0C,qBAAA,GACpBhE,MAAM,CAACK,KAAK,CAAC6D,aAAa,KAAAF,IAAAA,GAAAA,qBAAA,GAAI,mBAAmB,CACjD,CAAA;EAED,OAAO;AACNpG,IAAAA,IAAI,EAAEkG,gBAAgB;AACtB,IAAA,MAAMb,MAAMA,CAAC;AAAEtB,MAAAA,KAAAA;AAAO,KAAA,EAAA;AACrB,MAAA,MAAMyB,KAAK,GAAGe,UAAU,EAAE,CAAA;MAC1B/E,SAAS,CAACuC,KAAK,CAACtC,OAAO,EAAEV,YAAY,EAAEyE,KAAK,CAAC,CAAA;MAE7C,MAAMgB,MAAM,GAAGC,iBAAiB,CAAC;AAChC9B,QAAAA,SAAS,EAAEvC,MAAM,CAACK,KAAK,CAACE,QAAQ;AAChC+D,QAAAA,aAAa,EAAE,MAAM;QACrB5B,YAAY,EAAEhF,SAAS,CAACiE,KAAK,CAAC0B,GAAG,CAAC1F,MAAM,EAAEmD,yBAAyB,CAAC;AACpEsC,QAAAA,KAAAA;AACA,OAAA,CAAC,CAAA;MAEF,MAAMS,QAAQ,CAAC,GAAG,EAAE,GAAGI,YAAY,CAAA,CAAA,EAAIG,MAAM,CAAA,CAAE,CAAC,CAAA;AACjD,KAAA;GACA,CAAA;AACF,CAAC;;AC5BM,MAAMG,0BAA0B,GAAG,yBAAyB,CAAA;AAE5D,MAAMC,0BAA0B,GACtCxE,MAAmB,IAChB;AAAA,EAAA,IAAAyE,qBAAA,CAAA;AACH;AACA,EAAA,IAAI,CAACzE,MAAM,CAACK,KAAK,CAACqE,UAAU,EAAE;AAC7B,IAAA,OAAOnG,SAAS,CAAA;AACjB,GAAA;AAEA,EAAA,MAAMoG,MAAM,GAAA,CAAAF,qBAAA,GAAGzE,MAAM,CAACyB,OAAO,CAACkD,MAAM,KAAA,IAAA,GAAAF,qBAAA,GAAIG,IAAI,CAAA;EAE5C,OAAO;AACNhH,IAAAA,IAAI,EAAE2G,0BAA0B;AAChC,IAAA,MAAMtB,MAAMA,CAAC;AAAEtB,MAAAA,KAAAA;AAAO,KAAA,EAAA;MACrB,MAAMgD,MAAM,CAAChD,KAAK,CAAC,CAAA;AACnB,MAAA,MAAMkC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AACzB,KAAA;GACA,CAAA;AACF,CAAC;;ACjBM,MAAMgB,iBAAiB,GAAG,gBAAgB,CAAA;AAE1C,MAAMC,kBAAkB,GAAkB9E,MAAmB,IAAI;AACvE;AACA,EAAA,IAAI,CAACA,MAAM,CAACK,KAAK,CAACqE,UAAU,EAAE;AAC7B,IAAA,OAAOnG,SAAS,CAAA;AACjB,GAAA;AAEA,EAAA,MAAMwG,SAAS,GAAGrH,SAAS,CAACsC,MAAM,CAACK,KAAK,CAACiB,OAAO,EAAEtB,MAAM,CAACK,KAAK,CAACqE,UAAU,CAAC,CAAA;EAE1E,OAAO;AACN9G,IAAAA,IAAI,EAAEiH,iBAAiB;AACvB,IAAA,MAAM5B,MAAMA,CAAC;AAAEtB,MAAAA,KAAAA;AAAO,KAAA,EAAA;MACrB,MAAMyC,MAAM,GAAGC,iBAAiB,CAAC;QAChCW,UAAU,EAAEtH,SAAS,CAACiE,KAAK,CAAC0B,GAAG,CAAC1F,MAAM,EAAE4G,0BAA0B,CAAC;AACnEhC,QAAAA,SAAS,EAAEvC,MAAM,CAACK,KAAK,CAACE,QAAAA;AACxB,OAAA,CAAC,CAAA;MAEF,MAAMsD,QAAQ,CAAC,GAAG,EAAE,GAAGkB,SAAS,CAAA,CAAA,EAAIX,MAAM,CAAA,CAAE,CAAC,CAAA;AAC9C,KAAA;GACA,CAAA;AACF,CAAC;;ACdD,MAAMa,cAAc,GAAGpG,MAAM,CAACC,MAAM,CAAC,CACpCiF,iBAAiB,EACjBe,kBAAkB,EAClB/D,yBAAyB,EACzByD,0BAA0B,CAC1B,CAAC,CAAA;AAEI,SAAUU,WAAWA,CAAClF,MAAmB,EAAA;EAC9C,OAAO,IAAImF,GAAG,CACbF,cAAc,CACZG,GAAG,CAAEC,YAAY,IAAKA,YAAY,CAACrF,MAAM,CAAC,CAAC,CAC3CsF,MAAM,CAAEC,KAAK,IAAKC,OAAO,CAACD,KAAK,CAAC,CAAA;AACjC;AAAA,GACCH,GAAG,CAAEG,KAAK,IAAK,CAACA,KAAK,CAAC3H,IAAI,EAAE2H,KAAK,CAACtC,MAAM,CAAC,CAAC,CAC5C,CAAA;AACF;;AC5BM,MAAOwC,sBAAuB,SAAQ1C,KAAK,CAAA;;ACU1C,MAAM2C,WAAW,GAAG5B,iBAAgB;AACpC,MAAM6B,YAAY,GAAGd,kBAAiB;AAEvC,SAAUe,KAAKA,CAAC5F,MAAmB,EAAA;AAAA,EAAA,IAAA6F,qBAAA,CAAA;AACxC,EAAA,MAAMC,MAAM,GAAGZ,WAAW,CAAClF,MAAM,CAAC,CAAA;EAClC,MAAM+F,aAAa,GAAAF,CAAAA,qBAAA,GAClB7F,MAAM,CAACyB,OAAO,CAACuE,MAAM,KAAA,IAAA,GAAAH,qBAAA,GACnBlE,KAAK,IAAK6D,OAAO,CAAC7D,KAAK,CAACtC,OAAO,CAACQ,GAAG,CAACnB,aAAa,CAAC,CAAE,CAAA;AAEvD,EAAA,OAAO,OAAO;IAAEiD,KAAK;AAAEsE,IAAAA,OAAAA;AAAO,GAAE,KAAI;IACnC,MAAMC,WAAW,GAAGJ,MAAM,CAACjG,GAAG,CAAC8B,KAAK,CAAC0B,GAAG,CAAC8C,QAAQ,CAAC,CAAA;AAElD,IAAA,IAAID,WAAW,EAAE;AAChB,MAAA,MAAMA,WAAW,CAAC;QAAEvE,KAAK;AAAEsE,QAAAA,OAAAA;AAAO,OAAE,CAAC,CAAA;AAErC;AACA,MAAA,MAAMpD,KAAK,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;AAClC,KAAA;AAEA,IAAA,MAAMmD,MAAM,GAAG,MAAMD,aAAa,CAACpE,KAAK,CAAC,CAAA;IAEzC,IAAI,CAACqE,MAAM,EAAE;AACZ,MAAA,MAAMnC,QAAQ,CAAC,GAAG,EAAEC,gBAAgB,CAAC,CAAA;AACtC,KAAA;IAEA,OAAOmC,OAAO,CAACtE,KAAK,CAAC,CAAA;GACrB,CAAA;AACF,CAAA;AAEA;;;;;AAKG;AACI,eAAeyE,qBAAqBA,CAC1CtE,KAA0B,EAC1B9B,MAAyB,EAAA;EAAA,IAAAqG,qBAAA,EAAAC,qBAAA,CAAA;AAEzB,EAAA,MAAMjD,GAAG,GAAAgD,CAAAA,qBAAA,GACRrG,MAAM,CAACK,KAAK,CAACkG,eAAe,KAAAF,IAAAA,GAAAA,qBAAA,GAC5B,CAAGrG,EAAAA,MAAM,CAACK,KAAK,CAACiB,OAAO,CAAmC,iCAAA,CAAA,CAAA;AAE3D,EAAA,MAAMU,QAAQ,GAAG,MAAMF,KAAK,CAACuB,GAAG,EAAE;AACjCnB,IAAAA,OAAO,EAAE;AACRC,MAAAA,MAAM,EAAE,kBAAA;AACR,KAAA;AACD,GAAA,CAAC,CAAA;AAEF,EAAA,IAAI,CAACH,QAAQ,CAACY,EAAE,EAAE;AACjB,IAAA,MAAME,IAAI,GAAG,MAAMd,QAAQ,CAACc,IAAI,EAAE,CAAA;AAClC,IAAA,MAAM,IAAI2C,sBAAsB,CAAC3C,IAAI,CAAC,CAAA;AACvC,GAAA;AAEA,EAAA,MAAMV,IAAI,GAAG,MAAMJ,QAAQ,CAACgB,IAAI,EAAE,CAAA;AAElC,EAAA,OAAO4C,KAAK,CAAC;AACZ,IAAA,GAAG5F,MAAM;AACTK,IAAAA,KAAK,EAAE;MACN,GAAGL,MAAM,CAACK,KAAK;MACfkB,SAAS,EAAEa,IAAI,CAACoE,cAAc;MAC9BtC,aAAa,EAAE9B,IAAI,CAACqE,sBAAsB;MAC1CrG,MAAM,EAAEgC,IAAI,CAAChC,MAAM;MACnBe,OAAO,EAAEiB,IAAI,CAACsE,QAAQ;MACtBhC,UAAU,EAAA,CAAA4B,qBAAA,GAAElE,IAAI,CAACuE,oBAAoB,KAAA,IAAA,GAAAL,qBAAA,GAAI/H,SAAAA;AACzC,KAAA;AACD,GAAA,CAAC,CAAA;AACH,CAAA;AAEM,SAAUqI,qBAAqBA,CAACvH,OAAgB,EAAA;AACrD,EAAA,MAAMuC,MAAM,GAAGjC,SAAS,CAAcN,OAAO,EAAEX,aAAa,CAAC,CAAA;EAC7D8E,gBAAgB,CAAC5B,MAAM,CAAC,CAAA;AACxB,EAAA,OAAOA,MAAM,CAAA;AACd;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/utils/utils.ts","../src/utils/cookie.ts","../src/utils/jwt.ts","../src/routes/redirect-login.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/errors.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type { ArmorTokenExchange } 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","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","import { ArmorConfig } from \"../contracts\";\nimport {\n\tjwtDecrypt,\n\tJWTPayload,\n\tjwtVerify,\n\tJWTVerifyGetKey,\n\tJWTVerifyOptions,\n} from \"jose\";\n\nexport function jwtVerifyAndDecryptIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyAndDecryptToken(\n\t\tconfig,\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}\n\nexport function jwtVerifyAndDecryptAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyAndDecryptToken(\n\t\tconfig,\n\t\tjwks,\n\t\t{ issuer: config.oauth.issuer },\n\t\taccessToken,\n\t);\n}\n\nfunction jwtIsEncryptedToken(token: string): boolean {\n\tconst parts = token.split(\".\");\n\treturn parts.length === 5;\n}\n\nasync function jwtVerifyAndDecryptToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload> {\n\tif (jwtIsEncryptedToken(token)) {\n\t\tconst secret = new TextEncoder().encode(config.oauth.clientSecret);\n\t\tconst { payload } = await jwtDecrypt(token, secret, opts);\n\t\treturn payload;\n\t}\n\n\tconst { payload } = await jwtVerify(token, jwks, opts);\n\treturn payload;\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { strTrimEnd, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange } from \"../utils/utils\";\nimport {\n\tCOOKIE_STATE,\n\tCOOKIE_TOKENS,\n\tcookieGetAndDelete,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport {\n\tjwtVerifyAndDecryptAccessToken,\n\tjwtVerifyAndDecryptIdToken,\n} from \"../utils/jwt\";\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.jwksUrl ??\n\t\t\t`${strTrimEnd(config.oauth.issuer, \"/\")}/.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 sessionLogin =\n\t\tconfig.session?.login ??\n\t\t((event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens));\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 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({\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\t\tcode,\n\t\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t}).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\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\t\t\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\t\t\tif (state !== stateCookie) {\n\t\t\t\tthrow new Error(\"State do not match\");\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\tfetch,\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\tjwtVerifyAndDecryptIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAndDecryptAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tawait sessionLogin(event, {\n\t\t\t\texchange,\n\t\t\t\tidToken: idToken as ArmorIdToken,\n\t\t\t\taccessToken,\n\t\t\t});\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_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\";\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\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});\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 { noop } from \"@nekm/core\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst logout = config.session?.logout ?? noop;\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tawait logout(event);\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\";\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\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tlogout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t});\n\n\t\t\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 routeCreate(config: ArmorConfig): Map<string, Handle> {\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.handle]),\n\t);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends Error {}\n","import { error, redirect, type Handle, Cookies } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { ROUTE_PATH_LOGOUT } from \"./routes/logout\";\nimport { routeCreate } from \"./routes/routes\";\nimport { COOKIE_TOKENS, cookieGet } from \"./utils/cookie\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\n\nexport type { ArmorConfig, ArmorTokens };\n\nexport const ARMOR_LOGIN = ROUTE_PATH_LOGIN;\nexport const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routes = routeCreate(config);\n\tconst sessionExists =\n\t\tconfig.session?.exists ??\n\t\t((event) => Boolean(event.cookies.get(COOKIE_TOKENS)));\n\n\treturn async ({ event, resolve }) => {\n\t\tconst routeHandle = routes.get(event.url.pathname);\n\n\t\tif (routeHandle) {\n\t\t\tawait routeHandle({ event, resolve });\n\n\t\t\t// Handle should redirect. If it doesn't, something is wrong.\n\t\t\tthrow error(500, \"Illegal state\");\n\t\t}\n\n\t\tconst exists = await sessionExists(event);\n\n\t\tif (!exists) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn resolve(event);\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuiration that specifies how to configure.\n * Use that to autoconfigure your instance.\n * @param config\n * @param fetch\n */\nexport async function armorFromOpenIdConfig(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n) {\n\tconst url =\n\t\tconfig.oauth.openIdConfigUrl ??\n\t\t`${config.oauth.baseUrl}/.well-known/openid-configuration`;\n\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(url, {\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 armor({\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\tjwksUrl: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t},\n\t});\n}\n\nexport function armorCookiesGetTokens(cookies: Cookies): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\tthrowIfUndefined(tokens);\n\treturn tokens;\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","jwtVerifyAndDecryptIdToken","config","jwks","idToken","jwtVerifyAndDecryptToken","issuer","oauth","audience","clientId","jwtVerifyAndDecryptAccessToken","accessToken","jwtIsEncryptedToken","token","parts","split","length","opts","secret","TextEncoder","encode","clientSecret","payload","jwtDecrypt","jwtVerify","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksUrl","_config$oauth$tokenEn","_config$session$login","_config$session","jwksUrl","URL","tokenUrl","tokenEndpoint","baseUrl","sessionLogin","session","login","event","tokens","exchangeCodeForToken","fetch","code","response","method","headers","Accept","body","URLSearchParams","grant_type","client_id","client_secret","redirect_uri","toString","ok","error","text","Error","json","handle","_event$url$searchPara","_event$url$searchPara2","state","url","searchParams","stateCookie","throwIfUndefined","exchange","createRemoteJWKSet","Promise","all","redirect","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","params","queryParamsCreate","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","_config$session$logou","logoutEndpoint","logout","noop","ROUTE_PATH_LOGOUT","routeLogoutFactory","logout_uri","routeFactories","routeCreate","Map","map","routeFactory","filter","route","Boolean","ArmorOpenIdConfigError","ARMOR_LOGIN","ARMOR_LOGOUT","armor","_config$session$exist","routes","sessionExists","exists","resolve","routeHandle","pathname","armorFromOpenIdConfig","_config$oauth$openIdC","_body$end_session_end","openIdConfigUrl","fetchToUse","global","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint","armorCookiesGetTokens"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -41,30 +41,41 @@ function cookieGet(cookies, key) {
41
41
  return !value ? undefined : JSON.parse(value);
42
42
  }
43
43
 
44
- function jwtVerifyIdToken(config, jwks, idToken) {
45
- return jwtVerifyToken(jwks, {
44
+ function jwtVerifyAndDecryptIdToken(config, jwks, idToken) {
45
+ return jwtVerifyAndDecryptToken(config, jwks, {
46
46
  issuer: config.oauth.issuer,
47
47
  audience: config.oauth.clientId
48
48
  }, idToken);
49
49
  }
50
- function jwtVerifyAccessToken(config, jwks, accessToken) {
51
- return jwtVerifyToken(jwks, {
50
+ function jwtVerifyAndDecryptAccessToken(config, jwks, accessToken) {
51
+ return jwtVerifyAndDecryptToken(config, jwks, {
52
52
  issuer: config.oauth.issuer
53
53
  }, accessToken);
54
54
  }
55
- async function jwtVerifyToken(jwks, options, token) {
55
+ function jwtIsEncryptedToken(token) {
56
+ const parts = token.split(".");
57
+ return parts.length === 5;
58
+ }
59
+ async function jwtVerifyAndDecryptToken(config, jwks, opts, token) {
60
+ if (jwtIsEncryptedToken(token)) {
61
+ const secret = new TextEncoder().encode(config.oauth.clientSecret);
62
+ const {
63
+ payload
64
+ } = await jose.jwtDecrypt(token, secret, opts);
65
+ return payload;
66
+ }
56
67
  const {
57
68
  payload
58
- } = await jose.jwtVerify(token, jwks, options);
69
+ } = await jose.jwtVerify(token, jwks, opts);
59
70
  return payload;
60
71
  }
61
72
 
62
73
  const ROUTE_PATH_REDIRECT_LOGIN = "/_armor/redirect/login";
63
74
  const routeRedirectLoginFactory = config => {
64
- var _config$oauth$jwksUrl, _config$oauth$tokenPa, _config$session$login;
75
+ var _config$oauth$jwksUrl, _config$oauth$tokenEn, _config$session$login, _config$session;
65
76
  const jwksUrl = new URL((_config$oauth$jwksUrl = config.oauth.jwksUrl) != null ? _config$oauth$jwksUrl : `${core.strTrimEnd(config.oauth.issuer, "/")}/.well-known/jwks.json`);
66
- const tokenUrl = urlConcat(config.oauth.baseUrl, (_config$oauth$tokenPa = config.oauth.tokenPath) != null ? _config$oauth$tokenPa : "oauth2/token");
67
- const sessionLogin = (_config$session$login = config.session.login) != null ? _config$session$login : (event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens);
77
+ const tokenUrl = (_config$oauth$tokenEn = config.oauth.tokenEndpoint) != null ? _config$oauth$tokenEn : urlConcat(config.oauth.baseUrl, "oauth2/token");
78
+ const sessionLogin = (_config$session$login = (_config$session = config.session) == null ? void 0 : _config$session.login) != null ? _config$session$login : (event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens);
68
79
  async function exchangeCodeForToken(fetch, origin, code) {
69
80
  const response = await fetch(tokenUrl, {
70
81
  method: "POST",
@@ -105,7 +116,7 @@ const routeRedirectLoginFactory = config => {
105
116
  core.throwIfUndefined(code);
106
117
  const exchange = await exchangeCodeForToken(fetch, event.url.origin, code);
107
118
  const jwks = jose.createRemoteJWKSet(jwksUrl);
108
- const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, exchange.id_token), jwtVerifyAccessToken(config, jwks, exchange.access_token)]);
119
+ const [idToken, accessToken] = await Promise.all([jwtVerifyAndDecryptIdToken(config, jwks, exchange.id_token), jwtVerifyAndDecryptAccessToken(config, jwks, exchange.access_token)]);
109
120
  await sessionLogin(event, {
110
121
  exchange,
111
122
  idToken: idToken,
@@ -119,7 +130,7 @@ const routeRedirectLoginFactory = config => {
119
130
  const ROUTE_PATH_LOGIN = "/_armor/login";
120
131
  const routeLoginFactory = config => {
121
132
  var _config$oauth$authori;
122
- const authorizeUrl = urlConcat(config.oauth.baseUrl, (_config$oauth$authori = config.oauth.authorizePath) != null ? _config$oauth$authori : "/oauth2/authorize");
133
+ const authorizeEndpoint = (_config$oauth$authori = config.oauth.authorizeEndpoint) != null ? _config$oauth$authori : urlConcat(config.oauth.baseUrl, "oauth2/authorize");
123
134
  return {
124
135
  path: ROUTE_PATH_LOGIN,
125
136
  async handle({
@@ -133,19 +144,19 @@ const routeLoginFactory = config => {
133
144
  redirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),
134
145
  state
135
146
  });
136
- throw kit.redirect(302, `${authorizeUrl}?${params}`);
147
+ throw kit.redirect(302, `${authorizeEndpoint}?${params}`);
137
148
  }
138
149
  };
139
150
  };
140
151
 
141
152
  const ROUTE_PATH_REDIRECT_LOGOUT = "/_armor/redirect/logout";
142
153
  const routeRedirectLogoutFactory = config => {
143
- var _config$session$logou;
154
+ var _config$session$logou, _config$session;
144
155
  // Check if the oauth provider supports a logout path.
145
- if (!config.oauth.logoutPath) {
156
+ if (!config.oauth.logoutEndpoint) {
146
157
  return undefined;
147
158
  }
148
- const logout = (_config$session$logou = config.session.logout) != null ? _config$session$logou : core.noop;
159
+ const logout = (_config$session$logou = (_config$session = config.session) == null ? void 0 : _config$session.logout) != null ? _config$session$logou : core.noop;
149
160
  return {
150
161
  path: ROUTE_PATH_REDIRECT_LOGOUT,
151
162
  async handle({
@@ -160,10 +171,9 @@ const routeRedirectLogoutFactory = config => {
160
171
  const ROUTE_PATH_LOGOUT = "/_armor/logout";
161
172
  const routeLogoutFactory = config => {
162
173
  // Check if the oauth provider supports a logout path.
163
- if (!config.oauth.logoutPath) {
174
+ if (!config.oauth.logoutEndpoint) {
164
175
  return undefined;
165
176
  }
166
- const logoutUrl = urlConcat(config.oauth.baseUrl, config.oauth.logoutPath);
167
177
  return {
168
178
  path: ROUTE_PATH_LOGOUT,
169
179
  async handle({
@@ -173,7 +183,7 @@ const routeLogoutFactory = config => {
173
183
  logout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
174
184
  client_id: config.oauth.clientId
175
185
  });
176
- throw kit.redirect(302, `${logoutUrl}?${params}`);
186
+ throw kit.redirect(302, `${config.oauth.logoutEndpoint}?${params}`);
177
187
  }
178
188
  };
179
189
  };
@@ -190,9 +200,9 @@ class ArmorOpenIdConfigError extends Error {}
190
200
  const ARMOR_LOGIN = ROUTE_PATH_LOGIN;
191
201
  const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;
192
202
  function armor(config) {
193
- var _config$session$exist;
203
+ var _config$session$exist, _config$session;
194
204
  const routes = routeCreate(config);
195
- const sessionExists = (_config$session$exist = config.session.exists) != null ? _config$session$exist : event => Boolean(event.cookies.get(COOKIE_TOKENS));
205
+ const sessionExists = (_config$session$exist = (_config$session = config.session) == null ? void 0 : _config$session.exists) != null ? _config$session$exist : event => Boolean(event.cookies.get(COOKIE_TOKENS));
196
206
  return async ({
197
207
  event,
198
208
  resolve
@@ -216,13 +226,14 @@ function armor(config) {
216
226
  /**
217
227
  * Some IdP's expose a /.well-known/openid-configuiration that specifies how to configure.
218
228
  * Use that to autoconfigure your instance.
219
- * @param fetch
220
229
  * @param config
230
+ * @param fetch
221
231
  */
222
- async function armorFromOpenIdConfig(fetch, config) {
232
+ async function armorFromOpenIdConfig(config, fetch) {
223
233
  var _config$oauth$openIdC, _body$end_session_end;
224
234
  const url = (_config$oauth$openIdC = config.oauth.openIdConfigUrl) != null ? _config$oauth$openIdC : `${config.oauth.baseUrl}/.well-known/openid-configuration`;
225
- const response = await fetch(url, {
235
+ const fetchToUse = fetch != null ? fetch : global.fetch;
236
+ const response = await fetchToUse(url, {
226
237
  headers: {
227
238
  Accept: "application/json"
228
239
  }
@@ -236,11 +247,11 @@ async function armorFromOpenIdConfig(fetch, config) {
236
247
  ...config,
237
248
  oauth: {
238
249
  ...config.oauth,
239
- tokenPath: body.token_endpoint,
240
- authorizePath: body.authorization_endpoint,
250
+ tokenEndpoint: body.token_endpoint,
251
+ authorizeEndpoint: body.authorization_endpoint,
241
252
  issuer: body.issuer,
242
253
  jwksUrl: body.jwks_uri,
243
- logoutPath: (_body$end_session_end = body.end_session_endpoint) != null ? _body$end_session_end : undefined
254
+ logoutEndpoint: (_body$end_session_end = body.end_session_endpoint) != null ? _body$end_session_end : undefined
244
255
  }
245
256
  });
246
257
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils/utils.ts","../src/utils/cookie.ts","../src/utils/jwt.ts","../src/routes/redirect-login.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/errors.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type { ArmorTokenExchange } 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","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","import { ArmorConfig } from \"../contracts\";\nimport { jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n) {\n\treturn 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}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n) {\n\treturn jwtVerifyToken(jwks, { issuer: config.oauth.issuer }, accessToken);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\toptions: JWTVerifyOptions,\n\ttoken: string,\n) {\n\tconst { payload } = await jwtVerify(token, jwks, options);\n\n\treturn payload;\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { strTrimEnd, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange } from \"../utils/utils\";\nimport {\n\tCOOKIE_STATE,\n\tCOOKIE_TOKENS,\n\tcookieGetAndDelete,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"../utils/jwt\";\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.jwksUrl ??\n\t\t\t`${strTrimEnd(config.oauth.issuer, \"/\")}/.well-known/jwks.json`,\n\t);\n\n\tconst tokenUrl = urlConcat(\n\t\tconfig.oauth.baseUrl,\n\t\tconfig.oauth.tokenPath ?? \"oauth2/token\",\n\t);\n\n\tconst sessionLogin =\n\t\tconfig.session.login ??\n\t\t((event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens));\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 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({\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\t\tcode,\n\t\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t}).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\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\t\t\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\t\t\tif (state !== stateCookie) {\n\t\t\t\tthrow new Error(\"State do not match\");\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\tfetch,\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 sessionLogin(event, {\n\t\t\t\texchange,\n\t\t\t\tidToken: idToken as ArmorIdToken,\n\t\t\t\taccessToken,\n\t\t\t});\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_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\";\n\nexport const ROUTE_PATH_LOGIN = \"/_armor/login\";\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeUrl = urlConcat(\n\t\tconfig.oauth.baseUrl,\n\t\tconfig.oauth.authorizePath ?? \"/oauth2/authorize\",\n\t);\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});\n\n\t\t\tthrow redirect(302, `${authorizeUrl}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { noop } from \"@nekm/core\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutPath) {\n\t\treturn undefined;\n\t}\n\n\tconst logout = config.session.logout ?? noop;\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tawait logout(event);\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\";\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.logoutPath) {\n\t\treturn undefined;\n\t}\n\n\tconst logoutUrl = urlConcat(config.oauth.baseUrl, config.oauth.logoutPath);\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tlogout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${logoutUrl}?${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 routeCreate(config: ArmorConfig): Map<string, Handle> {\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.handle]),\n\t);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends Error {}\n","import { error, redirect, type Handle, Cookies } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { ROUTE_PATH_LOGOUT } from \"./routes/logout\";\nimport { routeCreate } from \"./routes/routes\";\nimport { COOKIE_TOKENS, cookieGet } from \"./utils/cookie\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\n\nexport type { ArmorConfig, ArmorTokens };\n\nexport const ARMOR_LOGIN = ROUTE_PATH_LOGIN;\nexport const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routes = routeCreate(config);\n\tconst sessionExists =\n\t\tconfig.session.exists ??\n\t\t((event) => Boolean(event.cookies.get(COOKIE_TOKENS)));\n\n\treturn async ({ event, resolve }) => {\n\t\tconst routeHandle = routes.get(event.url.pathname);\n\n\t\tif (routeHandle) {\n\t\t\tawait routeHandle({ event, resolve });\n\n\t\t\t// Handle should redirect. If it doesn't, something is wrong.\n\t\t\tthrow error(500, \"Illegal state\");\n\t\t}\n\n\t\tconst exists = await sessionExists(event);\n\n\t\tif (!exists) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn resolve(event);\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuiration that specifies how to configure.\n * Use that to autoconfigure your instance.\n * @param fetch\n * @param config\n */\nexport async function armorFromOpenIdConfig(\n\tfetch: typeof global.fetch,\n\tconfig: ArmorOpenIdConfig,\n) {\n\tconst url =\n\t\tconfig.oauth.openIdConfigUrl ??\n\t\t`${config.oauth.baseUrl}/.well-known/openid-configuration`;\n\n\tconst response = await fetch(url, {\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 armor({\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenPath: body.token_endpoint,\n\t\t\tauthorizePath: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksUrl: body.jwks_uri,\n\t\t\tlogoutPath: body.end_session_endpoint ?? undefined,\n\t\t},\n\t});\n}\n\nexport function armorCookiesGetTokens(cookies: Cookies): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\tthrowIfUndefined(tokens);\n\treturn tokens;\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","jwtVerifyIdToken","config","jwks","idToken","jwtVerifyToken","issuer","oauth","audience","clientId","jwtVerifyAccessToken","accessToken","options","token","payload","jwtVerify","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksUrl","_config$oauth$tokenPa","_config$session$login","jwksUrl","URL","tokenUrl","baseUrl","tokenPath","sessionLogin","session","login","event","tokens","exchangeCodeForToken","fetch","code","response","method","headers","Accept","body","URLSearchParams","grant_type","client_id","client_secret","clientSecret","redirect_uri","toString","ok","error","text","Error","json","handle","_event$url$searchPara","_event$url$searchPara2","state","url","searchParams","stateCookie","throwIfUndefined","exchange","createRemoteJWKSet","Promise","all","redirect","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeUrl","authorizePath","randomUUID","params","queryParamsCreate","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","_config$session$logou","logoutPath","logout","noop","ROUTE_PATH_LOGOUT","routeLogoutFactory","logoutUrl","logout_uri","routeFactories","routeCreate","Map","map","routeFactory","filter","route","Boolean","ArmorOpenIdConfigError","ARMOR_LOGIN","ARMOR_LOGOUT","armor","_config$session$exist","routes","sessionExists","exists","resolve","routeHandle","pathname","armorFromOpenIdConfig","_config$oauth$openIdC","_body$end_session_end","openIdConfigUrl","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint","armorCookiesGetTokens"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/utils/utils.ts","../src/utils/cookie.ts","../src/utils/jwt.ts","../src/routes/redirect-login.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/errors.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type { ArmorTokenExchange } 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","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","import { ArmorConfig } from \"../contracts\";\nimport {\n\tjwtDecrypt,\n\tJWTPayload,\n\tjwtVerify,\n\tJWTVerifyGetKey,\n\tJWTVerifyOptions,\n} from \"jose\";\n\nexport function jwtVerifyAndDecryptIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyAndDecryptToken(\n\t\tconfig,\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}\n\nexport function jwtVerifyAndDecryptAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyAndDecryptToken(\n\t\tconfig,\n\t\tjwks,\n\t\t{ issuer: config.oauth.issuer },\n\t\taccessToken,\n\t);\n}\n\nfunction jwtIsEncryptedToken(token: string): boolean {\n\tconst parts = token.split(\".\");\n\treturn parts.length === 5;\n}\n\nasync function jwtVerifyAndDecryptToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload> {\n\tif (jwtIsEncryptedToken(token)) {\n\t\tconst secret = new TextEncoder().encode(config.oauth.clientSecret);\n\t\tconst { payload } = await jwtDecrypt(token, secret, opts);\n\t\treturn payload;\n\t}\n\n\tconst { payload } = await jwtVerify(token, jwks, opts);\n\treturn payload;\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { strTrimEnd, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange } from \"../utils/utils\";\nimport {\n\tCOOKIE_STATE,\n\tCOOKIE_TOKENS,\n\tcookieGetAndDelete,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport {\n\tjwtVerifyAndDecryptAccessToken,\n\tjwtVerifyAndDecryptIdToken,\n} from \"../utils/jwt\";\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.jwksUrl ??\n\t\t\t`${strTrimEnd(config.oauth.issuer, \"/\")}/.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 sessionLogin =\n\t\tconfig.session?.login ??\n\t\t((event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens));\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 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({\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\t\tcode,\n\t\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t}).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\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\t\t\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\t\t\tif (state !== stateCookie) {\n\t\t\t\tthrow new Error(\"State do not match\");\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\tfetch,\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\tjwtVerifyAndDecryptIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAndDecryptAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tawait sessionLogin(event, {\n\t\t\t\texchange,\n\t\t\t\tidToken: idToken as ArmorIdToken,\n\t\t\t\taccessToken,\n\t\t\t});\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_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\";\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\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});\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 { noop } from \"@nekm/core\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst logout = config.session?.logout ?? noop;\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tawait logout(event);\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\";\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\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tlogout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t});\n\n\t\t\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 routeCreate(config: ArmorConfig): Map<string, Handle> {\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.handle]),\n\t);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends Error {}\n","import { error, redirect, type Handle, Cookies } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { ROUTE_PATH_LOGOUT } from \"./routes/logout\";\nimport { routeCreate } from \"./routes/routes\";\nimport { COOKIE_TOKENS, cookieGet } from \"./utils/cookie\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\n\nexport type { ArmorConfig, ArmorTokens };\n\nexport const ARMOR_LOGIN = ROUTE_PATH_LOGIN;\nexport const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routes = routeCreate(config);\n\tconst sessionExists =\n\t\tconfig.session?.exists ??\n\t\t((event) => Boolean(event.cookies.get(COOKIE_TOKENS)));\n\n\treturn async ({ event, resolve }) => {\n\t\tconst routeHandle = routes.get(event.url.pathname);\n\n\t\tif (routeHandle) {\n\t\t\tawait routeHandle({ event, resolve });\n\n\t\t\t// Handle should redirect. If it doesn't, something is wrong.\n\t\t\tthrow error(500, \"Illegal state\");\n\t\t}\n\n\t\tconst exists = await sessionExists(event);\n\n\t\tif (!exists) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn resolve(event);\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuiration that specifies how to configure.\n * Use that to autoconfigure your instance.\n * @param config\n * @param fetch\n */\nexport async function armorFromOpenIdConfig(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n) {\n\tconst url =\n\t\tconfig.oauth.openIdConfigUrl ??\n\t\t`${config.oauth.baseUrl}/.well-known/openid-configuration`;\n\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(url, {\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 armor({\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\tjwksUrl: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t},\n\t});\n}\n\nexport function armorCookiesGetTokens(cookies: Cookies): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\tthrowIfUndefined(tokens);\n\treturn tokens;\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","jwtVerifyAndDecryptIdToken","config","jwks","idToken","jwtVerifyAndDecryptToken","issuer","oauth","audience","clientId","jwtVerifyAndDecryptAccessToken","accessToken","jwtIsEncryptedToken","token","parts","split","length","opts","secret","TextEncoder","encode","clientSecret","payload","jwtDecrypt","jwtVerify","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksUrl","_config$oauth$tokenEn","_config$session$login","_config$session","jwksUrl","URL","tokenUrl","tokenEndpoint","baseUrl","sessionLogin","session","login","event","tokens","exchangeCodeForToken","fetch","code","response","method","headers","Accept","body","URLSearchParams","grant_type","client_id","client_secret","redirect_uri","toString","ok","error","text","Error","json","handle","_event$url$searchPara","_event$url$searchPara2","state","url","searchParams","stateCookie","throwIfUndefined","exchange","createRemoteJWKSet","Promise","all","redirect","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","params","queryParamsCreate","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","_config$session$logou","logoutEndpoint","logout","noop","ROUTE_PATH_LOGOUT","routeLogoutFactory","logout_uri","routeFactories","routeCreate","Map","map","routeFactory","filter","route","Boolean","ArmorOpenIdConfigError","ARMOR_LOGIN","ARMOR_LOGOUT","armor","_config$session$exist","routes","sessionExists","exists","resolve","routeHandle","pathname","armorFromOpenIdConfig","_config$oauth$openIdC","_body$end_session_end","openIdConfigUrl","fetchToUse","global","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint","armorCookiesGetTokens"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import { ArmorConfig } from "../contracts";
2
- import { JWTVerifyGetKey } from "jose";
3
- export declare function jwtVerifyIdToken(config: ArmorConfig, jwks: JWTVerifyGetKey, idToken: string): Promise<import("jose").JWTPayload>;
4
- export declare function jwtVerifyAccessToken(config: ArmorConfig, jwks: JWTVerifyGetKey, accessToken: string): Promise<import("jose").JWTPayload>;
2
+ import { JWTPayload, JWTVerifyGetKey } from "jose";
3
+ export declare function jwtVerifyAndDecryptIdToken(config: ArmorConfig, jwks: JWTVerifyGetKey, idToken: string): Promise<JWTPayload>;
4
+ export declare function jwtVerifyAndDecryptAccessToken(config: ArmorConfig, jwks: JWTVerifyGetKey, accessToken: string): Promise<JWTPayload>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nekm/sveltekit-armor",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Zero-config OAuth protection for SvelteKit",
5
5
  "license": "MIT",
6
6
  "source": "./src/index.ts",
package/src/contracts.ts CHANGED
@@ -35,7 +35,7 @@ interface ArmorCredentials {
35
35
  }
36
36
 
37
37
  export interface ArmorConfig {
38
- readonly session: {
38
+ readonly session?: {
39
39
  readonly exists?: (event: RequestEvent) => Promise<boolean> | boolean;
40
40
  readonly login?: (
41
41
  event: RequestEvent,
@@ -47,9 +47,9 @@ export interface ArmorConfig {
47
47
  readonly baseUrl: string;
48
48
  readonly jwksUrl?: string;
49
49
  readonly issuer: string;
50
- readonly authorizePath?: string;
51
- readonly logoutPath?: string;
52
- readonly tokenPath?: string;
50
+ readonly authorizeEndpoint?: string;
51
+ readonly logoutEndpoint?: string;
52
+ readonly tokenEndpoint?: string;
53
53
  };
54
54
  }
55
55
 
package/src/index.ts CHANGED
@@ -15,7 +15,7 @@ export const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;
15
15
  export function armor(config: ArmorConfig): Handle {
16
16
  const routes = routeCreate(config);
17
17
  const sessionExists =
18
- config.session.exists ??
18
+ config.session?.exists ??
19
19
  ((event) => Boolean(event.cookies.get(COOKIE_TOKENS)));
20
20
 
21
21
  return async ({ event, resolve }) => {
@@ -41,18 +41,20 @@ export function armor(config: ArmorConfig): Handle {
41
41
  /**
42
42
  * Some IdP's expose a /.well-known/openid-configuiration that specifies how to configure.
43
43
  * Use that to autoconfigure your instance.
44
- * @param fetch
45
44
  * @param config
45
+ * @param fetch
46
46
  */
47
47
  export async function armorFromOpenIdConfig(
48
- fetch: typeof global.fetch,
49
48
  config: ArmorOpenIdConfig,
49
+ fetch?: typeof global.fetch,
50
50
  ) {
51
51
  const url =
52
52
  config.oauth.openIdConfigUrl ??
53
53
  `${config.oauth.baseUrl}/.well-known/openid-configuration`;
54
54
 
55
- const response = await fetch(url, {
55
+ const fetchToUse = fetch ?? global.fetch;
56
+
57
+ const response = await fetchToUse(url, {
56
58
  headers: {
57
59
  Accept: "application/json",
58
60
  },
@@ -69,11 +71,11 @@ export async function armorFromOpenIdConfig(
69
71
  ...config,
70
72
  oauth: {
71
73
  ...config.oauth,
72
- tokenPath: body.token_endpoint,
73
- authorizePath: body.authorization_endpoint,
74
+ tokenEndpoint: body.token_endpoint,
75
+ authorizeEndpoint: body.authorization_endpoint,
74
76
  issuer: body.issuer,
75
77
  jwksUrl: body.jwks_uri,
76
- logoutPath: body.end_session_endpoint ?? undefined,
78
+ logoutEndpoint: body.end_session_endpoint ?? undefined,
77
79
  },
78
80
  });
79
81
  }
@@ -10,10 +10,9 @@ import { urlConcat } from "../utils/utils";
10
10
  export const ROUTE_PATH_LOGIN = "/_armor/login";
11
11
 
12
12
  export const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {
13
- const authorizeUrl = urlConcat(
14
- config.oauth.baseUrl,
15
- config.oauth.authorizePath ?? "/oauth2/authorize",
16
- );
13
+ const authorizeEndpoint =
14
+ config.oauth.authorizeEndpoint ??
15
+ urlConcat(config.oauth.baseUrl, "oauth2/authorize");
17
16
 
18
17
  return {
19
18
  path: ROUTE_PATH_LOGIN,
@@ -28,7 +27,7 @@ export const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {
28
27
  state,
29
28
  });
30
29
 
31
- throw redirect(302, `${authorizeUrl}?${params}`);
30
+ throw redirect(302, `${authorizeEndpoint}?${params}`);
32
31
  },
33
32
  };
34
33
  };
@@ -9,12 +9,10 @@ export const ROUTE_PATH_LOGOUT = "/_armor/logout";
9
9
 
10
10
  export const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {
11
11
  // Check if the oauth provider supports a logout path.
12
- if (!config.oauth.logoutPath) {
12
+ if (!config.oauth.logoutEndpoint) {
13
13
  return undefined;
14
14
  }
15
15
 
16
- const logoutUrl = urlConcat(config.oauth.baseUrl, config.oauth.logoutPath);
17
-
18
16
  return {
19
17
  path: ROUTE_PATH_LOGOUT,
20
18
  async handle({ event }) {
@@ -23,7 +21,7 @@ export const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {
23
21
  client_id: config.oauth.clientId,
24
22
  });
25
23
 
26
- throw redirect(302, `${logoutUrl}?${params}`);
24
+ throw redirect(302, `${config.oauth.logoutEndpoint}?${params}`);
27
25
  },
28
26
  };
29
27
  };
@@ -14,7 +14,10 @@ import {
14
14
  cookieGetAndDelete,
15
15
  cookieSet,
16
16
  } from "../utils/cookie";
17
- import { jwtVerifyAccessToken, jwtVerifyIdToken } from "../utils/jwt";
17
+ import {
18
+ jwtVerifyAndDecryptAccessToken,
19
+ jwtVerifyAndDecryptIdToken,
20
+ } from "../utils/jwt";
18
21
 
19
22
  export const ROUTE_PATH_REDIRECT_LOGIN = "/_armor/redirect/login";
20
23
 
@@ -26,13 +29,12 @@ export const routeRedirectLoginFactory: RouteFactory = (
26
29
  `${strTrimEnd(config.oauth.issuer, "/")}/.well-known/jwks.json`,
27
30
  );
28
31
 
29
- const tokenUrl = urlConcat(
30
- config.oauth.baseUrl,
31
- config.oauth.tokenPath ?? "oauth2/token",
32
- );
32
+ const tokenUrl =
33
+ config.oauth.tokenEndpoint ??
34
+ urlConcat(config.oauth.baseUrl, "oauth2/token");
33
35
 
34
36
  const sessionLogin =
35
- config.session.login ??
37
+ config.session?.login ??
36
38
  ((event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens));
37
39
 
38
40
  async function exchangeCodeForToken(
@@ -91,8 +93,8 @@ export const routeRedirectLoginFactory: RouteFactory = (
91
93
  const jwks = createRemoteJWKSet(jwksUrl);
92
94
 
93
95
  const [idToken, accessToken] = await Promise.all([
94
- jwtVerifyIdToken(config, jwks, exchange.id_token),
95
- jwtVerifyAccessToken(config, jwks, exchange.access_token),
96
+ jwtVerifyAndDecryptIdToken(config, jwks, exchange.id_token),
97
+ jwtVerifyAndDecryptAccessToken(config, jwks, exchange.access_token),
96
98
  ]);
97
99
 
98
100
  await sessionLogin(event, {
@@ -9,11 +9,11 @@ export const routeRedirectLogoutFactory: RouteFactory = (
9
9
  config: ArmorConfig,
10
10
  ) => {
11
11
  // Check if the oauth provider supports a logout path.
12
- if (!config.oauth.logoutPath) {
12
+ if (!config.oauth.logoutEndpoint) {
13
13
  return undefined;
14
14
  }
15
15
 
16
- const logout = config.session.logout ?? noop;
16
+ const logout = config.session?.logout ?? noop;
17
17
 
18
18
  return {
19
19
  path: ROUTE_PATH_REDIRECT_LOGOUT,
package/src/utils/jwt.ts CHANGED
@@ -1,12 +1,19 @@
1
1
  import { ArmorConfig } from "../contracts";
2
- import { jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from "jose";
2
+ import {
3
+ jwtDecrypt,
4
+ JWTPayload,
5
+ jwtVerify,
6
+ JWTVerifyGetKey,
7
+ JWTVerifyOptions,
8
+ } from "jose";
3
9
 
4
- export function jwtVerifyIdToken(
10
+ export function jwtVerifyAndDecryptIdToken(
5
11
  config: ArmorConfig,
6
12
  jwks: JWTVerifyGetKey,
7
13
  idToken: string,
8
- ) {
9
- return jwtVerifyToken(
14
+ ): Promise<JWTPayload> {
15
+ return jwtVerifyAndDecryptToken(
16
+ config,
10
17
  jwks,
11
18
  {
12
19
  issuer: config.oauth.issuer,
@@ -16,20 +23,36 @@ export function jwtVerifyIdToken(
16
23
  );
17
24
  }
18
25
 
19
- export function jwtVerifyAccessToken(
26
+ export function jwtVerifyAndDecryptAccessToken(
20
27
  config: ArmorConfig,
21
28
  jwks: JWTVerifyGetKey,
22
29
  accessToken: string,
23
- ) {
24
- return jwtVerifyToken(jwks, { issuer: config.oauth.issuer }, accessToken);
30
+ ): Promise<JWTPayload> {
31
+ return jwtVerifyAndDecryptToken(
32
+ config,
33
+ jwks,
34
+ { issuer: config.oauth.issuer },
35
+ accessToken,
36
+ );
25
37
  }
26
38
 
27
- async function jwtVerifyToken(
39
+ function jwtIsEncryptedToken(token: string): boolean {
40
+ const parts = token.split(".");
41
+ return parts.length === 5;
42
+ }
43
+
44
+ async function jwtVerifyAndDecryptToken(
45
+ config: ArmorConfig,
28
46
  jwks: JWTVerifyGetKey,
29
- options: JWTVerifyOptions,
47
+ opts: JWTVerifyOptions,
30
48
  token: string,
31
- ) {
32
- const { payload } = await jwtVerify(token, jwks, options);
49
+ ): Promise<JWTPayload> {
50
+ if (jwtIsEncryptedToken(token)) {
51
+ const secret = new TextEncoder().encode(config.oauth.clientSecret);
52
+ const { payload } = await jwtDecrypt(token, secret, opts);
53
+ return payload;
54
+ }
33
55
 
56
+ const { payload } = await jwtVerify(token, jwks, opts);
34
57
  return payload;
35
58
  }