@nekm/sveltekit-armor 0.2.0 → 0.2.2

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.
@@ -30,7 +30,7 @@ interface OauthEndpoints {
30
30
  readonly baseUrl?: never;
31
31
  readonly jwksEndpoint: string;
32
32
  readonly authorizeEndpoint: string;
33
- readonly logoutEndpoint: string;
33
+ readonly logoutEndpoint?: string;
34
34
  readonly tokenEndpoint: string;
35
35
  }
36
36
  type OauthEndpointsOrBaseUrl = OauthBaseUrl | OauthEndpoints;
@@ -46,10 +46,27 @@ export interface ArmorConfig {
46
46
  readonly issuer: string;
47
47
  readonly scope?: string;
48
48
  readonly audience?: string;
49
+ /**
50
+ * When redirecting a user to the oauth logout flow,
51
+ * what should we name the return to parameter? I.e.
52
+ * the parameter that decides where to redirect the
53
+ * user back.
54
+ * @default {string} logout_uri
55
+ */
56
+ readonly logoutReturnToParam?: string;
57
+ /**
58
+ * If an error occurs, where should we redirect the
59
+ * user? Should be an internal path. There'll be more
60
+ * information as query parameters:
61
+ * 1. error
62
+ * 2. error_description
63
+ * @default {undefined} Armor will throw an error
64
+ */
65
+ readonly errorLoginRedirectPath?: string;
49
66
  };
50
67
  }
51
68
  export interface ArmorOpenIdConfig extends Pick<ArmorConfig, "session"> {
52
- readonly oauth: Pick<ArmorConfig["oauth"], "clientId" | "clientSecret" | "scope" | "audience"> & {
69
+ readonly oauth: Pick<ArmorConfig["oauth"], "clientId" | "clientSecret" | "scope" | "audience" | "logoutReturnToParam" | "errorLoginRedirectPath"> & {
53
70
  readonly openIdConfigEndpoint: string;
54
71
  };
55
72
  }
package/dist/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
- import { redirect, error } from '@sveltejs/kit';
2
- import { strTrimEnd, strTrimStart, throwIfUndefined, queryParamsCreate } from '@nekm/core';
1
+ import { redirect } from '@sveltejs/kit';
2
+ import { strTrimEnd, strTrimStart, queryParamsCreate, throwIfUndefined } from '@nekm/core';
3
3
  import { jwtVerify, createRemoteJWKSet } from 'jose';
4
4
  import { randomUUID } from 'node:crypto';
5
5
 
@@ -121,9 +121,26 @@ const routeRedirectLoginFactory = config => {
121
121
  async handle({
122
122
  event
123
123
  }) {
124
- var _event$url$searchPara;
124
+ var _event$url$searchPara, _event$url$searchPara3;
125
125
  eventStateValidOrThrow(event);
126
- const code = (_event$url$searchPara = event.url.searchParams.get("code")) != null ? _event$url$searchPara : undefined;
126
+ const error = (_event$url$searchPara = event.url.searchParams.get("error")) != null ? _event$url$searchPara : undefined;
127
+ if (error) {
128
+ var _event$url$searchPara2;
129
+ const error_description = (_event$url$searchPara2 = event.url.searchParams.get("error_description")) != null ? _event$url$searchPara2 : undefined;
130
+ if (!config.oauth.errorLoginRedirectPath) {
131
+ return new Response(`${error}\n${error_description}`.trimEnd(), {
132
+ headers: {
133
+ "Content-Type": "text/plain"
134
+ }
135
+ });
136
+ }
137
+ const errorParams = queryParamsCreate({
138
+ error,
139
+ error_description
140
+ });
141
+ throw redirect(302, `${config.oauth.errorLoginRedirectPath}?${errorParams}`);
142
+ }
143
+ const code = (_event$url$searchPara3 = event.url.searchParams.get("code")) != null ? _event$url$searchPara3 : undefined;
127
144
  throwIfUndefined(code);
128
145
  const exchange = await exchangeCodeForToken(event.fetch, event.url.origin, code);
129
146
  const jwks = createRemoteJWKSet(jwksUrl);
@@ -183,10 +200,12 @@ const routeRedirectLogoutFactory = config => {
183
200
 
184
201
  const ROUTE_PATH_LOGOUT = "/_armor/logout";
185
202
  const routeLogoutFactory = config => {
203
+ var _config$oauth$logoutR;
186
204
  // Check if the oauth provider supports a logout path.
187
205
  if (!config.oauth.logoutEndpoint) {
188
206
  return undefined;
189
207
  }
208
+ const returnTo = (_config$oauth$logoutR = config.oauth.logoutReturnToParam) != null ? _config$oauth$logoutR : "logout_uri";
190
209
  return {
191
210
  path: ROUTE_PATH_LOGOUT,
192
211
  async handle({
@@ -195,7 +214,7 @@ const routeLogoutFactory = config => {
195
214
  const state = randomUUID();
196
215
  cookieSet(event.cookies, COOKIE_STATE, state);
197
216
  const params = queryParamsCreate({
198
- logout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
217
+ [returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
199
218
  client_id: config.oauth.clientId,
200
219
  state
201
220
  });
@@ -251,12 +270,10 @@ function armor(config) {
251
270
  }) => {
252
271
  const routeHandle = routes.get(event.url.pathname);
253
272
  if (routeHandle) {
254
- await routeHandle({
273
+ return routeHandle({
255
274
  event,
256
275
  resolve
257
276
  });
258
- // Handle should redirect. If it doesn't, something is wrong.
259
- throw error(500, "Illegal state");
260
277
  }
261
278
  const exists = await config.session.exists(event);
262
279
  if (!exists) {
@@ -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/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type { ArmorTokenExchange } from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload> {\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\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload> {\n\tconst { payload } = await jwtVerify(token, jwks, opts);\n\treturn payload;\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\";\nexport const COOKIE_STATE = \"state\";\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\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 { throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange } 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 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(event, {\n\t\t\t\texchange,\n\t\t\t\tidToken: idToken as ArmorIdToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\n\nexport const ROUTE_PATH_LOGIN = \"/_armor/login\";\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\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\";\n\nexport const ROUTE_PATH_LOGOUT = \"/_armor/logout\";\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tlogout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\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 routeCreate(config: ArmorConfig): Map<string, Handle> {\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route.handle]),\n\t);\n}\n","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 cookieSessionExists({ cookies }: RequestEvent): boolean {\n\treturn Boolean(cookies.get(COOKIE_TOKENS));\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\texists: cookieSessionExists,\n\tlogin: cookieSessionLogin,\n\tlogout: cookieSessionLogout,\n};\n","import { error, redirect, type Handle } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { ROUTE_PATH_LOGOUT } from \"./routes/logout\";\nimport { routeCreate } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\n\nexport const ARMOR_LOGIN = ROUTE_PATH_LOGIN;\nexport const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routes = routeCreate(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst routeHandle = routes.get(event.url.pathname);\n\n\t\tif (routeHandle) {\n\t\t\tawait routeHandle({ event, resolve });\n\n\t\t\t// Handle should redirect. If it doesn't, something is wrong.\n\t\t\tthrow error(500, \"Illegal state\");\n\t\t}\n\n\t\tconst exists = await config.session.exists(event);\n\n\t\tif (!exists) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn resolve(event);\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-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},\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","jwtVerifyIdToken","config","jwks","idToken","jwtVerifyToken","issuer","oauth","audience","clientId","jwtVerifyAccessToken","accessToken","opts","token","payload","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","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","error","text","json","handle","throwIfUndefined","exchange","createRemoteJWKSet","Promise","all","session","login","redirect","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","queryParamsCreate","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","logout_uri","routeFactories","routeCreate","Map","map","routeFactory","filter","route","Boolean","cookieSessionExists","cookieSessionLogin","tokens","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","exists","ARMOR_LOGIN","ARMOR_LOGOUT","armor","routes","resolve","routeHandle","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/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type { ArmorTokenExchange } from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload> {\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\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload> {\n\tconst { payload } = await jwtVerify(token, jwks, opts);\n\treturn payload;\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\";\nexport const COOKIE_STATE = \"state\";\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\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 } 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(event, {\n\t\t\t\texchange,\n\t\t\t\tidToken: idToken as ArmorIdToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\n\nexport const ROUTE_PATH_LOGIN = \"/_armor/login\";\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\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\";\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 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 routeCreate(config: ArmorConfig): Map<string, Handle> {\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route.handle]),\n\t);\n}\n","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 cookieSessionExists({ cookies }: RequestEvent): boolean {\n\treturn Boolean(cookies.get(COOKIE_TOKENS));\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\texists: cookieSessionExists,\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 { ROUTE_PATH_LOGOUT } from \"./routes/logout\";\nimport { routeCreate } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\n\nexport const ARMOR_LOGIN = ROUTE_PATH_LOGIN;\nexport const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routes = routeCreate(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst routeHandle = routes.get(event.url.pathname);\n\n\t\tif (routeHandle) {\n\t\t\treturn routeHandle({ event, resolve });\n\t\t}\n\n\t\tconst exists = await config.session.exists(event);\n\n\t\tif (!exists) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn resolve(event);\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-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},\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","jwtVerifyIdToken","config","jwks","idToken","jwtVerifyToken","issuer","oauth","audience","clientId","jwtVerifyAccessToken","accessToken","opts","token","payload","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","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","error","text","json","handle","_event$url$searchPara3","_event$url$searchPara2","error_description","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","throwIfUndefined","exchange","createRemoteJWKSet","Promise","all","session","login","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","routeFactories","routeCreate","Map","map","routeFactory","filter","route","Boolean","cookieSessionExists","cookieSessionLogin","tokens","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","exists","ARMOR_LOGIN","ARMOR_LOGOUT","armor","routes","resolve","routeHandle","pathname","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -121,9 +121,26 @@ const routeRedirectLoginFactory = config => {
121
121
  async handle({
122
122
  event
123
123
  }) {
124
- var _event$url$searchPara;
124
+ var _event$url$searchPara, _event$url$searchPara3;
125
125
  eventStateValidOrThrow(event);
126
- const code = (_event$url$searchPara = event.url.searchParams.get("code")) != null ? _event$url$searchPara : undefined;
126
+ const error = (_event$url$searchPara = event.url.searchParams.get("error")) != null ? _event$url$searchPara : undefined;
127
+ if (error) {
128
+ var _event$url$searchPara2;
129
+ const error_description = (_event$url$searchPara2 = event.url.searchParams.get("error_description")) != null ? _event$url$searchPara2 : undefined;
130
+ if (!config.oauth.errorLoginRedirectPath) {
131
+ return new Response(`${error}\n${error_description}`.trimEnd(), {
132
+ headers: {
133
+ "Content-Type": "text/plain"
134
+ }
135
+ });
136
+ }
137
+ const errorParams = core.queryParamsCreate({
138
+ error,
139
+ error_description
140
+ });
141
+ throw kit.redirect(302, `${config.oauth.errorLoginRedirectPath}?${errorParams}`);
142
+ }
143
+ const code = (_event$url$searchPara3 = event.url.searchParams.get("code")) != null ? _event$url$searchPara3 : undefined;
127
144
  core.throwIfUndefined(code);
128
145
  const exchange = await exchangeCodeForToken(event.fetch, event.url.origin, code);
129
146
  const jwks = jose.createRemoteJWKSet(jwksUrl);
@@ -183,10 +200,12 @@ const routeRedirectLogoutFactory = config => {
183
200
 
184
201
  const ROUTE_PATH_LOGOUT = "/_armor/logout";
185
202
  const routeLogoutFactory = config => {
203
+ var _config$oauth$logoutR;
186
204
  // Check if the oauth provider supports a logout path.
187
205
  if (!config.oauth.logoutEndpoint) {
188
206
  return undefined;
189
207
  }
208
+ const returnTo = (_config$oauth$logoutR = config.oauth.logoutReturnToParam) != null ? _config$oauth$logoutR : "logout_uri";
190
209
  return {
191
210
  path: ROUTE_PATH_LOGOUT,
192
211
  async handle({
@@ -195,7 +214,7 @@ const routeLogoutFactory = config => {
195
214
  const state = node_crypto.randomUUID();
196
215
  cookieSet(event.cookies, COOKIE_STATE, state);
197
216
  const params = core.queryParamsCreate({
198
- logout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
217
+ [returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
199
218
  client_id: config.oauth.clientId,
200
219
  state
201
220
  });
@@ -251,12 +270,10 @@ function armor(config) {
251
270
  }) => {
252
271
  const routeHandle = routes.get(event.url.pathname);
253
272
  if (routeHandle) {
254
- await routeHandle({
273
+ return routeHandle({
255
274
  event,
256
275
  resolve
257
276
  });
258
- // Handle should redirect. If it doesn't, something is wrong.
259
- throw kit.error(500, "Illegal state");
260
277
  }
261
278
  const exists = await config.session.exists(event);
262
279
  if (!exists) {
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/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type { ArmorTokenExchange } from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload> {\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\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload> {\n\tconst { payload } = await jwtVerify(token, jwks, opts);\n\treturn payload;\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\";\nexport const COOKIE_STATE = \"state\";\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\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 { throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange } 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 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(event, {\n\t\t\t\texchange,\n\t\t\t\tidToken: idToken as ArmorIdToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\n\nexport const ROUTE_PATH_LOGIN = \"/_armor/login\";\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\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\";\n\nexport const ROUTE_PATH_LOGOUT = \"/_armor/logout\";\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tlogout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\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 routeCreate(config: ArmorConfig): Map<string, Handle> {\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route.handle]),\n\t);\n}\n","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 cookieSessionExists({ cookies }: RequestEvent): boolean {\n\treturn Boolean(cookies.get(COOKIE_TOKENS));\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\texists: cookieSessionExists,\n\tlogin: cookieSessionLogin,\n\tlogout: cookieSessionLogout,\n};\n","import { error, redirect, type Handle } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { ROUTE_PATH_LOGOUT } from \"./routes/logout\";\nimport { routeCreate } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\n\nexport const ARMOR_LOGIN = ROUTE_PATH_LOGIN;\nexport const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routes = routeCreate(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst routeHandle = routes.get(event.url.pathname);\n\n\t\tif (routeHandle) {\n\t\t\tawait routeHandle({ event, resolve });\n\n\t\t\t// Handle should redirect. If it doesn't, something is wrong.\n\t\t\tthrow error(500, \"Illegal state\");\n\t\t}\n\n\t\tconst exists = await config.session.exists(event);\n\n\t\tif (!exists) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn resolve(event);\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-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},\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","jwtVerifyIdToken","config","jwks","idToken","jwtVerifyToken","issuer","oauth","audience","clientId","jwtVerifyAccessToken","accessToken","opts","token","payload","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","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","error","text","json","handle","throwIfUndefined","exchange","createRemoteJWKSet","Promise","all","session","login","redirect","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","queryParamsCreate","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","logout_uri","routeFactories","routeCreate","Map","map","routeFactory","filter","route","Boolean","cookieSessionExists","cookieSessionLogin","tokens","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","exists","ARMOR_LOGIN","ARMOR_LOGOUT","armor","routes","resolve","routeHandle","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/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/session/cookie.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type { ArmorTokenExchange } from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n","import { ArmorConfig } from \"../contracts\";\nimport { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload> {\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\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload> {\n\tconst { payload } = await jwtVerify(token, jwks, opts);\n\treturn payload;\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\";\nexport const COOKIE_STATE = \"state\";\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n\nexport function cookieDelete(cookies: Cookies, key: string): void {\n\tcookies.delete(key, cookieDeleteOptions);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends ArmorError {}\nexport class ArmorInvalidStateError extends ArmorError {}\nexport class ArmorAuthMissingError extends ArmorError {}\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 } 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(event, {\n\t\t\t\texchange,\n\t\t\t\tidToken: idToken as ArmorIdToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\n\nexport const ROUTE_PATH_LOGIN = \"/_armor/login\";\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\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\";\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 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 routeCreate(config: ArmorConfig): Map<string, Handle> {\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route.handle]),\n\t);\n}\n","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 cookieSessionExists({ cookies }: RequestEvent): boolean {\n\treturn Boolean(cookies.get(COOKIE_TOKENS));\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\texists: cookieSessionExists,\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 { ROUTE_PATH_LOGOUT } from \"./routes/logout\";\nimport { routeCreate } from \"./routes/routes\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\n\nexport type { ArmorConfig, ArmorTokens };\nexport { armorCookieSession, armorCookieSessionGet } from \"./session/cookie\";\n\nexport const ARMOR_LOGIN = ROUTE_PATH_LOGIN;\nexport const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routes = routeCreate(config);\n\n\treturn async ({ event, resolve }) => {\n\t\tconst routeHandle = routes.get(event.url.pathname);\n\n\t\tif (routeHandle) {\n\t\t\treturn routeHandle({ event, resolve });\n\t\t}\n\n\t\tconst exists = await config.session.exists(event);\n\n\t\tif (!exists) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn resolve(event);\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-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},\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","jwtVerifyIdToken","config","jwks","idToken","jwtVerifyToken","issuer","oauth","audience","clientId","jwtVerifyAccessToken","accessToken","opts","token","payload","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","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","error","text","json","handle","_event$url$searchPara3","_event$url$searchPara2","error_description","errorLoginRedirectPath","Response","trimEnd","errorParams","queryParamsCreate","redirect","throwIfUndefined","exchange","createRemoteJWKSet","Promise","all","session","login","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","logoutEndpoint","logout","ROUTE_PATH_LOGOUT","routeLogoutFactory","_config$oauth$logoutR","returnTo","logoutReturnToParam","routeFactories","routeCreate","Map","map","routeFactory","filter","route","Boolean","cookieSessionExists","cookieSessionLogin","tokens","cookieSessionLogout","armorCookieSessionGet","armorCookieSession","exists","ARMOR_LOGIN","ARMOR_LOGOUT","armor","routes","resolve","routeHandle","pathname","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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nekm/sveltekit-armor",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Zero-config OAuth protection for SvelteKit",
5
5
  "license": "MIT",
6
6
  "source": "./src/index.ts",
package/src/contracts.ts CHANGED
@@ -43,7 +43,7 @@ interface OauthEndpoints {
43
43
 
44
44
  readonly jwksEndpoint: string;
45
45
  readonly authorizeEndpoint: string;
46
- readonly logoutEndpoint: string;
46
+ readonly logoutEndpoint?: string;
47
47
  readonly tokenEndpoint: string;
48
48
  }
49
49
 
@@ -64,13 +64,35 @@ export interface ArmorConfig {
64
64
  readonly issuer: string;
65
65
  readonly scope?: string;
66
66
  readonly audience?: string;
67
+ /**
68
+ * When redirecting a user to the oauth logout flow,
69
+ * what should we name the return to parameter? I.e.
70
+ * the parameter that decides where to redirect the
71
+ * user back.
72
+ * @default {string} logout_uri
73
+ */
74
+ readonly logoutReturnToParam?: string;
75
+ /**
76
+ * If an error occurs, where should we redirect the
77
+ * user? Should be an internal path. There'll be more
78
+ * information as query parameters:
79
+ * 1. error
80
+ * 2. error_description
81
+ * @default {undefined} Armor will throw an error
82
+ */
83
+ readonly errorLoginRedirectPath?: string;
67
84
  };
68
85
  }
69
86
 
70
87
  export interface ArmorOpenIdConfig extends Pick<ArmorConfig, "session"> {
71
88
  readonly oauth: Pick<
72
89
  ArmorConfig["oauth"],
73
- "clientId" | "clientSecret" | "scope" | "audience"
90
+ | "clientId"
91
+ | "clientSecret"
92
+ | "scope"
93
+ | "audience"
94
+ | "logoutReturnToParam"
95
+ | "errorLoginRedirectPath"
74
96
  > & {
75
97
  readonly openIdConfigEndpoint: string;
76
98
  };
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { error, redirect, type Handle } from "@sveltejs/kit";
1
+ import { redirect, type Handle } from "@sveltejs/kit";
2
2
  import { ROUTE_PATH_LOGIN } from "./routes/login";
3
3
  import type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from "./contracts";
4
4
  import { ROUTE_PATH_LOGOUT } from "./routes/logout";
@@ -18,10 +18,7 @@ export function armor(config: ArmorConfig): Handle {
18
18
  const routeHandle = routes.get(event.url.pathname);
19
19
 
20
20
  if (routeHandle) {
21
- await routeHandle({ event, resolve });
22
-
23
- // Handle should redirect. If it doesn't, something is wrong.
24
- throw error(500, "Illegal state");
21
+ return routeHandle({ event, resolve });
25
22
  }
26
23
 
27
24
  const exists = await config.session.exists(event);
@@ -15,6 +15,8 @@ export const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {
15
15
  return undefined;
16
16
  }
17
17
 
18
+ const returnTo = config.oauth.logoutReturnToParam ?? "logout_uri";
19
+
18
20
  return {
19
21
  path: ROUTE_PATH_LOGOUT,
20
22
  async handle({ event }) {
@@ -22,7 +24,7 @@ export const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {
22
24
  cookieSet(event.cookies, COOKIE_STATE, state);
23
25
 
24
26
  const params = queryParamsCreate({
25
- logout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
27
+ [returnTo]: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),
26
28
  client_id: config.oauth.clientId,
27
29
  state,
28
30
  });
@@ -4,7 +4,7 @@ import type {
4
4
  ArmorIdToken,
5
5
  ArmorTokenExchange,
6
6
  } from "../contracts";
7
- import { throwIfUndefined } from "@nekm/core";
7
+ import { queryParamsCreate, throwIfUndefined } from "@nekm/core";
8
8
  import { createRemoteJWKSet } from "jose";
9
9
  import type { RouteFactory } from "./routes";
10
10
  import { urlConcat, isTokenExchange } from "../utils/utils";
@@ -73,6 +73,27 @@ export const routeRedirectLoginFactory: RouteFactory = (
73
73
  async handle({ event }) {
74
74
  eventStateValidOrThrow(event);
75
75
 
76
+ const error = event.url.searchParams.get("error") ?? undefined;
77
+
78
+ if (error) {
79
+ const error_description =
80
+ event.url.searchParams.get("error_description") ?? undefined;
81
+
82
+ if (!config.oauth.errorLoginRedirectPath) {
83
+ return new Response(`${error}\n${error_description}`.trimEnd(), {
84
+ headers: {
85
+ "Content-Type": "text/plain",
86
+ },
87
+ });
88
+ }
89
+
90
+ const errorParams = queryParamsCreate({ error, error_description });
91
+ throw redirect(
92
+ 302,
93
+ `${config.oauth.errorLoginRedirectPath}?${errorParams}`,
94
+ );
95
+ }
96
+
76
97
  const code = event.url.searchParams.get("code") ?? undefined;
77
98
  throwIfUndefined(code);
78
99