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