@nekm/sveltekit-armor 0.3.8 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contracts.d.ts +8 -1
- package/dist/index.esm.js +46 -13
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +46 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/contracts.ts +14 -1
- package/src/index.ts +1 -0
- package/src/routes/login.ts +7 -3
- package/src/routes/logout.ts +7 -10
- package/src/routes/redirect-login.ts +15 -0
- package/src/routes/redirect-logout.ts +1 -2
- package/src/utils/refresh.ts +8 -1
package/dist/contracts.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ interface OauthEndpoints {
|
|
|
37
37
|
readonly refreshEndpoint: string;
|
|
38
38
|
}
|
|
39
39
|
type OauthEndpointsOrBaseUrl = OauthBaseUrl | OauthEndpoints;
|
|
40
|
+
type LoggerFunction = (message: string, params?: Record<string, unknown>) => void;
|
|
40
41
|
export interface ArmorConfig {
|
|
41
42
|
readonly session: {
|
|
42
43
|
readonly login: (event: RequestEvent, tokens: ArmorTokens) => Promise<void> | void;
|
|
@@ -67,8 +68,14 @@ export interface ArmorConfig {
|
|
|
67
68
|
*/
|
|
68
69
|
readonly errorLoginRedirectPath?: string;
|
|
69
70
|
};
|
|
71
|
+
readonly logger?: {
|
|
72
|
+
readonly debug?: LoggerFunction;
|
|
73
|
+
readonly info?: LoggerFunction;
|
|
74
|
+
readonly warning?: LoggerFunction;
|
|
75
|
+
readonly error?: LoggerFunction;
|
|
76
|
+
};
|
|
70
77
|
}
|
|
71
|
-
export interface ArmorOpenIdConfig extends Pick<ArmorConfig, "session"> {
|
|
78
|
+
export interface ArmorOpenIdConfig extends Pick<ArmorConfig, "session" | "logger"> {
|
|
72
79
|
readonly oauth: Pick<ArmorConfig["oauth"], "clientId" | "clientSecret" | "scope" | "audience" | "logoutReturnToParam" | "errorLoginRedirectPath"> & {
|
|
73
80
|
readonly openIdConfigEndpoint: string;
|
|
74
81
|
};
|
package/dist/index.esm.js
CHANGED
|
@@ -164,12 +164,17 @@ const routeRedirectLoginFactory = config => {
|
|
|
164
164
|
async handle({
|
|
165
165
|
event
|
|
166
166
|
}) {
|
|
167
|
-
var _event$url$searchPara, _event$url$searchPara3;
|
|
167
|
+
var _config$logger, _event$url$searchPara, _event$url$searchPara3, _config$logger3, _config$logger4, _config$logger5;
|
|
168
|
+
(_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Handle login redirect callback.");
|
|
168
169
|
eventStateValidOrThrow(event);
|
|
169
170
|
const error = (_event$url$searchPara = event.url.searchParams.get("error")) != null ? _event$url$searchPara : undefined;
|
|
170
171
|
if (error) {
|
|
171
|
-
var _event$url$searchPara2;
|
|
172
|
+
var _event$url$searchPara2, _config$logger2;
|
|
172
173
|
const error_description = (_event$url$searchPara2 = event.url.searchParams.get("error_description")) != null ? _event$url$searchPara2 : undefined;
|
|
174
|
+
(_config$logger2 = config.logger) == null || _config$logger2.error == null || _config$logger2.error("Login returned error.", {
|
|
175
|
+
error,
|
|
176
|
+
errorDescription: error_description
|
|
177
|
+
});
|
|
173
178
|
if (!config.oauth.errorLoginRedirectPath) {
|
|
174
179
|
return new Response(`${error}\n${error_description}`.trimEnd(), {
|
|
175
180
|
headers: {
|
|
@@ -184,10 +189,20 @@ const routeRedirectLoginFactory = config => {
|
|
|
184
189
|
throw redirect(302, `${config.oauth.errorLoginRedirectPath}?${errorParams}`);
|
|
185
190
|
}
|
|
186
191
|
const code = (_event$url$searchPara3 = event.url.searchParams.get("code")) != null ? _event$url$searchPara3 : undefined;
|
|
192
|
+
(_config$logger3 = config.logger) == null || _config$logger3.debug == null || _config$logger3.debug("Get code from query params.", {
|
|
193
|
+
code
|
|
194
|
+
});
|
|
187
195
|
throwIfUndefined(code);
|
|
188
196
|
const exchange = await exchangeCodeForToken(event.fetch, event.url.origin, code);
|
|
197
|
+
(_config$logger4 = config.logger) == null || _config$logger4.debug == null || _config$logger4.debug("Exchange code for tokens.", {
|
|
198
|
+
exchange
|
|
199
|
+
});
|
|
189
200
|
const jwks = createRemoteJWKSet(jwksUrl);
|
|
190
201
|
const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, exchange.id_token), jwtVerifyAccessToken(config, jwks, exchange.access_token)]);
|
|
202
|
+
(_config$logger5 = config.logger) == null || _config$logger5.debug == null || _config$logger5.debug("Extract and verify tokens.", {
|
|
203
|
+
idToken,
|
|
204
|
+
accessToken
|
|
205
|
+
});
|
|
191
206
|
await config.session.login(event, exchangeToTokens(exchange, idToken, accessToken));
|
|
192
207
|
throw redirect(302, "/");
|
|
193
208
|
}
|
|
@@ -207,17 +222,23 @@ const routeLoginFactory = config => {
|
|
|
207
222
|
async handle({
|
|
208
223
|
event
|
|
209
224
|
}) {
|
|
225
|
+
var _config$logger;
|
|
210
226
|
const state = randomUUID();
|
|
211
227
|
cookieSet(event.cookies, COOKIE_STATE, state);
|
|
212
|
-
const params =
|
|
228
|
+
const params = {
|
|
213
229
|
client_id: config.oauth.clientId,
|
|
214
230
|
response_type: "code",
|
|
215
231
|
redirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),
|
|
216
232
|
state,
|
|
217
233
|
scope,
|
|
218
234
|
audience: config.oauth.audience
|
|
235
|
+
};
|
|
236
|
+
const paramsStr = queryParamsCreate(params);
|
|
237
|
+
(_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Pre login redirect.", {
|
|
238
|
+
params,
|
|
239
|
+
state
|
|
219
240
|
});
|
|
220
|
-
throw redirect(302, `${authorizeEndpoint}?${
|
|
241
|
+
throw redirect(302, `${authorizeEndpoint}?${paramsStr}`);
|
|
221
242
|
}
|
|
222
243
|
};
|
|
223
244
|
};
|
|
@@ -233,7 +254,8 @@ const routeRedirectLogoutFactory = config => {
|
|
|
233
254
|
async handle({
|
|
234
255
|
event
|
|
235
256
|
}) {
|
|
236
|
-
|
|
257
|
+
var _config$logger;
|
|
258
|
+
(_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Handle logout redirect callback.");
|
|
237
259
|
await config.session.logout(event);
|
|
238
260
|
throw redirect(302, "/");
|
|
239
261
|
}
|
|
@@ -250,18 +272,19 @@ const routeLogoutFactory = config => {
|
|
|
250
272
|
const returnTo = (_config$oauth$logoutR = config.oauth.logoutReturnToParam) != null ? _config$oauth$logoutR : "logout_uri";
|
|
251
273
|
return {
|
|
252
274
|
path: ROUTE_PATH_LOGOUT,
|
|
253
|
-
method: "GET",
|
|
254
275
|
async handle({
|
|
255
276
|
event
|
|
256
277
|
}) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const params = queryParamsCreate({
|
|
278
|
+
var _config$logger;
|
|
279
|
+
const params = {
|
|
260
280
|
[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
|
|
261
|
-
client_id: config.oauth.clientId
|
|
262
|
-
|
|
281
|
+
client_id: config.oauth.clientId
|
|
282
|
+
};
|
|
283
|
+
const paramsStr = queryParamsCreate(params);
|
|
284
|
+
(_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Pre logout redirect.", {
|
|
285
|
+
params
|
|
263
286
|
});
|
|
264
|
-
throw redirect(302, `${config.oauth.logoutEndpoint}?${
|
|
287
|
+
throw redirect(302, `${config.oauth.logoutEndpoint}?${paramsStr}`);
|
|
265
288
|
}
|
|
266
289
|
};
|
|
267
290
|
};
|
|
@@ -313,11 +336,19 @@ function armorRefreshFactory(config) {
|
|
|
313
336
|
try {
|
|
314
337
|
let validTokens = tokens;
|
|
315
338
|
if (shouldRefresh(tokens)) {
|
|
316
|
-
|
|
339
|
+
var _config$logger, _config$logger2, _config$logger3;
|
|
340
|
+
(_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Tokens has expired. Refreshing...");
|
|
317
341
|
throwIfUndefined(tokens.exchange.refresh_token);
|
|
318
342
|
const newExchange = await refresh(fetch, tokens.exchange.refresh_token);
|
|
343
|
+
(_config$logger2 = config.logger) == null || _config$logger2.debug == null || _config$logger2.debug("Exchange code for tokens.", {
|
|
344
|
+
newExchange
|
|
345
|
+
});
|
|
319
346
|
const jwks = createRemoteJWKSet(jwksUrl);
|
|
320
347
|
const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, newExchange.id_token), jwtVerifyAccessToken(config, jwks, newExchange.access_token)]);
|
|
348
|
+
(_config$logger3 = config.logger) == null || _config$logger3.debug == null || _config$logger3.debug("Extract and verify tokens.", {
|
|
349
|
+
idToken,
|
|
350
|
+
accessToken
|
|
351
|
+
});
|
|
321
352
|
validTokens = exchangeToTokens(newExchange, idToken, accessToken);
|
|
322
353
|
await config.session.login(event, validTokens);
|
|
323
354
|
}
|
|
@@ -378,6 +409,8 @@ function armor(config) {
|
|
|
378
409
|
}
|
|
379
410
|
const tokens = await config.session.getTokens(event);
|
|
380
411
|
if (!tokens) {
|
|
412
|
+
var _config$logger;
|
|
413
|
+
(_config$logger = config.logger) == null || _config$logger.warning == null || _config$logger.warning("Could not find tokens. Redirecting to login.");
|
|
381
414
|
throw redirect(302, ROUTE_PATH_LOGIN);
|
|
382
415
|
}
|
|
383
416
|
return refresh.ensureValidToken(event, tokens, () => resolve(event));
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/utils/utils.ts","../src/utils/jwt.ts","../src/utils/cookie.ts","../src/errors.ts","../src/utils/event.ts","../src/routes/redirect-login.ts","../src/browser/index.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/utils/refresh.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type {\n\tArmorAccessToken,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n\nconst MINUTES_MS = 60 * 1000;\n\nexport function shouldRefresh(\n\ttokens: Pick<ArmorTokens, \"idToken\" | \"accessToken\">,\n): boolean {\n\tconst idExpiry = tokens.idToken.exp * 1000;\n\n\tconst accessExpiry =\n\t\ttypeof tokens.accessToken !== \"string\" &&\n\t\ttokens.accessToken.exp !== undefined\n\t\t\t? tokens.accessToken.exp * 1000\n\t\t\t: Infinity;\n\n\treturn Math.min(idExpiry, accessExpiry) < Date.now() + 5 * MINUTES_MS;\n}\n\nexport function createExpiresAt(seconds: number): Date {\n\tconst now = new Date();\n\tnow.setSeconds(now.getSeconds() + seconds);\n\treturn now;\n}\n\nexport function exchangeToTokens(\n\texchange: ArmorTokenExchange,\n\tidToken: ArmorIdToken,\n\taccessToken?: ArmorAccessToken,\n): ArmorTokens {\n\treturn {\n\t\texchange,\n\t\tidToken: idToken as ArmorIdToken,\n\t\t// Generally, IdP's require an audience to get a JWT\n\t\t// access token. Most cases, this doesn't matter.\n\t\taccessToken: accessToken ?? exchange.access_token,\n\t\texpiresAt: createExpiresAt(exchange.expires_in),\n\t};\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\nimport { throwIfUndefined } from \"@nekm/core\";\n\nfunction jwtIsCompactJwt(token: string): boolean {\n\t// Must be three base64url segments\n\tconst parts = token.trim().split(\".\");\n\treturn parts.length === 3 && parts.every((p) => p.length > 0);\n}\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\tconst payload = jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n\tthrowIfUndefined(payload);\n\t// @ts-expect-error We're already verifying non-null above.\n\treturn payload;\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload | undefined> {\n\tconst opts: JWTVerifyOptions = { issuer: config.oauth.issuer };\n\n\tif (config.oauth.audience) {\n\t\topts.audience = config.oauth.audience;\n\t}\n\n\treturn jwtVerifyToken(jwks, opts, accessToken);\n}\n\nfunction isInvalidCompactJwt(error: unknown): boolean {\n\treturn Boolean(\n\t\ttypeof error === \"object\" &&\n\t\terror &&\n\t\t\"message\" in error &&\n\t\ttypeof error.message === \"string\" &&\n\t\t/invalid compact jws/gi.test(error.message),\n\t);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload | undefined> {\n\ttry {\n\t\tif (!jwtIsCompactJwt(token)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst { payload } = await jwtVerify(token, jwks, opts);\n\t\treturn payload;\n\t} catch (error) {\n\t\tif (isInvalidCompactJwt(error)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\" as const;\nexport const COOKIE_STATE = \"state\" as const;\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\nexport class ArmorRefreshError extends ArmorError {}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport { COOKIE_STATE, cookieGetAndDelete } from \"./cookie\";\nimport { ArmorInvalidStateError } from \"../errors\";\n\nexport function eventStateValidOrThrow(event: RequestEvent): void {\n\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\tif (state !== stateCookie) {\n\t\tthrow new ArmorInvalidStateError();\n\t}\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { queryParamsCreate, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange, exchangeToTokens } from \"../utils/utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"../utils/jwt\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\n\nexport const ROUTE_PATH_REDIRECT_LOGIN = \"/_armor/redirect/login\";\n\nexport const routeRedirectLoginFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst tokenUrl =\n\t\tconfig.oauth.tokenEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst params: Record<string, string> = {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\tcode,\n\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\tscope,\n\t\t};\n\n\t\tif (config.oauth.audience) {\n\t\t\tparams.audience = config.oauth.audience;\n\t\t}\n\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams(params).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\teventStateValidOrThrow(event);\n\n\t\t\tconst error = event.url.searchParams.get(\"error\") ?? undefined;\n\n\t\t\tif (error) {\n\t\t\t\tconst error_description =\n\t\t\t\t\tevent.url.searchParams.get(\"error_description\") ?? undefined;\n\n\t\t\t\tif (!config.oauth.errorLoginRedirectPath) {\n\t\t\t\t\treturn new Response(`${error}\\n${error_description}`.trimEnd(), {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"text/plain\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst errorParams = queryParamsCreate({ error, error_description });\n\t\t\t\tthrow redirect(\n\t\t\t\t\t302,\n\t\t\t\t\t`${config.oauth.errorLoginRedirectPath}?${errorParams}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst code = event.url.searchParams.get(\"code\") ?? undefined;\n\t\t\tthrowIfUndefined(code);\n\n\t\t\tconst exchange = await exchangeCodeForToken(\n\t\t\t\tevent.fetch,\n\t\t\t\tevent.url.origin,\n\t\t\t\tcode,\n\t\t\t);\n\n\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\tjwtVerifyIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tawait config.session.login(\n\t\t\t\tevent,\n\t\t\t\texchangeToTokens(exchange, idToken as ArmorIdToken, accessToken),\n\t\t\t);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","export const ARMOR_LOGIN = \"/_armor/login\" as const;\nexport const ARMOR_LOGOUT = \"/_armor/logout\" as const;\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGIN } from \"../browser\";\n\nexport const ROUTE_PATH_LOGIN = ARMOR_LOGIN;\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t\tscope,\n\t\t\t\taudience: config.oauth.audience,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\teventStateValidOrThrow(event);\n\n\t\t\tawait config.session.logout(event);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGOUT } from \"./redirect-logout\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat } from \"../utils/utils\";\nimport { randomUUID } from \"node:crypto\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { ARMOR_LOGOUT } from \"../browser\";\n\nexport const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst returnTo = config.oauth.logoutReturnToParam ?? \"logout_uri\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tmethod: \"GET\",\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\t[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tstate,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import type { Handle } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { routeLoginFactory } from \"./login\";\nimport { routeLogoutFactory } from \"./logout\";\nimport { routeRedirectLogoutFactory } from \"./redirect-logout\";\nimport { routeRedirectLoginFactory } from \"./redirect-login\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n]);\n\nexport function routeByPathFactory(config: ArmorConfig): Map<string, Route> {\n\t// @ts-expect-error Incorrect typing error.\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route]),\n\t);\n}\n","import { createRemoteJWKSet } from \"jose\";\nimport {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\nimport { ArmorRefreshError } from \"../errors\";\nimport { exchangeToTokens, shouldRefresh, urlConcat } from \"./utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"./jwt\";\nimport { redirect, RequestEvent } from \"@sveltejs/kit\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ROUTE_PATH_LOGIN } from \"../routes/login\";\n\nexport function armorRefreshFactory(config: ArmorConfig) {\n\tconst refreshEndpoint =\n\t\tconfig.oauth.refreshEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst refresh = async (\n\t\tfetch: typeof global.fetch,\n\t\trefreshToken: string,\n\t): Promise<ArmorTokenExchange> => {\n\t\tconst body = new URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\trefresh_token: refreshToken,\n\t\t});\n\n\t\tif (config.oauth.scope) {\n\t\t\tbody.set(\"scope\", config.oauth.scope);\n\t\t}\n\n\t\tconst response = await fetch(refreshEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: body.toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new ArmorRefreshError(`Could not refresh token: ${error}`);\n\t\t}\n\n\t\tconst json: ArmorTokenExchange = await response.json();\n\n\t\treturn {\n\t\t\t...json,\n\t\t\trefresh_token: json.refresh_token ?? refreshToken,\n\t\t};\n\t};\n\n\treturn {\n\t\trefresh,\n\t\tasync ensureValidToken<T>(\n\t\t\tevent: RequestEvent,\n\t\t\ttokens: ArmorTokens,\n\t\t\tfn: (tokens: ArmorTokens) => T | Promise<T>,\n\t\t): Promise<T> {\n\t\t\ttry {\n\t\t\t\tlet validTokens = tokens;\n\n\t\t\t\tif (shouldRefresh(tokens)) {\n\t\t\t\t\tconsole.log(\"Refreshing tokens...\");\n\n\t\t\t\t\tthrowIfUndefined(tokens.exchange.refresh_token);\n\n\t\t\t\t\tconst newExchange = await refresh(\n\t\t\t\t\t\tfetch,\n\t\t\t\t\t\ttokens.exchange.refresh_token,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\t\t\tjwtVerifyIdToken(config, jwks, newExchange.id_token),\n\t\t\t\t\t\tjwtVerifyAccessToken(config, jwks, newExchange.access_token),\n\t\t\t\t\t]);\n\n\t\t\t\t\tvalidTokens = exchangeToTokens(\n\t\t\t\t\t\tnewExchange,\n\t\t\t\t\t\tidToken as ArmorIdToken,\n\t\t\t\t\t\taccessToken,\n\t\t\t\t\t);\n\n\t\t\t\t\tawait config.session.login(event, validTokens);\n\t\t\t\t}\n\n\t\t\t\treturn fn(validTokens);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof ArmorRefreshError) {\n\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport {\n\tCOOKIE_TOKENS,\n\tcookieDelete,\n\tcookieGet,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport { ArmorConfig, ArmorTokens } from \"../contracts\";\nimport { ArmorAuthMissingError } from \"../errors\";\n\nfunction cookieSessionGetTokens({\n\tcookies,\n}: RequestEvent): ArmorTokens | undefined {\n\treturn cookies.get(COOKIE_TOKENS) as ArmorTokens | undefined;\n}\n\nexport function cookieSessionLogin(\n\t{ cookies }: RequestEvent,\n\ttokens: ArmorTokens,\n): void {\n\tcookieSet(cookies, COOKIE_TOKENS, tokens);\n}\n\nfunction cookieSessionLogout({ cookies }: RequestEvent): void {\n\tcookieDelete(cookies, COOKIE_TOKENS);\n}\n\nexport function armorCookieSessionGet({ cookies }: RequestEvent): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\n\tif (!tokens) {\n\t\tthrow new ArmorAuthMissingError();\n\t}\n\n\treturn tokens;\n}\n\nexport const armorCookieSession: ArmorConfig[\"session\"] = {\n\tgetTokens: cookieSessionGetTokens,\n\tlogin: cookieSessionLogin,\n\tlogout: cookieSessionLogout,\n};\n","import { redirect, type Handle } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { routeByPathFactory } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\nimport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\nexport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routeByPath = routeByPathFactory(config);\n\tconst refresh = armorRefreshFactory(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst route = routeByPath.get(event.url.pathname);\n\n\t\tif (route) {\n\t\t\treturn route.handle({ event, resolve });\n\t\t}\n\n\t\tconst tokens = await config.session.getTokens(event);\n\n\t\tif (!tokens) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn refresh.ensureValidToken(event, tokens, () => resolve(event));\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.\n * Use that to create your config.\n * @param config\n * @param fetch\n */\nexport async function armorConfigFromOpenId(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n): Promise<ArmorConfig> {\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(config.oauth.openIdConfigEndpoint, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn {\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksEndpoint: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t\trefreshEndpoint: body.token_endpoint,\n\t\t},\n\t};\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","MINUTES_MS","shouldRefresh","tokens","idExpiry","idToken","exp","accessExpiry","accessToken","Infinity","Math","min","Date","now","createExpiresAt","seconds","setSeconds","getSeconds","exchangeToTokens","exchange","expiresAt","jwtIsCompactJwt","token","parts","trim","split","length","every","p","jwtVerifyIdToken","config","jwks","payload","jwtVerifyToken","issuer","oauth","audience","clientId","throwIfUndefined","jwtVerifyAccessToken","opts","isInvalidCompactJwt","error","Boolean","message","test","jwtVerify","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","cookieDelete","ArmorError","Error","ArmorOpenIdConfigError","ArmorInvalidStateError","ArmorAuthMissingError","ArmorRefreshError","eventStateValidOrThrow","event","_event$url$searchPara","state","url","searchParams","stateCookie","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksEnd","_config$oauth$tokenEn","_config$oauth$scope","jwksUrl","URL","jwksEndpoint","baseUrl","tokenUrl","tokenEndpoint","exchangeCodeForToken","fetch","code","params","grant_type","client_id","client_secret","clientSecret","redirect_uri","response","method","headers","Accept","body","URLSearchParams","toString","ok","text","json","handle","_event$url$searchPara3","_event$url$searchPara2","error_description","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","createRemoteJWKSet","Promise","all","session","login","ARMOR_LOGIN","ARMOR_LOGOUT","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","routeFactories","routeByPathFactory","Map","map","routeFactory","filter","route","armorRefreshFactory","_config$oauth$refresh","refreshEndpoint","refresh","refreshToken","_json$refresh_token","ensureValidToken","fn","validTokens","console","log","newExchange","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","getTokens","armor","routeByPath","resolve","pathname","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/utils/utils.ts","../src/utils/jwt.ts","../src/utils/cookie.ts","../src/errors.ts","../src/utils/event.ts","../src/routes/redirect-login.ts","../src/browser/index.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/utils/refresh.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type {\n\tArmorAccessToken,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n\nconst MINUTES_MS = 60 * 1000;\n\nexport function shouldRefresh(\n\ttokens: Pick<ArmorTokens, \"idToken\" | \"accessToken\">,\n): boolean {\n\tconst idExpiry = tokens.idToken.exp * 1000;\n\n\tconst accessExpiry =\n\t\ttypeof tokens.accessToken !== \"string\" &&\n\t\ttokens.accessToken.exp !== undefined\n\t\t\t? tokens.accessToken.exp * 1000\n\t\t\t: Infinity;\n\n\treturn Math.min(idExpiry, accessExpiry) < Date.now() + 5 * MINUTES_MS;\n}\n\nexport function createExpiresAt(seconds: number): Date {\n\tconst now = new Date();\n\tnow.setSeconds(now.getSeconds() + seconds);\n\treturn now;\n}\n\nexport function exchangeToTokens(\n\texchange: ArmorTokenExchange,\n\tidToken: ArmorIdToken,\n\taccessToken?: ArmorAccessToken,\n): ArmorTokens {\n\treturn {\n\t\texchange,\n\t\tidToken: idToken as ArmorIdToken,\n\t\t// Generally, IdP's require an audience to get a JWT\n\t\t// access token. Most cases, this doesn't matter.\n\t\taccessToken: accessToken ?? exchange.access_token,\n\t\texpiresAt: createExpiresAt(exchange.expires_in),\n\t};\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\nimport { throwIfUndefined } from \"@nekm/core\";\n\nfunction jwtIsCompactJwt(token: string): boolean {\n\t// Must be three base64url segments\n\tconst parts = token.trim().split(\".\");\n\treturn parts.length === 3 && parts.every((p) => p.length > 0);\n}\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\tconst payload = jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n\tthrowIfUndefined(payload);\n\t// @ts-expect-error We're already verifying non-null above.\n\treturn payload;\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload | undefined> {\n\tconst opts: JWTVerifyOptions = { issuer: config.oauth.issuer };\n\n\tif (config.oauth.audience) {\n\t\topts.audience = config.oauth.audience;\n\t}\n\n\treturn jwtVerifyToken(jwks, opts, accessToken);\n}\n\nfunction isInvalidCompactJwt(error: unknown): boolean {\n\treturn Boolean(\n\t\ttypeof error === \"object\" &&\n\t\terror &&\n\t\t\"message\" in error &&\n\t\ttypeof error.message === \"string\" &&\n\t\t/invalid compact jws/gi.test(error.message),\n\t);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload | undefined> {\n\ttry {\n\t\tif (!jwtIsCompactJwt(token)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst { payload } = await jwtVerify(token, jwks, opts);\n\t\treturn payload;\n\t} catch (error) {\n\t\tif (isInvalidCompactJwt(error)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\" as const;\nexport const COOKIE_STATE = \"state\" as const;\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\nexport class ArmorRefreshError extends ArmorError {}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport { COOKIE_STATE, cookieGetAndDelete } from \"./cookie\";\nimport { ArmorInvalidStateError } from \"../errors\";\n\nexport function eventStateValidOrThrow(event: RequestEvent): void {\n\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\tif (state !== stateCookie) {\n\t\tthrow new ArmorInvalidStateError();\n\t}\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { queryParamsCreate, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange, exchangeToTokens } from \"../utils/utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"../utils/jwt\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\n\nexport const ROUTE_PATH_REDIRECT_LOGIN = \"/_armor/redirect/login\";\n\nexport const routeRedirectLoginFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst tokenUrl =\n\t\tconfig.oauth.tokenEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst params: Record<string, string> = {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\tcode,\n\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\tscope,\n\t\t};\n\n\t\tif (config.oauth.audience) {\n\t\t\tparams.audience = config.oauth.audience;\n\t\t}\n\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams(params).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle login redirect callback.\");\n\n\t\t\teventStateValidOrThrow(event);\n\n\t\t\tconst error = event.url.searchParams.get(\"error\") ?? undefined;\n\n\t\t\tif (error) {\n\t\t\t\tconst error_description =\n\t\t\t\t\tevent.url.searchParams.get(\"error_description\") ?? undefined;\n\n\t\t\t\tconfig.logger?.error?.(\"Login returned error.\", {\n\t\t\t\t\terror,\n\t\t\t\t\terrorDescription: error_description,\n\t\t\t\t});\n\n\t\t\t\tif (!config.oauth.errorLoginRedirectPath) {\n\t\t\t\t\treturn new Response(`${error}\\n${error_description}`.trimEnd(), {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"text/plain\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst errorParams = queryParamsCreate({ error, error_description });\n\t\t\t\tthrow redirect(\n\t\t\t\t\t302,\n\t\t\t\t\t`${config.oauth.errorLoginRedirectPath}?${errorParams}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst code = event.url.searchParams.get(\"code\") ?? undefined;\n\t\t\tconfig.logger?.debug?.(\"Get code from query params.\", { code });\n\t\t\tthrowIfUndefined(code);\n\n\t\t\tconst exchange = await exchangeCodeForToken(\n\t\t\t\tevent.fetch,\n\t\t\t\tevent.url.origin,\n\t\t\t\tcode,\n\t\t\t);\n\n\t\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { exchange });\n\n\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\tjwtVerifyIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\t\tidToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tawait config.session.login(\n\t\t\t\tevent,\n\t\t\t\texchangeToTokens(exchange, idToken as ArmorIdToken, accessToken),\n\t\t\t);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","export const ARMOR_LOGIN = \"/_armor/login\" as const;\nexport const ARMOR_LOGOUT = \"/_armor/logout\" as const;\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGIN } from \"../browser\";\n\nexport const ROUTE_PATH_LOGIN = ARMOR_LOGIN;\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = {\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t\tscope,\n\t\t\t\taudience: config.oauth.audience,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre login redirect.\", { params, state });\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle logout redirect callback.\");\n\n\t\t\tawait config.session.logout(event);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGOUT } from \"./redirect-logout\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGOUT } from \"../browser\";\n\nexport const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst returnTo = config.oauth.logoutReturnToParam ?? \"logout_uri\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = {\n\t\t\t\t[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre logout redirect.\", { params });\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import type { Handle } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { routeLoginFactory } from \"./login\";\nimport { routeLogoutFactory } from \"./logout\";\nimport { routeRedirectLogoutFactory } from \"./redirect-logout\";\nimport { routeRedirectLoginFactory } from \"./redirect-login\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n]);\n\nexport function routeByPathFactory(config: ArmorConfig): Map<string, Route> {\n\t// @ts-expect-error Incorrect typing error.\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route]),\n\t);\n}\n","import { createRemoteJWKSet } from \"jose\";\nimport {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\nimport { ArmorRefreshError } from \"../errors\";\nimport { exchangeToTokens, shouldRefresh, urlConcat } from \"./utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"./jwt\";\nimport { redirect, RequestEvent } from \"@sveltejs/kit\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ROUTE_PATH_LOGIN } from \"../routes/login\";\n\nexport function armorRefreshFactory(config: ArmorConfig) {\n\tconst refreshEndpoint =\n\t\tconfig.oauth.refreshEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst refresh = async (\n\t\tfetch: typeof global.fetch,\n\t\trefreshToken: string,\n\t): Promise<ArmorTokenExchange> => {\n\t\tconst body = new URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\trefresh_token: refreshToken,\n\t\t});\n\n\t\tif (config.oauth.scope) {\n\t\t\tbody.set(\"scope\", config.oauth.scope);\n\t\t}\n\n\t\tconst response = await fetch(refreshEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: body.toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new ArmorRefreshError(`Could not refresh token: ${error}`);\n\t\t}\n\n\t\tconst json: ArmorTokenExchange = await response.json();\n\n\t\treturn {\n\t\t\t...json,\n\t\t\trefresh_token: json.refresh_token ?? refreshToken,\n\t\t};\n\t};\n\n\treturn {\n\t\trefresh,\n\t\tasync ensureValidToken<T>(\n\t\t\tevent: RequestEvent,\n\t\t\ttokens: ArmorTokens,\n\t\t\tfn: (tokens: ArmorTokens) => T | Promise<T>,\n\t\t): Promise<T> {\n\t\t\ttry {\n\t\t\t\tlet validTokens = tokens;\n\n\t\t\t\tif (shouldRefresh(tokens)) {\n\t\t\t\t\tconfig.logger?.debug?.(\"Tokens has expired. Refreshing...\");\n\n\t\t\t\t\tthrowIfUndefined(tokens.exchange.refresh_token);\n\n\t\t\t\t\tconst newExchange = await refresh(\n\t\t\t\t\t\tfetch,\n\t\t\t\t\t\ttokens.exchange.refresh_token,\n\t\t\t\t\t);\n\n\t\t\t\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { newExchange });\n\n\t\t\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\t\t\tjwtVerifyIdToken(config, jwks, newExchange.id_token),\n\t\t\t\t\t\tjwtVerifyAccessToken(config, jwks, newExchange.access_token),\n\t\t\t\t\t]);\n\n\t\t\t\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\t\t\t\tidToken,\n\t\t\t\t\t\taccessToken,\n\t\t\t\t\t});\n\n\t\t\t\t\tvalidTokens = exchangeToTokens(\n\t\t\t\t\t\tnewExchange,\n\t\t\t\t\t\tidToken as ArmorIdToken,\n\t\t\t\t\t\taccessToken,\n\t\t\t\t\t);\n\n\t\t\t\t\tawait config.session.login(event, validTokens);\n\t\t\t\t}\n\n\t\t\t\treturn fn(validTokens);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof ArmorRefreshError) {\n\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport {\n\tCOOKIE_TOKENS,\n\tcookieDelete,\n\tcookieGet,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport { ArmorConfig, ArmorTokens } from \"../contracts\";\nimport { ArmorAuthMissingError } from \"../errors\";\n\nfunction cookieSessionGetTokens({\n\tcookies,\n}: RequestEvent): ArmorTokens | undefined {\n\treturn cookies.get(COOKIE_TOKENS) as ArmorTokens | undefined;\n}\n\nexport function cookieSessionLogin(\n\t{ cookies }: RequestEvent,\n\ttokens: ArmorTokens,\n): void {\n\tcookieSet(cookies, COOKIE_TOKENS, tokens);\n}\n\nfunction cookieSessionLogout({ cookies }: RequestEvent): void {\n\tcookieDelete(cookies, COOKIE_TOKENS);\n}\n\nexport function armorCookieSessionGet({ cookies }: RequestEvent): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\n\tif (!tokens) {\n\t\tthrow new ArmorAuthMissingError();\n\t}\n\n\treturn tokens;\n}\n\nexport const armorCookieSession: ArmorConfig[\"session\"] = {\n\tgetTokens: cookieSessionGetTokens,\n\tlogin: cookieSessionLogin,\n\tlogout: cookieSessionLogout,\n};\n","import { redirect, type Handle } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { routeByPathFactory } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\nimport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\nexport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routeByPath = routeByPathFactory(config);\n\tconst refresh = armorRefreshFactory(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst route = routeByPath.get(event.url.pathname);\n\n\t\tif (route) {\n\t\t\treturn route.handle({ event, resolve });\n\t\t}\n\n\t\tconst tokens = await config.session.getTokens(event);\n\n\t\tif (!tokens) {\n\t\t\tconfig.logger?.warning?.(\"Could not find tokens. Redirecting to login.\");\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn refresh.ensureValidToken(event, tokens, () => resolve(event));\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.\n * Use that to create your config.\n * @param config\n * @param fetch\n */\nexport async function armorConfigFromOpenId(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n): Promise<ArmorConfig> {\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(config.oauth.openIdConfigEndpoint, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn {\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksEndpoint: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t\trefreshEndpoint: body.token_endpoint,\n\t\t},\n\t};\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","MINUTES_MS","shouldRefresh","tokens","idExpiry","idToken","exp","accessExpiry","accessToken","Infinity","Math","min","Date","now","createExpiresAt","seconds","setSeconds","getSeconds","exchangeToTokens","exchange","expiresAt","jwtIsCompactJwt","token","parts","trim","split","length","every","p","jwtVerifyIdToken","config","jwks","payload","jwtVerifyToken","issuer","oauth","audience","clientId","throwIfUndefined","jwtVerifyAccessToken","opts","isInvalidCompactJwt","error","Boolean","message","test","jwtVerify","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","cookieDelete","ArmorError","Error","ArmorOpenIdConfigError","ArmorInvalidStateError","ArmorAuthMissingError","ArmorRefreshError","eventStateValidOrThrow","event","_event$url$searchPara","state","url","searchParams","stateCookie","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksEnd","_config$oauth$tokenEn","_config$oauth$scope","jwksUrl","URL","jwksEndpoint","baseUrl","tokenUrl","tokenEndpoint","exchangeCodeForToken","fetch","code","params","grant_type","client_id","client_secret","clientSecret","redirect_uri","response","method","headers","Accept","body","URLSearchParams","toString","ok","text","json","handle","_config$logger","_event$url$searchPara3","_config$logger3","_config$logger4","_config$logger5","logger","debug","_event$url$searchPara2","_config$logger2","error_description","errorDescription","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","createRemoteJWKSet","Promise","all","session","login","ARMOR_LOGIN","ARMOR_LOGOUT","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","paramsStr","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","routeFactories","routeByPathFactory","Map","map","routeFactory","filter","route","armorRefreshFactory","_config$oauth$refresh","refreshEndpoint","refresh","refreshToken","_json$refresh_token","ensureValidToken","fn","validTokens","newExchange","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","getTokens","armor","routeByPath","resolve","pathname","warning","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -164,12 +164,17 @@ const routeRedirectLoginFactory = config => {
|
|
|
164
164
|
async handle({
|
|
165
165
|
event
|
|
166
166
|
}) {
|
|
167
|
-
var _event$url$searchPara, _event$url$searchPara3;
|
|
167
|
+
var _config$logger, _event$url$searchPara, _event$url$searchPara3, _config$logger3, _config$logger4, _config$logger5;
|
|
168
|
+
(_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Handle login redirect callback.");
|
|
168
169
|
eventStateValidOrThrow(event);
|
|
169
170
|
const error = (_event$url$searchPara = event.url.searchParams.get("error")) != null ? _event$url$searchPara : undefined;
|
|
170
171
|
if (error) {
|
|
171
|
-
var _event$url$searchPara2;
|
|
172
|
+
var _event$url$searchPara2, _config$logger2;
|
|
172
173
|
const error_description = (_event$url$searchPara2 = event.url.searchParams.get("error_description")) != null ? _event$url$searchPara2 : undefined;
|
|
174
|
+
(_config$logger2 = config.logger) == null || _config$logger2.error == null || _config$logger2.error("Login returned error.", {
|
|
175
|
+
error,
|
|
176
|
+
errorDescription: error_description
|
|
177
|
+
});
|
|
173
178
|
if (!config.oauth.errorLoginRedirectPath) {
|
|
174
179
|
return new Response(`${error}\n${error_description}`.trimEnd(), {
|
|
175
180
|
headers: {
|
|
@@ -184,10 +189,20 @@ const routeRedirectLoginFactory = config => {
|
|
|
184
189
|
throw kit.redirect(302, `${config.oauth.errorLoginRedirectPath}?${errorParams}`);
|
|
185
190
|
}
|
|
186
191
|
const code = (_event$url$searchPara3 = event.url.searchParams.get("code")) != null ? _event$url$searchPara3 : undefined;
|
|
192
|
+
(_config$logger3 = config.logger) == null || _config$logger3.debug == null || _config$logger3.debug("Get code from query params.", {
|
|
193
|
+
code
|
|
194
|
+
});
|
|
187
195
|
core.throwIfUndefined(code);
|
|
188
196
|
const exchange = await exchangeCodeForToken(event.fetch, event.url.origin, code);
|
|
197
|
+
(_config$logger4 = config.logger) == null || _config$logger4.debug == null || _config$logger4.debug("Exchange code for tokens.", {
|
|
198
|
+
exchange
|
|
199
|
+
});
|
|
189
200
|
const jwks = jose.createRemoteJWKSet(jwksUrl);
|
|
190
201
|
const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, exchange.id_token), jwtVerifyAccessToken(config, jwks, exchange.access_token)]);
|
|
202
|
+
(_config$logger5 = config.logger) == null || _config$logger5.debug == null || _config$logger5.debug("Extract and verify tokens.", {
|
|
203
|
+
idToken,
|
|
204
|
+
accessToken
|
|
205
|
+
});
|
|
191
206
|
await config.session.login(event, exchangeToTokens(exchange, idToken, accessToken));
|
|
192
207
|
throw kit.redirect(302, "/");
|
|
193
208
|
}
|
|
@@ -207,17 +222,23 @@ const routeLoginFactory = config => {
|
|
|
207
222
|
async handle({
|
|
208
223
|
event
|
|
209
224
|
}) {
|
|
225
|
+
var _config$logger;
|
|
210
226
|
const state = node_crypto.randomUUID();
|
|
211
227
|
cookieSet(event.cookies, COOKIE_STATE, state);
|
|
212
|
-
const params =
|
|
228
|
+
const params = {
|
|
213
229
|
client_id: config.oauth.clientId,
|
|
214
230
|
response_type: "code",
|
|
215
231
|
redirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),
|
|
216
232
|
state,
|
|
217
233
|
scope,
|
|
218
234
|
audience: config.oauth.audience
|
|
235
|
+
};
|
|
236
|
+
const paramsStr = core.queryParamsCreate(params);
|
|
237
|
+
(_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Pre login redirect.", {
|
|
238
|
+
params,
|
|
239
|
+
state
|
|
219
240
|
});
|
|
220
|
-
throw kit.redirect(302, `${authorizeEndpoint}?${
|
|
241
|
+
throw kit.redirect(302, `${authorizeEndpoint}?${paramsStr}`);
|
|
221
242
|
}
|
|
222
243
|
};
|
|
223
244
|
};
|
|
@@ -233,7 +254,8 @@ const routeRedirectLogoutFactory = config => {
|
|
|
233
254
|
async handle({
|
|
234
255
|
event
|
|
235
256
|
}) {
|
|
236
|
-
|
|
257
|
+
var _config$logger;
|
|
258
|
+
(_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Handle logout redirect callback.");
|
|
237
259
|
await config.session.logout(event);
|
|
238
260
|
throw kit.redirect(302, "/");
|
|
239
261
|
}
|
|
@@ -250,18 +272,19 @@ const routeLogoutFactory = config => {
|
|
|
250
272
|
const returnTo = (_config$oauth$logoutR = config.oauth.logoutReturnToParam) != null ? _config$oauth$logoutR : "logout_uri";
|
|
251
273
|
return {
|
|
252
274
|
path: ROUTE_PATH_LOGOUT,
|
|
253
|
-
method: "GET",
|
|
254
275
|
async handle({
|
|
255
276
|
event
|
|
256
277
|
}) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const params = core.queryParamsCreate({
|
|
278
|
+
var _config$logger;
|
|
279
|
+
const params = {
|
|
260
280
|
[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
|
|
261
|
-
client_id: config.oauth.clientId
|
|
262
|
-
|
|
281
|
+
client_id: config.oauth.clientId
|
|
282
|
+
};
|
|
283
|
+
const paramsStr = core.queryParamsCreate(params);
|
|
284
|
+
(_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Pre logout redirect.", {
|
|
285
|
+
params
|
|
263
286
|
});
|
|
264
|
-
throw kit.redirect(302, `${config.oauth.logoutEndpoint}?${
|
|
287
|
+
throw kit.redirect(302, `${config.oauth.logoutEndpoint}?${paramsStr}`);
|
|
265
288
|
}
|
|
266
289
|
};
|
|
267
290
|
};
|
|
@@ -313,11 +336,19 @@ function armorRefreshFactory(config) {
|
|
|
313
336
|
try {
|
|
314
337
|
let validTokens = tokens;
|
|
315
338
|
if (shouldRefresh(tokens)) {
|
|
316
|
-
|
|
339
|
+
var _config$logger, _config$logger2, _config$logger3;
|
|
340
|
+
(_config$logger = config.logger) == null || _config$logger.debug == null || _config$logger.debug("Tokens has expired. Refreshing...");
|
|
317
341
|
core.throwIfUndefined(tokens.exchange.refresh_token);
|
|
318
342
|
const newExchange = await refresh(fetch, tokens.exchange.refresh_token);
|
|
343
|
+
(_config$logger2 = config.logger) == null || _config$logger2.debug == null || _config$logger2.debug("Exchange code for tokens.", {
|
|
344
|
+
newExchange
|
|
345
|
+
});
|
|
319
346
|
const jwks = jose.createRemoteJWKSet(jwksUrl);
|
|
320
347
|
const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, newExchange.id_token), jwtVerifyAccessToken(config, jwks, newExchange.access_token)]);
|
|
348
|
+
(_config$logger3 = config.logger) == null || _config$logger3.debug == null || _config$logger3.debug("Extract and verify tokens.", {
|
|
349
|
+
idToken,
|
|
350
|
+
accessToken
|
|
351
|
+
});
|
|
321
352
|
validTokens = exchangeToTokens(newExchange, idToken, accessToken);
|
|
322
353
|
await config.session.login(event, validTokens);
|
|
323
354
|
}
|
|
@@ -378,6 +409,8 @@ function armor(config) {
|
|
|
378
409
|
}
|
|
379
410
|
const tokens = await config.session.getTokens(event);
|
|
380
411
|
if (!tokens) {
|
|
412
|
+
var _config$logger;
|
|
413
|
+
(_config$logger = config.logger) == null || _config$logger.warning == null || _config$logger.warning("Could not find tokens. Redirecting to login.");
|
|
381
414
|
throw kit.redirect(302, ROUTE_PATH_LOGIN);
|
|
382
415
|
}
|
|
383
416
|
return refresh.ensureValidToken(event, tokens, () => resolve(event));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/utils/utils.ts","../src/utils/jwt.ts","../src/utils/cookie.ts","../src/errors.ts","../src/utils/event.ts","../src/routes/redirect-login.ts","../src/browser/index.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/utils/refresh.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type {\n\tArmorAccessToken,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n\nconst MINUTES_MS = 60 * 1000;\n\nexport function shouldRefresh(\n\ttokens: Pick<ArmorTokens, \"idToken\" | \"accessToken\">,\n): boolean {\n\tconst idExpiry = tokens.idToken.exp * 1000;\n\n\tconst accessExpiry =\n\t\ttypeof tokens.accessToken !== \"string\" &&\n\t\ttokens.accessToken.exp !== undefined\n\t\t\t? tokens.accessToken.exp * 1000\n\t\t\t: Infinity;\n\n\treturn Math.min(idExpiry, accessExpiry) < Date.now() + 5 * MINUTES_MS;\n}\n\nexport function createExpiresAt(seconds: number): Date {\n\tconst now = new Date();\n\tnow.setSeconds(now.getSeconds() + seconds);\n\treturn now;\n}\n\nexport function exchangeToTokens(\n\texchange: ArmorTokenExchange,\n\tidToken: ArmorIdToken,\n\taccessToken?: ArmorAccessToken,\n): ArmorTokens {\n\treturn {\n\t\texchange,\n\t\tidToken: idToken as ArmorIdToken,\n\t\t// Generally, IdP's require an audience to get a JWT\n\t\t// access token. Most cases, this doesn't matter.\n\t\taccessToken: accessToken ?? exchange.access_token,\n\t\texpiresAt: createExpiresAt(exchange.expires_in),\n\t};\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\nimport { throwIfUndefined } from \"@nekm/core\";\n\nfunction jwtIsCompactJwt(token: string): boolean {\n\t// Must be three base64url segments\n\tconst parts = token.trim().split(\".\");\n\treturn parts.length === 3 && parts.every((p) => p.length > 0);\n}\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\tconst payload = jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n\tthrowIfUndefined(payload);\n\t// @ts-expect-error We're already verifying non-null above.\n\treturn payload;\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload | undefined> {\n\tconst opts: JWTVerifyOptions = { issuer: config.oauth.issuer };\n\n\tif (config.oauth.audience) {\n\t\topts.audience = config.oauth.audience;\n\t}\n\n\treturn jwtVerifyToken(jwks, opts, accessToken);\n}\n\nfunction isInvalidCompactJwt(error: unknown): boolean {\n\treturn Boolean(\n\t\ttypeof error === \"object\" &&\n\t\terror &&\n\t\t\"message\" in error &&\n\t\ttypeof error.message === \"string\" &&\n\t\t/invalid compact jws/gi.test(error.message),\n\t);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload | undefined> {\n\ttry {\n\t\tif (!jwtIsCompactJwt(token)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst { payload } = await jwtVerify(token, jwks, opts);\n\t\treturn payload;\n\t} catch (error) {\n\t\tif (isInvalidCompactJwt(error)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\" as const;\nexport const COOKIE_STATE = \"state\" as const;\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\nexport class ArmorRefreshError extends ArmorError {}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport { COOKIE_STATE, cookieGetAndDelete } from \"./cookie\";\nimport { ArmorInvalidStateError } from \"../errors\";\n\nexport function eventStateValidOrThrow(event: RequestEvent): void {\n\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\tif (state !== stateCookie) {\n\t\tthrow new ArmorInvalidStateError();\n\t}\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { queryParamsCreate, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange, exchangeToTokens } from \"../utils/utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"../utils/jwt\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\n\nexport const ROUTE_PATH_REDIRECT_LOGIN = \"/_armor/redirect/login\";\n\nexport const routeRedirectLoginFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst tokenUrl =\n\t\tconfig.oauth.tokenEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst params: Record<string, string> = {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\tcode,\n\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\tscope,\n\t\t};\n\n\t\tif (config.oauth.audience) {\n\t\t\tparams.audience = config.oauth.audience;\n\t\t}\n\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams(params).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\teventStateValidOrThrow(event);\n\n\t\t\tconst error = event.url.searchParams.get(\"error\") ?? undefined;\n\n\t\t\tif (error) {\n\t\t\t\tconst error_description =\n\t\t\t\t\tevent.url.searchParams.get(\"error_description\") ?? undefined;\n\n\t\t\t\tif (!config.oauth.errorLoginRedirectPath) {\n\t\t\t\t\treturn new Response(`${error}\\n${error_description}`.trimEnd(), {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"text/plain\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst errorParams = queryParamsCreate({ error, error_description });\n\t\t\t\tthrow redirect(\n\t\t\t\t\t302,\n\t\t\t\t\t`${config.oauth.errorLoginRedirectPath}?${errorParams}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst code = event.url.searchParams.get(\"code\") ?? undefined;\n\t\t\tthrowIfUndefined(code);\n\n\t\t\tconst exchange = await exchangeCodeForToken(\n\t\t\t\tevent.fetch,\n\t\t\t\tevent.url.origin,\n\t\t\t\tcode,\n\t\t\t);\n\n\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\tjwtVerifyIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tawait config.session.login(\n\t\t\t\tevent,\n\t\t\t\texchangeToTokens(exchange, idToken as ArmorIdToken, accessToken),\n\t\t\t);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","export const ARMOR_LOGIN = \"/_armor/login\" as const;\nexport const ARMOR_LOGOUT = \"/_armor/logout\" as const;\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGIN } from \"../browser\";\n\nexport const ROUTE_PATH_LOGIN = ARMOR_LOGIN;\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t\tscope,\n\t\t\t\taudience: config.oauth.audience,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\teventStateValidOrThrow(event);\n\n\t\t\tawait config.session.logout(event);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGOUT } from \"./redirect-logout\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat } from \"../utils/utils\";\nimport { randomUUID } from \"node:crypto\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { ARMOR_LOGOUT } from \"../browser\";\n\nexport const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst returnTo = config.oauth.logoutReturnToParam ?? \"logout_uri\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tmethod: \"GET\",\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\t[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tstate,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import type { Handle } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { routeLoginFactory } from \"./login\";\nimport { routeLogoutFactory } from \"./logout\";\nimport { routeRedirectLogoutFactory } from \"./redirect-logout\";\nimport { routeRedirectLoginFactory } from \"./redirect-login\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n]);\n\nexport function routeByPathFactory(config: ArmorConfig): Map<string, Route> {\n\t// @ts-expect-error Incorrect typing error.\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route]),\n\t);\n}\n","import { createRemoteJWKSet } from \"jose\";\nimport {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\nimport { ArmorRefreshError } from \"../errors\";\nimport { exchangeToTokens, shouldRefresh, urlConcat } from \"./utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"./jwt\";\nimport { redirect, RequestEvent } from \"@sveltejs/kit\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ROUTE_PATH_LOGIN } from \"../routes/login\";\n\nexport function armorRefreshFactory(config: ArmorConfig) {\n\tconst refreshEndpoint =\n\t\tconfig.oauth.refreshEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst refresh = async (\n\t\tfetch: typeof global.fetch,\n\t\trefreshToken: string,\n\t): Promise<ArmorTokenExchange> => {\n\t\tconst body = new URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\trefresh_token: refreshToken,\n\t\t});\n\n\t\tif (config.oauth.scope) {\n\t\t\tbody.set(\"scope\", config.oauth.scope);\n\t\t}\n\n\t\tconst response = await fetch(refreshEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: body.toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new ArmorRefreshError(`Could not refresh token: ${error}`);\n\t\t}\n\n\t\tconst json: ArmorTokenExchange = await response.json();\n\n\t\treturn {\n\t\t\t...json,\n\t\t\trefresh_token: json.refresh_token ?? refreshToken,\n\t\t};\n\t};\n\n\treturn {\n\t\trefresh,\n\t\tasync ensureValidToken<T>(\n\t\t\tevent: RequestEvent,\n\t\t\ttokens: ArmorTokens,\n\t\t\tfn: (tokens: ArmorTokens) => T | Promise<T>,\n\t\t): Promise<T> {\n\t\t\ttry {\n\t\t\t\tlet validTokens = tokens;\n\n\t\t\t\tif (shouldRefresh(tokens)) {\n\t\t\t\t\tconsole.log(\"Refreshing tokens...\");\n\n\t\t\t\t\tthrowIfUndefined(tokens.exchange.refresh_token);\n\n\t\t\t\t\tconst newExchange = await refresh(\n\t\t\t\t\t\tfetch,\n\t\t\t\t\t\ttokens.exchange.refresh_token,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\t\t\tjwtVerifyIdToken(config, jwks, newExchange.id_token),\n\t\t\t\t\t\tjwtVerifyAccessToken(config, jwks, newExchange.access_token),\n\t\t\t\t\t]);\n\n\t\t\t\t\tvalidTokens = exchangeToTokens(\n\t\t\t\t\t\tnewExchange,\n\t\t\t\t\t\tidToken as ArmorIdToken,\n\t\t\t\t\t\taccessToken,\n\t\t\t\t\t);\n\n\t\t\t\t\tawait config.session.login(event, validTokens);\n\t\t\t\t}\n\n\t\t\t\treturn fn(validTokens);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof ArmorRefreshError) {\n\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport {\n\tCOOKIE_TOKENS,\n\tcookieDelete,\n\tcookieGet,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport { ArmorConfig, ArmorTokens } from \"../contracts\";\nimport { ArmorAuthMissingError } from \"../errors\";\n\nfunction cookieSessionGetTokens({\n\tcookies,\n}: RequestEvent): ArmorTokens | undefined {\n\treturn cookies.get(COOKIE_TOKENS) as ArmorTokens | undefined;\n}\n\nexport function cookieSessionLogin(\n\t{ cookies }: RequestEvent,\n\ttokens: ArmorTokens,\n): void {\n\tcookieSet(cookies, COOKIE_TOKENS, tokens);\n}\n\nfunction cookieSessionLogout({ cookies }: RequestEvent): void {\n\tcookieDelete(cookies, COOKIE_TOKENS);\n}\n\nexport function armorCookieSessionGet({ cookies }: RequestEvent): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\n\tif (!tokens) {\n\t\tthrow new ArmorAuthMissingError();\n\t}\n\n\treturn tokens;\n}\n\nexport const armorCookieSession: ArmorConfig[\"session\"] = {\n\tgetTokens: cookieSessionGetTokens,\n\tlogin: cookieSessionLogin,\n\tlogout: cookieSessionLogout,\n};\n","import { redirect, type Handle } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { routeByPathFactory } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\nimport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\nexport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routeByPath = routeByPathFactory(config);\n\tconst refresh = armorRefreshFactory(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst route = routeByPath.get(event.url.pathname);\n\n\t\tif (route) {\n\t\t\treturn route.handle({ event, resolve });\n\t\t}\n\n\t\tconst tokens = await config.session.getTokens(event);\n\n\t\tif (!tokens) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn refresh.ensureValidToken(event, tokens, () => resolve(event));\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.\n * Use that to create your config.\n * @param config\n * @param fetch\n */\nexport async function armorConfigFromOpenId(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n): Promise<ArmorConfig> {\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(config.oauth.openIdConfigEndpoint, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn {\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksEndpoint: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t\trefreshEndpoint: body.token_endpoint,\n\t\t},\n\t};\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","MINUTES_MS","shouldRefresh","tokens","idExpiry","idToken","exp","accessExpiry","accessToken","Infinity","Math","min","Date","now","createExpiresAt","seconds","setSeconds","getSeconds","exchangeToTokens","exchange","expiresAt","jwtIsCompactJwt","token","parts","trim","split","length","every","p","jwtVerifyIdToken","config","jwks","payload","jwtVerifyToken","issuer","oauth","audience","clientId","throwIfUndefined","jwtVerifyAccessToken","opts","isInvalidCompactJwt","error","Boolean","message","test","jwtVerify","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","cookieDelete","ArmorError","Error","ArmorOpenIdConfigError","ArmorInvalidStateError","ArmorAuthMissingError","ArmorRefreshError","eventStateValidOrThrow","event","_event$url$searchPara","state","url","searchParams","stateCookie","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksEnd","_config$oauth$tokenEn","_config$oauth$scope","jwksUrl","URL","jwksEndpoint","baseUrl","tokenUrl","tokenEndpoint","exchangeCodeForToken","fetch","code","params","grant_type","client_id","client_secret","clientSecret","redirect_uri","response","method","headers","Accept","body","URLSearchParams","toString","ok","text","json","handle","_event$url$searchPara3","_event$url$searchPara2","error_description","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","createRemoteJWKSet","Promise","all","session","login","ARMOR_LOGIN","ARMOR_LOGOUT","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","routeFactories","routeByPathFactory","Map","map","routeFactory","filter","route","armorRefreshFactory","_config$oauth$refresh","refreshEndpoint","refresh","refreshToken","_json$refresh_token","ensureValidToken","fn","validTokens","console","log","newExchange","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","getTokens","armor","routeByPath","resolve","pathname","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/utils/utils.ts","../src/utils/jwt.ts","../src/utils/cookie.ts","../src/errors.ts","../src/utils/event.ts","../src/routes/redirect-login.ts","../src/browser/index.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/utils/refresh.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type {\n\tArmorAccessToken,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n\nconst MINUTES_MS = 60 * 1000;\n\nexport function shouldRefresh(\n\ttokens: Pick<ArmorTokens, \"idToken\" | \"accessToken\">,\n): boolean {\n\tconst idExpiry = tokens.idToken.exp * 1000;\n\n\tconst accessExpiry =\n\t\ttypeof tokens.accessToken !== \"string\" &&\n\t\ttokens.accessToken.exp !== undefined\n\t\t\t? tokens.accessToken.exp * 1000\n\t\t\t: Infinity;\n\n\treturn Math.min(idExpiry, accessExpiry) < Date.now() + 5 * MINUTES_MS;\n}\n\nexport function createExpiresAt(seconds: number): Date {\n\tconst now = new Date();\n\tnow.setSeconds(now.getSeconds() + seconds);\n\treturn now;\n}\n\nexport function exchangeToTokens(\n\texchange: ArmorTokenExchange,\n\tidToken: ArmorIdToken,\n\taccessToken?: ArmorAccessToken,\n): ArmorTokens {\n\treturn {\n\t\texchange,\n\t\tidToken: idToken as ArmorIdToken,\n\t\t// Generally, IdP's require an audience to get a JWT\n\t\t// access token. Most cases, this doesn't matter.\n\t\taccessToken: accessToken ?? exchange.access_token,\n\t\texpiresAt: createExpiresAt(exchange.expires_in),\n\t};\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\nimport { throwIfUndefined } from \"@nekm/core\";\n\nfunction jwtIsCompactJwt(token: string): boolean {\n\t// Must be three base64url segments\n\tconst parts = token.trim().split(\".\");\n\treturn parts.length === 3 && parts.every((p) => p.length > 0);\n}\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\tconst payload = jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n\tthrowIfUndefined(payload);\n\t// @ts-expect-error We're already verifying non-null above.\n\treturn payload;\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload | undefined> {\n\tconst opts: JWTVerifyOptions = { issuer: config.oauth.issuer };\n\n\tif (config.oauth.audience) {\n\t\topts.audience = config.oauth.audience;\n\t}\n\n\treturn jwtVerifyToken(jwks, opts, accessToken);\n}\n\nfunction isInvalidCompactJwt(error: unknown): boolean {\n\treturn Boolean(\n\t\ttypeof error === \"object\" &&\n\t\terror &&\n\t\t\"message\" in error &&\n\t\ttypeof error.message === \"string\" &&\n\t\t/invalid compact jws/gi.test(error.message),\n\t);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload | undefined> {\n\ttry {\n\t\tif (!jwtIsCompactJwt(token)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst { payload } = await jwtVerify(token, jwks, opts);\n\t\treturn payload;\n\t} catch (error) {\n\t\tif (isInvalidCompactJwt(error)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tthrow error;\n\t}\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\" as const;\nexport const COOKIE_STATE = \"state\" as const;\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\nexport class ArmorRefreshError extends ArmorError {}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport { COOKIE_STATE, cookieGetAndDelete } from \"./cookie\";\nimport { ArmorInvalidStateError } from \"../errors\";\n\nexport function eventStateValidOrThrow(event: RequestEvent): void {\n\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\tif (state !== stateCookie) {\n\t\tthrow new ArmorInvalidStateError();\n\t}\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { queryParamsCreate, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange, exchangeToTokens } from \"../utils/utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"../utils/jwt\";\nimport { eventStateValidOrThrow } from \"../utils/event\";\n\nexport const ROUTE_PATH_REDIRECT_LOGIN = \"/_armor/redirect/login\";\n\nexport const routeRedirectLoginFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst tokenUrl =\n\t\tconfig.oauth.tokenEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst params: Record<string, string> = {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\tcode,\n\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\tscope,\n\t\t};\n\n\t\tif (config.oauth.audience) {\n\t\t\tparams.audience = config.oauth.audience;\n\t\t}\n\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams(params).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle login redirect callback.\");\n\n\t\t\teventStateValidOrThrow(event);\n\n\t\t\tconst error = event.url.searchParams.get(\"error\") ?? undefined;\n\n\t\t\tif (error) {\n\t\t\t\tconst error_description =\n\t\t\t\t\tevent.url.searchParams.get(\"error_description\") ?? undefined;\n\n\t\t\t\tconfig.logger?.error?.(\"Login returned error.\", {\n\t\t\t\t\terror,\n\t\t\t\t\terrorDescription: error_description,\n\t\t\t\t});\n\n\t\t\t\tif (!config.oauth.errorLoginRedirectPath) {\n\t\t\t\t\treturn new Response(`${error}\\n${error_description}`.trimEnd(), {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"text/plain\",\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst errorParams = queryParamsCreate({ error, error_description });\n\t\t\t\tthrow redirect(\n\t\t\t\t\t302,\n\t\t\t\t\t`${config.oauth.errorLoginRedirectPath}?${errorParams}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst code = event.url.searchParams.get(\"code\") ?? undefined;\n\t\t\tconfig.logger?.debug?.(\"Get code from query params.\", { code });\n\t\t\tthrowIfUndefined(code);\n\n\t\t\tconst exchange = await exchangeCodeForToken(\n\t\t\t\tevent.fetch,\n\t\t\t\tevent.url.origin,\n\t\t\t\tcode,\n\t\t\t);\n\n\t\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { exchange });\n\n\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\tjwtVerifyIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\t\tidToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tawait config.session.login(\n\t\t\t\tevent,\n\t\t\t\texchangeToTokens(exchange, idToken as ArmorIdToken, accessToken),\n\t\t\t);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","export const ARMOR_LOGIN = \"/_armor/login\" as const;\nexport const ARMOR_LOGOUT = \"/_armor/logout\" as const;\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGIN } from \"../browser\";\n\nexport const ROUTE_PATH_LOGIN = ARMOR_LOGIN;\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = {\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t\tscope,\n\t\t\t\taudience: config.oauth.audience,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre login redirect.\", { params, state });\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconfig.logger?.debug?.(\"Handle logout redirect callback.\");\n\n\t\t\tawait config.session.logout(event);\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGOUT } from \"./redirect-logout\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat } from \"../utils/utils\";\nimport { ARMOR_LOGOUT } from \"../browser\";\n\nexport const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst returnTo = config.oauth.logoutReturnToParam ?? \"logout_uri\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = {\n\t\t\t\t[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t};\n\n\t\t\tconst paramsStr = queryParamsCreate(params);\n\n\t\t\tconfig.logger?.debug?.(\"Pre logout redirect.\", { params });\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${paramsStr}`);\n\t\t},\n\t};\n};\n","import type { Handle } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { routeLoginFactory } from \"./login\";\nimport { routeLogoutFactory } from \"./logout\";\nimport { routeRedirectLogoutFactory } from \"./redirect-logout\";\nimport { routeRedirectLoginFactory } from \"./redirect-login\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n]);\n\nexport function routeByPathFactory(config: ArmorConfig): Map<string, Route> {\n\t// @ts-expect-error Incorrect typing error.\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route]),\n\t);\n}\n","import { createRemoteJWKSet } from \"jose\";\nimport {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n\tArmorTokens,\n} from \"../contracts\";\nimport { ArmorRefreshError } from \"../errors\";\nimport { exchangeToTokens, shouldRefresh, urlConcat } from \"./utils\";\nimport { jwtVerifyAccessToken, jwtVerifyIdToken } from \"./jwt\";\nimport { redirect, RequestEvent } from \"@sveltejs/kit\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ROUTE_PATH_LOGIN } from \"../routes/login\";\n\nexport function armorRefreshFactory(config: ArmorConfig) {\n\tconst refreshEndpoint =\n\t\tconfig.oauth.refreshEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksEndpoint ??\n\t\t\turlConcat(config.oauth.baseUrl, \".well-known/jwks.json\"),\n\t);\n\n\tconst refresh = async (\n\t\tfetch: typeof global.fetch,\n\t\trefreshToken: string,\n\t): Promise<ArmorTokenExchange> => {\n\t\tconst body = new URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\trefresh_token: refreshToken,\n\t\t});\n\n\t\tif (config.oauth.scope) {\n\t\t\tbody.set(\"scope\", config.oauth.scope);\n\t\t}\n\n\t\tconst response = await fetch(refreshEndpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: body.toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new ArmorRefreshError(`Could not refresh token: ${error}`);\n\t\t}\n\n\t\tconst json: ArmorTokenExchange = await response.json();\n\n\t\treturn {\n\t\t\t...json,\n\t\t\trefresh_token: json.refresh_token ?? refreshToken,\n\t\t};\n\t};\n\n\treturn {\n\t\trefresh,\n\t\tasync ensureValidToken<T>(\n\t\t\tevent: RequestEvent,\n\t\t\ttokens: ArmorTokens,\n\t\t\tfn: (tokens: ArmorTokens) => T | Promise<T>,\n\t\t): Promise<T> {\n\t\t\ttry {\n\t\t\t\tlet validTokens = tokens;\n\n\t\t\t\tif (shouldRefresh(tokens)) {\n\t\t\t\t\tconfig.logger?.debug?.(\"Tokens has expired. Refreshing...\");\n\n\t\t\t\t\tthrowIfUndefined(tokens.exchange.refresh_token);\n\n\t\t\t\t\tconst newExchange = await refresh(\n\t\t\t\t\t\tfetch,\n\t\t\t\t\t\ttokens.exchange.refresh_token,\n\t\t\t\t\t);\n\n\t\t\t\t\tconfig.logger?.debug?.(\"Exchange code for tokens.\", { newExchange });\n\n\t\t\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\t\t\tjwtVerifyIdToken(config, jwks, newExchange.id_token),\n\t\t\t\t\t\tjwtVerifyAccessToken(config, jwks, newExchange.access_token),\n\t\t\t\t\t]);\n\n\t\t\t\t\tconfig.logger?.debug?.(\"Extract and verify tokens.\", {\n\t\t\t\t\t\tidToken,\n\t\t\t\t\t\taccessToken,\n\t\t\t\t\t});\n\n\t\t\t\t\tvalidTokens = exchangeToTokens(\n\t\t\t\t\t\tnewExchange,\n\t\t\t\t\t\tidToken as ArmorIdToken,\n\t\t\t\t\t\taccessToken,\n\t\t\t\t\t);\n\n\t\t\t\t\tawait config.session.login(event, validTokens);\n\t\t\t\t}\n\n\t\t\t\treturn fn(validTokens);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof ArmorRefreshError) {\n\t\t\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t};\n}\n","import { RequestEvent } from \"@sveltejs/kit\";\nimport {\n\tCOOKIE_TOKENS,\n\tcookieDelete,\n\tcookieGet,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport { ArmorConfig, ArmorTokens } from \"../contracts\";\nimport { ArmorAuthMissingError } from \"../errors\";\n\nfunction cookieSessionGetTokens({\n\tcookies,\n}: RequestEvent): ArmorTokens | undefined {\n\treturn cookies.get(COOKIE_TOKENS) as ArmorTokens | undefined;\n}\n\nexport function cookieSessionLogin(\n\t{ cookies }: RequestEvent,\n\ttokens: ArmorTokens,\n): void {\n\tcookieSet(cookies, COOKIE_TOKENS, tokens);\n}\n\nfunction cookieSessionLogout({ cookies }: RequestEvent): void {\n\tcookieDelete(cookies, COOKIE_TOKENS);\n}\n\nexport function armorCookieSessionGet({ cookies }: RequestEvent): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\n\tif (!tokens) {\n\t\tthrow new ArmorAuthMissingError();\n\t}\n\n\treturn tokens;\n}\n\nexport const armorCookieSession: ArmorConfig[\"session\"] = {\n\tgetTokens: cookieSessionGetTokens,\n\tlogin: cookieSessionLogin,\n\tlogout: cookieSessionLogout,\n};\n","import { redirect, type Handle } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { routeByPathFactory } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\nimport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\nexport { armorRefreshFactory } from \"./utils/refresh\";\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routeByPath = routeByPathFactory(config);\n\tconst refresh = armorRefreshFactory(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst route = routeByPath.get(event.url.pathname);\n\n\t\tif (route) {\n\t\t\treturn route.handle({ event, resolve });\n\t\t}\n\n\t\tconst tokens = await config.session.getTokens(event);\n\n\t\tif (!tokens) {\n\t\t\tconfig.logger?.warning?.(\"Could not find tokens. Redirecting to login.\");\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn refresh.ensureValidToken(event, tokens, () => resolve(event));\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.\n * Use that to create your config.\n * @param config\n * @param fetch\n */\nexport async function armorConfigFromOpenId(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n): Promise<ArmorConfig> {\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(config.oauth.openIdConfigEndpoint, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn {\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksEndpoint: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t\trefreshEndpoint: body.token_endpoint,\n\t\t},\n\t};\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","MINUTES_MS","shouldRefresh","tokens","idExpiry","idToken","exp","accessExpiry","accessToken","Infinity","Math","min","Date","now","createExpiresAt","seconds","setSeconds","getSeconds","exchangeToTokens","exchange","expiresAt","jwtIsCompactJwt","token","parts","trim","split","length","every","p","jwtVerifyIdToken","config","jwks","payload","jwtVerifyToken","issuer","oauth","audience","clientId","throwIfUndefined","jwtVerifyAccessToken","opts","isInvalidCompactJwt","error","Boolean","message","test","jwtVerify","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","cookieDelete","ArmorError","Error","ArmorOpenIdConfigError","ArmorInvalidStateError","ArmorAuthMissingError","ArmorRefreshError","eventStateValidOrThrow","event","_event$url$searchPara","state","url","searchParams","stateCookie","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksEnd","_config$oauth$tokenEn","_config$oauth$scope","jwksUrl","URL","jwksEndpoint","baseUrl","tokenUrl","tokenEndpoint","exchangeCodeForToken","fetch","code","params","grant_type","client_id","client_secret","clientSecret","redirect_uri","response","method","headers","Accept","body","URLSearchParams","toString","ok","text","json","handle","_config$logger","_event$url$searchPara3","_config$logger3","_config$logger4","_config$logger5","logger","debug","_event$url$searchPara2","_config$logger2","error_description","errorDescription","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","createRemoteJWKSet","Promise","all","session","login","ARMOR_LOGIN","ARMOR_LOGOUT","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","paramsStr","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","routeFactories","routeByPathFactory","Map","map","routeFactory","filter","route","armorRefreshFactory","_config$oauth$refresh","refreshEndpoint","refresh","refreshToken","_json$refresh_token","ensureValidToken","fn","validTokens","newExchange","cookieSessionGetTokens","cookieSessionLogin","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","getTokens","armor","routeByPath","resolve","pathname","warning","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint"],"mappings":"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"}
|
package/package.json
CHANGED
package/src/contracts.ts
CHANGED
|
@@ -51,6 +51,10 @@ interface OauthEndpoints {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
type OauthEndpointsOrBaseUrl = OauthBaseUrl | OauthEndpoints;
|
|
54
|
+
type LoggerFunction = (
|
|
55
|
+
message: string,
|
|
56
|
+
params?: Record<string, unknown>,
|
|
57
|
+
) => void;
|
|
54
58
|
|
|
55
59
|
export interface ArmorConfig {
|
|
56
60
|
readonly session: {
|
|
@@ -87,9 +91,18 @@ export interface ArmorConfig {
|
|
|
87
91
|
*/
|
|
88
92
|
readonly errorLoginRedirectPath?: string;
|
|
89
93
|
};
|
|
94
|
+
readonly logger?: {
|
|
95
|
+
readonly debug?: LoggerFunction;
|
|
96
|
+
readonly info?: LoggerFunction;
|
|
97
|
+
readonly warning?: LoggerFunction;
|
|
98
|
+
readonly error?: LoggerFunction;
|
|
99
|
+
};
|
|
90
100
|
}
|
|
91
101
|
|
|
92
|
-
export interface ArmorOpenIdConfig extends Pick<
|
|
102
|
+
export interface ArmorOpenIdConfig extends Pick<
|
|
103
|
+
ArmorConfig,
|
|
104
|
+
"session" | "logger"
|
|
105
|
+
> {
|
|
93
106
|
readonly oauth: Pick<
|
|
94
107
|
ArmorConfig["oauth"],
|
|
95
108
|
| "clientId"
|
package/src/index.ts
CHANGED
package/src/routes/login.ts
CHANGED
|
@@ -23,16 +23,20 @@ export const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {
|
|
|
23
23
|
const state = randomUUID();
|
|
24
24
|
cookieSet(event.cookies, COOKIE_STATE, state);
|
|
25
25
|
|
|
26
|
-
const params =
|
|
26
|
+
const params = {
|
|
27
27
|
client_id: config.oauth.clientId,
|
|
28
28
|
response_type: "code",
|
|
29
29
|
redirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),
|
|
30
30
|
state,
|
|
31
31
|
scope,
|
|
32
32
|
audience: config.oauth.audience,
|
|
33
|
-
}
|
|
33
|
+
};
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
const paramsStr = queryParamsCreate(params);
|
|
36
|
+
|
|
37
|
+
config.logger?.debug?.("Pre login redirect.", { params, state });
|
|
38
|
+
|
|
39
|
+
throw redirect(302, `${authorizeEndpoint}?${paramsStr}`);
|
|
36
40
|
},
|
|
37
41
|
};
|
|
38
42
|
};
|
package/src/routes/logout.ts
CHANGED
|
@@ -4,8 +4,6 @@ import { queryParamsCreate } from "@nekm/core";
|
|
|
4
4
|
import { ROUTE_PATH_REDIRECT_LOGOUT } from "./redirect-logout";
|
|
5
5
|
import type { RouteFactory } from "./routes";
|
|
6
6
|
import { urlConcat } from "../utils/utils";
|
|
7
|
-
import { randomUUID } from "node:crypto";
|
|
8
|
-
import { COOKIE_STATE, cookieSet } from "../utils/cookie";
|
|
9
7
|
import { ARMOR_LOGOUT } from "../browser";
|
|
10
8
|
|
|
11
9
|
export const ROUTE_PATH_LOGOUT = ARMOR_LOGOUT;
|
|
@@ -20,18 +18,17 @@ export const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {
|
|
|
20
18
|
|
|
21
19
|
return {
|
|
22
20
|
path: ROUTE_PATH_LOGOUT,
|
|
23
|
-
method: "GET",
|
|
24
21
|
async handle({ event }) {
|
|
25
|
-
const
|
|
26
|
-
cookieSet(event.cookies, COOKIE_STATE, state);
|
|
27
|
-
|
|
28
|
-
const params = queryParamsCreate({
|
|
22
|
+
const params = {
|
|
29
23
|
[returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
|
|
30
24
|
client_id: config.oauth.clientId,
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const paramsStr = queryParamsCreate(params);
|
|
28
|
+
|
|
29
|
+
config.logger?.debug?.("Pre logout redirect.", { params });
|
|
33
30
|
|
|
34
|
-
throw redirect(302, `${config.oauth.logoutEndpoint}?${
|
|
31
|
+
throw redirect(302, `${config.oauth.logoutEndpoint}?${paramsStr}`);
|
|
35
32
|
},
|
|
36
33
|
};
|
|
37
34
|
};
|
|
@@ -71,6 +71,8 @@ export const routeRedirectLoginFactory: RouteFactory = (
|
|
|
71
71
|
return {
|
|
72
72
|
path: ROUTE_PATH_REDIRECT_LOGIN,
|
|
73
73
|
async handle({ event }) {
|
|
74
|
+
config.logger?.debug?.("Handle login redirect callback.");
|
|
75
|
+
|
|
74
76
|
eventStateValidOrThrow(event);
|
|
75
77
|
|
|
76
78
|
const error = event.url.searchParams.get("error") ?? undefined;
|
|
@@ -79,6 +81,11 @@ export const routeRedirectLoginFactory: RouteFactory = (
|
|
|
79
81
|
const error_description =
|
|
80
82
|
event.url.searchParams.get("error_description") ?? undefined;
|
|
81
83
|
|
|
84
|
+
config.logger?.error?.("Login returned error.", {
|
|
85
|
+
error,
|
|
86
|
+
errorDescription: error_description,
|
|
87
|
+
});
|
|
88
|
+
|
|
82
89
|
if (!config.oauth.errorLoginRedirectPath) {
|
|
83
90
|
return new Response(`${error}\n${error_description}`.trimEnd(), {
|
|
84
91
|
headers: {
|
|
@@ -95,6 +102,7 @@ export const routeRedirectLoginFactory: RouteFactory = (
|
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
const code = event.url.searchParams.get("code") ?? undefined;
|
|
105
|
+
config.logger?.debug?.("Get code from query params.", { code });
|
|
98
106
|
throwIfUndefined(code);
|
|
99
107
|
|
|
100
108
|
const exchange = await exchangeCodeForToken(
|
|
@@ -103,6 +111,8 @@ export const routeRedirectLoginFactory: RouteFactory = (
|
|
|
103
111
|
code,
|
|
104
112
|
);
|
|
105
113
|
|
|
114
|
+
config.logger?.debug?.("Exchange code for tokens.", { exchange });
|
|
115
|
+
|
|
106
116
|
const jwks = createRemoteJWKSet(jwksUrl);
|
|
107
117
|
|
|
108
118
|
const [idToken, accessToken] = await Promise.all([
|
|
@@ -110,6 +120,11 @@ export const routeRedirectLoginFactory: RouteFactory = (
|
|
|
110
120
|
jwtVerifyAccessToken(config, jwks, exchange.access_token),
|
|
111
121
|
]);
|
|
112
122
|
|
|
123
|
+
config.logger?.debug?.("Extract and verify tokens.", {
|
|
124
|
+
idToken,
|
|
125
|
+
accessToken,
|
|
126
|
+
});
|
|
127
|
+
|
|
113
128
|
await config.session.login(
|
|
114
129
|
event,
|
|
115
130
|
exchangeToTokens(exchange, idToken as ArmorIdToken, accessToken),
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { redirect } from "@sveltejs/kit";
|
|
2
2
|
import type { ArmorConfig } from "../contracts";
|
|
3
3
|
import type { RouteFactory } from "./routes";
|
|
4
|
-
import { eventStateValidOrThrow } from "../utils/event";
|
|
5
4
|
|
|
6
5
|
export const ROUTE_PATH_REDIRECT_LOGOUT = "/_armor/redirect/logout";
|
|
7
6
|
|
|
@@ -16,7 +15,7 @@ export const routeRedirectLogoutFactory: RouteFactory = (
|
|
|
16
15
|
return {
|
|
17
16
|
path: ROUTE_PATH_REDIRECT_LOGOUT,
|
|
18
17
|
async handle({ event }) {
|
|
19
|
-
|
|
18
|
+
config.logger?.debug?.("Handle logout redirect callback.");
|
|
20
19
|
|
|
21
20
|
await config.session.logout(event);
|
|
22
21
|
|
package/src/utils/refresh.ts
CHANGED
|
@@ -70,7 +70,7 @@ export function armorRefreshFactory(config: ArmorConfig) {
|
|
|
70
70
|
let validTokens = tokens;
|
|
71
71
|
|
|
72
72
|
if (shouldRefresh(tokens)) {
|
|
73
|
-
|
|
73
|
+
config.logger?.debug?.("Tokens has expired. Refreshing...");
|
|
74
74
|
|
|
75
75
|
throwIfUndefined(tokens.exchange.refresh_token);
|
|
76
76
|
|
|
@@ -79,6 +79,8 @@ export function armorRefreshFactory(config: ArmorConfig) {
|
|
|
79
79
|
tokens.exchange.refresh_token,
|
|
80
80
|
);
|
|
81
81
|
|
|
82
|
+
config.logger?.debug?.("Exchange code for tokens.", { newExchange });
|
|
83
|
+
|
|
82
84
|
const jwks = createRemoteJWKSet(jwksUrl);
|
|
83
85
|
|
|
84
86
|
const [idToken, accessToken] = await Promise.all([
|
|
@@ -86,6 +88,11 @@ export function armorRefreshFactory(config: ArmorConfig) {
|
|
|
86
88
|
jwtVerifyAccessToken(config, jwks, newExchange.access_token),
|
|
87
89
|
]);
|
|
88
90
|
|
|
91
|
+
config.logger?.debug?.("Extract and verify tokens.", {
|
|
92
|
+
idToken,
|
|
93
|
+
accessToken,
|
|
94
|
+
});
|
|
95
|
+
|
|
89
96
|
validTokens = exchangeToTokens(
|
|
90
97
|
newExchange,
|
|
91
98
|
idToken as ArmorIdToken,
|