@nekm/sveltekit-armor 0.1.5 → 0.1.7
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 +5 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.esm.js +39 -38
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +38 -37
- package/dist/index.js.map +1 -1
- package/dist/utils/jwt.d.ts +2 -2
- package/package.json +1 -1
- package/src/contracts.ts +5 -1
- package/src/index.ts +7 -11
- package/src/routes/login.ts +4 -0
- package/src/routes/redirect-login.ts +19 -13
- package/src/utils/jwt.ts +11 -29
package/dist/contracts.d.ts
CHANGED
|
@@ -36,12 +36,16 @@ export interface ArmorConfig {
|
|
|
36
36
|
readonly authorizeEndpoint?: string;
|
|
37
37
|
readonly logoutEndpoint?: string;
|
|
38
38
|
readonly tokenEndpoint?: string;
|
|
39
|
+
readonly scope?: string;
|
|
40
|
+
readonly audience?: string;
|
|
39
41
|
};
|
|
40
42
|
}
|
|
41
43
|
export interface ArmorOpenIdConfig extends Pick<ArmorConfig, "session"> {
|
|
42
44
|
readonly oauth: ArmorCredentials & {
|
|
43
|
-
readonly
|
|
45
|
+
readonly openIdConfigEndpoint: string;
|
|
44
46
|
readonly baseUrl: string;
|
|
47
|
+
readonly scope?: string;
|
|
48
|
+
readonly audience?: string;
|
|
45
49
|
};
|
|
46
50
|
}
|
|
47
51
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -5,10 +5,10 @@ export declare const ARMOR_LOGIN = "/_armor/login";
|
|
|
5
5
|
export declare const ARMOR_LOGOUT = "/_armor/logout";
|
|
6
6
|
export declare function armor(config: ArmorConfig): Handle;
|
|
7
7
|
/**
|
|
8
|
-
* Some IdP's expose a /.well-known/openid-
|
|
9
|
-
* Use that to
|
|
8
|
+
* Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.
|
|
9
|
+
* Use that to create your config.
|
|
10
10
|
* @param config
|
|
11
11
|
* @param fetch
|
|
12
12
|
*/
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function armorConfigFromOpenId(config: ArmorOpenIdConfig, fetch?: typeof global.fetch): Promise<ArmorConfig>;
|
|
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 {
|
|
3
|
+
import { jwtVerify, createRemoteJWKSet } from 'jose';
|
|
4
4
|
import { randomUUID } from 'node:crypto';
|
|
5
5
|
|
|
6
6
|
function urlConcat(origin, path) {
|
|
@@ -41,29 +41,22 @@ function cookieGet(cookies, key) {
|
|
|
41
41
|
return !value ? undefined : JSON.parse(value);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
function
|
|
45
|
-
return
|
|
44
|
+
function jwtVerifyIdToken(config, jwks, idToken) {
|
|
45
|
+
return jwtVerifyToken(jwks, {
|
|
46
46
|
issuer: config.oauth.issuer,
|
|
47
47
|
audience: config.oauth.clientId
|
|
48
48
|
}, idToken);
|
|
49
49
|
}
|
|
50
|
-
function
|
|
51
|
-
|
|
50
|
+
function jwtVerifyAccessToken(config, jwks, accessToken) {
|
|
51
|
+
const opts = {
|
|
52
52
|
issuer: config.oauth.issuer
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
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;
|
|
53
|
+
};
|
|
54
|
+
if (config.oauth.audience) {
|
|
55
|
+
opts.audience = config.oauth.audience;
|
|
66
56
|
}
|
|
57
|
+
return jwtVerifyToken(jwks, opts, accessToken);
|
|
58
|
+
}
|
|
59
|
+
async function jwtVerifyToken(jwks, opts, token) {
|
|
67
60
|
const {
|
|
68
61
|
payload
|
|
69
62
|
} = await jwtVerify(token, jwks, opts);
|
|
@@ -72,24 +65,30 @@ async function jwtVerifyAndDecryptToken(config, jwks, opts, token) {
|
|
|
72
65
|
|
|
73
66
|
const ROUTE_PATH_REDIRECT_LOGIN = "/_armor/redirect/login";
|
|
74
67
|
const routeRedirectLoginFactory = config => {
|
|
75
|
-
var _config$oauth$jwksUrl, _config$oauth$tokenEn, _config$session$login, _config$session;
|
|
68
|
+
var _config$oauth$jwksUrl, _config$oauth$tokenEn, _config$session$login, _config$session, _config$oauth$scope;
|
|
76
69
|
const jwksUrl = new URL((_config$oauth$jwksUrl = config.oauth.jwksUrl) != null ? _config$oauth$jwksUrl : `${strTrimEnd(config.oauth.issuer, "/")}/.well-known/jwks.json`);
|
|
77
70
|
const tokenUrl = (_config$oauth$tokenEn = config.oauth.tokenEndpoint) != null ? _config$oauth$tokenEn : urlConcat(config.oauth.baseUrl, "oauth2/token");
|
|
78
71
|
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);
|
|
72
|
+
const scope = (_config$oauth$scope = config.oauth.scope) != null ? _config$oauth$scope : "openid profile email";
|
|
79
73
|
async function exchangeCodeForToken(fetch, origin, code) {
|
|
74
|
+
const params = {
|
|
75
|
+
grant_type: "authorization_code",
|
|
76
|
+
client_id: config.oauth.clientId,
|
|
77
|
+
client_secret: config.oauth.clientSecret,
|
|
78
|
+
code,
|
|
79
|
+
redirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),
|
|
80
|
+
scope
|
|
81
|
+
};
|
|
82
|
+
if (config.oauth.audience) {
|
|
83
|
+
params.audience = config.oauth.audience;
|
|
84
|
+
}
|
|
80
85
|
const response = await fetch(tokenUrl, {
|
|
81
86
|
method: "POST",
|
|
82
87
|
headers: {
|
|
83
88
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
84
89
|
Accept: "application/json"
|
|
85
90
|
},
|
|
86
|
-
body: new URLSearchParams(
|
|
87
|
-
grant_type: "authorization_code",
|
|
88
|
-
client_id: config.oauth.clientId,
|
|
89
|
-
client_secret: config.oauth.clientSecret,
|
|
90
|
-
code,
|
|
91
|
-
redirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN)
|
|
92
|
-
}).toString()
|
|
91
|
+
body: new URLSearchParams(params).toString()
|
|
93
92
|
});
|
|
94
93
|
if (!response.ok) {
|
|
95
94
|
const error = await response.text();
|
|
@@ -116,7 +115,7 @@ const routeRedirectLoginFactory = config => {
|
|
|
116
115
|
throwIfUndefined(code);
|
|
117
116
|
const exchange = await exchangeCodeForToken(fetch, event.url.origin, code);
|
|
118
117
|
const jwks = createRemoteJWKSet(jwksUrl);
|
|
119
|
-
const [idToken, accessToken] = await Promise.all([
|
|
118
|
+
const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, exchange.id_token), jwtVerifyAccessToken(config, jwks, exchange.access_token)]);
|
|
120
119
|
await sessionLogin(event, {
|
|
121
120
|
exchange,
|
|
122
121
|
idToken: idToken,
|
|
@@ -129,8 +128,9 @@ const routeRedirectLoginFactory = config => {
|
|
|
129
128
|
|
|
130
129
|
const ROUTE_PATH_LOGIN = "/_armor/login";
|
|
131
130
|
const routeLoginFactory = config => {
|
|
132
|
-
var _config$oauth$authori;
|
|
131
|
+
var _config$oauth$authori, _config$oauth$scope;
|
|
133
132
|
const authorizeEndpoint = (_config$oauth$authori = config.oauth.authorizeEndpoint) != null ? _config$oauth$authori : urlConcat(config.oauth.baseUrl, "oauth2/authorize");
|
|
133
|
+
const scope = (_config$oauth$scope = config.oauth.scope) != null ? _config$oauth$scope : "openid profile email";
|
|
134
134
|
return {
|
|
135
135
|
path: ROUTE_PATH_LOGIN,
|
|
136
136
|
async handle({
|
|
@@ -142,7 +142,9 @@ const routeLoginFactory = config => {
|
|
|
142
142
|
client_id: config.oauth.clientId,
|
|
143
143
|
response_type: "code",
|
|
144
144
|
redirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),
|
|
145
|
-
state
|
|
145
|
+
state,
|
|
146
|
+
scope,
|
|
147
|
+
audience: config.oauth.audience
|
|
146
148
|
});
|
|
147
149
|
throw redirect(302, `${authorizeEndpoint}?${params}`);
|
|
148
150
|
}
|
|
@@ -224,16 +226,15 @@ function armor(config) {
|
|
|
224
226
|
};
|
|
225
227
|
}
|
|
226
228
|
/**
|
|
227
|
-
* Some IdP's expose a /.well-known/openid-
|
|
228
|
-
* Use that to
|
|
229
|
+
* Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.
|
|
230
|
+
* Use that to create your config.
|
|
229
231
|
* @param config
|
|
230
232
|
* @param fetch
|
|
231
233
|
*/
|
|
232
|
-
async function
|
|
233
|
-
var
|
|
234
|
-
const url = (_config$oauth$openIdC = config.oauth.openIdConfigUrl) != null ? _config$oauth$openIdC : `${config.oauth.baseUrl}/.well-known/openid-configuration`;
|
|
234
|
+
async function armorConfigFromOpenId(config, fetch) {
|
|
235
|
+
var _body$end_session_end;
|
|
235
236
|
const fetchToUse = fetch != null ? fetch : global.fetch;
|
|
236
|
-
const response = await fetchToUse(
|
|
237
|
+
const response = await fetchToUse(config.oauth.openIdConfigEndpoint, {
|
|
237
238
|
headers: {
|
|
238
239
|
Accept: "application/json"
|
|
239
240
|
}
|
|
@@ -243,7 +244,7 @@ async function armorFromOpenIdConfig(config, fetch) {
|
|
|
243
244
|
throw new ArmorOpenIdConfigError(text);
|
|
244
245
|
}
|
|
245
246
|
const body = await response.json();
|
|
246
|
-
return
|
|
247
|
+
return {
|
|
247
248
|
...config,
|
|
248
249
|
oauth: {
|
|
249
250
|
...config.oauth,
|
|
@@ -253,7 +254,7 @@ async function armorFromOpenIdConfig(config, fetch) {
|
|
|
253
254
|
jwksUrl: body.jwks_uri,
|
|
254
255
|
logoutEndpoint: (_body$end_session_end = body.end_session_endpoint) != null ? _body$end_session_end : undefined
|
|
255
256
|
}
|
|
256
|
-
}
|
|
257
|
+
};
|
|
257
258
|
}
|
|
258
259
|
function armorCookiesGetTokens(cookies) {
|
|
259
260
|
const tokens = cookieGet(cookies, COOKIE_TOKENS);
|
|
@@ -261,5 +262,5 @@ function armorCookiesGetTokens(cookies) {
|
|
|
261
262
|
return tokens;
|
|
262
263
|
}
|
|
263
264
|
|
|
264
|
-
export { ARMOR_LOGIN, ARMOR_LOGOUT, armor,
|
|
265
|
+
export { ARMOR_LOGIN, ARMOR_LOGOUT, armor, armorConfigFromOpenId, armorCookiesGetTokens };
|
|
265
266
|
//# sourceMappingURL=index.esm.js.map
|
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 {\n\tjwtDecrypt,\n\tJWTPayload,\n\tjwtVerify,\n\tJWTVerifyGetKey,\n\tJWTVerifyOptions,\n} from \"jose\";\n\nexport function jwtVerifyAndDecryptIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyAndDecryptToken(\n\t\tconfig,\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n}\n\nexport function jwtVerifyAndDecryptAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyAndDecryptToken(\n\t\tconfig,\n\t\tjwks,\n\t\t{ issuer: config.oauth.issuer },\n\t\taccessToken,\n\t);\n}\n\nfunction jwtIsEncryptedToken(token: string): boolean {\n\tconst parts = token.split(\".\");\n\treturn parts.length === 5;\n}\n\nasync function jwtVerifyAndDecryptToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload> {\n\tif (jwtIsEncryptedToken(token)) {\n\t\tconst secret = new TextEncoder().encode(config.oauth.clientSecret);\n\t\tconst { payload } = await jwtDecrypt(token, secret, opts);\n\t\treturn payload;\n\t}\n\n\tconst { payload } = await jwtVerify(token, jwks, opts);\n\treturn payload;\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { strTrimEnd, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange } from \"../utils/utils\";\nimport {\n\tCOOKIE_STATE,\n\tCOOKIE_TOKENS,\n\tcookieGetAndDelete,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport {\n\tjwtVerifyAndDecryptAccessToken,\n\tjwtVerifyAndDecryptIdToken,\n} from \"../utils/jwt\";\n\nexport const ROUTE_PATH_REDIRECT_LOGIN = \"/_armor/redirect/login\";\n\nexport const routeRedirectLoginFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksUrl ??\n\t\t\t`${strTrimEnd(config.oauth.issuer, \"/\")}/.well-known/jwks.json`,\n\t);\n\n\tconst tokenUrl =\n\t\tconfig.oauth.tokenEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst sessionLogin =\n\t\tconfig.session?.login ??\n\t\t((event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens));\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\t\tcode,\n\t\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t}).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\t\t\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\t\t\tif (state !== stateCookie) {\n\t\t\t\tthrow new Error(\"State do not match\");\n\t\t\t}\n\n\t\t\tconst code = event.url.searchParams.get(\"code\") ?? undefined;\n\t\t\tthrowIfUndefined(code);\n\n\t\t\tconst exchange = await exchangeCodeForToken(\n\t\t\t\tfetch,\n\t\t\t\tevent.url.origin,\n\t\t\t\tcode,\n\t\t\t);\n\n\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\tjwtVerifyAndDecryptIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAndDecryptAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tawait sessionLogin(event, {\n\t\t\t\texchange,\n\t\t\t\tidToken: idToken as ArmorIdToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\n\nexport const ROUTE_PATH_LOGIN = \"/_armor/login\";\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { noop } from \"@nekm/core\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst logout = config.session?.logout ?? noop;\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tawait logout(event);\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGOUT } from \"./redirect-logout\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat } from \"../utils/utils\";\n\nexport const ROUTE_PATH_LOGOUT = \"/_armor/logout\";\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tlogout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import type { Handle } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { routeLoginFactory } from \"./login\";\nimport { routeLogoutFactory } from \"./logout\";\nimport { routeRedirectLogoutFactory } from \"./redirect-logout\";\nimport { routeRedirectLoginFactory } from \"./redirect-login\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n]);\n\nexport function routeCreate(config: ArmorConfig): Map<string, Handle> {\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route.handle]),\n\t);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends Error {}\n","import { error, redirect, type Handle, Cookies } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { ROUTE_PATH_LOGOUT } from \"./routes/logout\";\nimport { routeCreate } from \"./routes/routes\";\nimport { COOKIE_TOKENS, cookieGet } from \"./utils/cookie\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\n\nexport type { ArmorConfig, ArmorTokens };\n\nexport const ARMOR_LOGIN = ROUTE_PATH_LOGIN;\nexport const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routes = routeCreate(config);\n\tconst sessionExists =\n\t\tconfig.session?.exists ??\n\t\t((event) => Boolean(event.cookies.get(COOKIE_TOKENS)));\n\n\treturn async ({ event, resolve }) => {\n\t\tconst routeHandle = routes.get(event.url.pathname);\n\n\t\tif (routeHandle) {\n\t\t\tawait routeHandle({ event, resolve });\n\n\t\t\t// Handle should redirect. If it doesn't, something is wrong.\n\t\t\tthrow error(500, \"Illegal state\");\n\t\t}\n\n\t\tconst exists = await sessionExists(event);\n\n\t\tif (!exists) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn resolve(event);\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuiration that specifies how to configure.\n * Use that to autoconfigure your instance.\n * @param config\n * @param fetch\n */\nexport async function armorFromOpenIdConfig(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n) {\n\tconst url =\n\t\tconfig.oauth.openIdConfigUrl ??\n\t\t`${config.oauth.baseUrl}/.well-known/openid-configuration`;\n\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(url, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn armor({\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksUrl: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t},\n\t});\n}\n\nexport function armorCookiesGetTokens(cookies: Cookies): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\tthrowIfUndefined(tokens);\n\treturn tokens;\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","jwtVerifyAndDecryptIdToken","config","jwks","idToken","jwtVerifyAndDecryptToken","issuer","oauth","audience","clientId","jwtVerifyAndDecryptAccessToken","accessToken","jwtIsEncryptedToken","token","parts","split","length","opts","secret","TextEncoder","encode","clientSecret","payload","jwtDecrypt","jwtVerify","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksUrl","_config$oauth$tokenEn","_config$session$login","_config$session","jwksUrl","URL","tokenUrl","tokenEndpoint","baseUrl","sessionLogin","session","login","event","tokens","exchangeCodeForToken","fetch","code","response","method","headers","Accept","body","URLSearchParams","grant_type","client_id","client_secret","redirect_uri","toString","ok","error","text","Error","json","handle","_event$url$searchPara","_event$url$searchPara2","state","url","searchParams","stateCookie","throwIfUndefined","exchange","createRemoteJWKSet","Promise","all","redirect","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","params","queryParamsCreate","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","_config$session$logou","logoutEndpoint","logout","noop","ROUTE_PATH_LOGOUT","routeLogoutFactory","logout_uri","routeFactories","routeCreate","Map","map","routeFactory","filter","route","Boolean","ArmorOpenIdConfigError","ARMOR_LOGIN","ARMOR_LOGOUT","armor","_config$session$exist","routes","sessionExists","exists","resolve","routeHandle","pathname","armorFromOpenIdConfig","_config$oauth$openIdC","_body$end_session_end","openIdConfigUrl","fetchToUse","global","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint","armorCookiesGetTokens"],"mappings":"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"}
|
|
1
|
+
{"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 { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload> {\n\tconst opts: JWTVerifyOptions = { issuer: config.oauth.issuer };\n\n\tif (config.oauth.audience) {\n\t\topts.audience = config.oauth.audience;\n\t}\n\n\treturn jwtVerifyToken(jwks, opts, accessToken);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload> {\n\tconst { payload } = await jwtVerify(token, jwks, opts);\n\treturn payload;\n}\n","import { 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 =\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\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst params: Record<string, string> = {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\tcode,\n\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\tscope,\n\t\t};\n\n\t\tif (config.oauth.audience) {\n\t\t\tparams.audience = config.oauth.audience;\n\t\t}\n\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams(params).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\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 authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t\tscope,\n\t\t\t\taudience: config.oauth.audience,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { 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-configuration that specifies how to configure.\n * Use that to create your config.\n * @param config\n * @param fetch\n */\nexport async function armorConfigFromOpenId(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n): Promise<ArmorConfig> {\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(config.oauth.openIdConfigEndpoint, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn {\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\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","jwtVerifyIdToken","config","jwks","idToken","jwtVerifyToken","issuer","oauth","audience","clientId","jwtVerifyAccessToken","accessToken","opts","token","payload","jwtVerify","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksUrl","_config$oauth$tokenEn","_config$session$login","_config$session","_config$oauth$scope","jwksUrl","URL","tokenUrl","tokenEndpoint","baseUrl","sessionLogin","session","login","event","tokens","exchangeCodeForToken","fetch","code","params","grant_type","client_id","client_secret","clientSecret","redirect_uri","response","method","headers","Accept","body","URLSearchParams","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","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","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint","armorCookiesGetTokens"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -41,29 +41,22 @@ function cookieGet(cookies, key) {
|
|
|
41
41
|
return !value ? undefined : JSON.parse(value);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
function
|
|
45
|
-
return
|
|
44
|
+
function jwtVerifyIdToken(config, jwks, idToken) {
|
|
45
|
+
return jwtVerifyToken(jwks, {
|
|
46
46
|
issuer: config.oauth.issuer,
|
|
47
47
|
audience: config.oauth.clientId
|
|
48
48
|
}, idToken);
|
|
49
49
|
}
|
|
50
|
-
function
|
|
51
|
-
|
|
50
|
+
function jwtVerifyAccessToken(config, jwks, accessToken) {
|
|
51
|
+
const opts = {
|
|
52
52
|
issuer: config.oauth.issuer
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
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;
|
|
53
|
+
};
|
|
54
|
+
if (config.oauth.audience) {
|
|
55
|
+
opts.audience = config.oauth.audience;
|
|
66
56
|
}
|
|
57
|
+
return jwtVerifyToken(jwks, opts, accessToken);
|
|
58
|
+
}
|
|
59
|
+
async function jwtVerifyToken(jwks, opts, token) {
|
|
67
60
|
const {
|
|
68
61
|
payload
|
|
69
62
|
} = await jose.jwtVerify(token, jwks, opts);
|
|
@@ -72,24 +65,30 @@ async function jwtVerifyAndDecryptToken(config, jwks, opts, token) {
|
|
|
72
65
|
|
|
73
66
|
const ROUTE_PATH_REDIRECT_LOGIN = "/_armor/redirect/login";
|
|
74
67
|
const routeRedirectLoginFactory = config => {
|
|
75
|
-
var _config$oauth$jwksUrl, _config$oauth$tokenEn, _config$session$login, _config$session;
|
|
68
|
+
var _config$oauth$jwksUrl, _config$oauth$tokenEn, _config$session$login, _config$session, _config$oauth$scope;
|
|
76
69
|
const jwksUrl = new URL((_config$oauth$jwksUrl = config.oauth.jwksUrl) != null ? _config$oauth$jwksUrl : `${core.strTrimEnd(config.oauth.issuer, "/")}/.well-known/jwks.json`);
|
|
77
70
|
const tokenUrl = (_config$oauth$tokenEn = config.oauth.tokenEndpoint) != null ? _config$oauth$tokenEn : urlConcat(config.oauth.baseUrl, "oauth2/token");
|
|
78
71
|
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);
|
|
72
|
+
const scope = (_config$oauth$scope = config.oauth.scope) != null ? _config$oauth$scope : "openid profile email";
|
|
79
73
|
async function exchangeCodeForToken(fetch, origin, code) {
|
|
74
|
+
const params = {
|
|
75
|
+
grant_type: "authorization_code",
|
|
76
|
+
client_id: config.oauth.clientId,
|
|
77
|
+
client_secret: config.oauth.clientSecret,
|
|
78
|
+
code,
|
|
79
|
+
redirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),
|
|
80
|
+
scope
|
|
81
|
+
};
|
|
82
|
+
if (config.oauth.audience) {
|
|
83
|
+
params.audience = config.oauth.audience;
|
|
84
|
+
}
|
|
80
85
|
const response = await fetch(tokenUrl, {
|
|
81
86
|
method: "POST",
|
|
82
87
|
headers: {
|
|
83
88
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
84
89
|
Accept: "application/json"
|
|
85
90
|
},
|
|
86
|
-
body: new URLSearchParams(
|
|
87
|
-
grant_type: "authorization_code",
|
|
88
|
-
client_id: config.oauth.clientId,
|
|
89
|
-
client_secret: config.oauth.clientSecret,
|
|
90
|
-
code,
|
|
91
|
-
redirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN)
|
|
92
|
-
}).toString()
|
|
91
|
+
body: new URLSearchParams(params).toString()
|
|
93
92
|
});
|
|
94
93
|
if (!response.ok) {
|
|
95
94
|
const error = await response.text();
|
|
@@ -116,7 +115,7 @@ const routeRedirectLoginFactory = config => {
|
|
|
116
115
|
core.throwIfUndefined(code);
|
|
117
116
|
const exchange = await exchangeCodeForToken(fetch, event.url.origin, code);
|
|
118
117
|
const jwks = jose.createRemoteJWKSet(jwksUrl);
|
|
119
|
-
const [idToken, accessToken] = await Promise.all([
|
|
118
|
+
const [idToken, accessToken] = await Promise.all([jwtVerifyIdToken(config, jwks, exchange.id_token), jwtVerifyAccessToken(config, jwks, exchange.access_token)]);
|
|
120
119
|
await sessionLogin(event, {
|
|
121
120
|
exchange,
|
|
122
121
|
idToken: idToken,
|
|
@@ -129,8 +128,9 @@ const routeRedirectLoginFactory = config => {
|
|
|
129
128
|
|
|
130
129
|
const ROUTE_PATH_LOGIN = "/_armor/login";
|
|
131
130
|
const routeLoginFactory = config => {
|
|
132
|
-
var _config$oauth$authori;
|
|
131
|
+
var _config$oauth$authori, _config$oauth$scope;
|
|
133
132
|
const authorizeEndpoint = (_config$oauth$authori = config.oauth.authorizeEndpoint) != null ? _config$oauth$authori : urlConcat(config.oauth.baseUrl, "oauth2/authorize");
|
|
133
|
+
const scope = (_config$oauth$scope = config.oauth.scope) != null ? _config$oauth$scope : "openid profile email";
|
|
134
134
|
return {
|
|
135
135
|
path: ROUTE_PATH_LOGIN,
|
|
136
136
|
async handle({
|
|
@@ -142,7 +142,9 @@ const routeLoginFactory = config => {
|
|
|
142
142
|
client_id: config.oauth.clientId,
|
|
143
143
|
response_type: "code",
|
|
144
144
|
redirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),
|
|
145
|
-
state
|
|
145
|
+
state,
|
|
146
|
+
scope,
|
|
147
|
+
audience: config.oauth.audience
|
|
146
148
|
});
|
|
147
149
|
throw kit.redirect(302, `${authorizeEndpoint}?${params}`);
|
|
148
150
|
}
|
|
@@ -224,16 +226,15 @@ function armor(config) {
|
|
|
224
226
|
};
|
|
225
227
|
}
|
|
226
228
|
/**
|
|
227
|
-
* Some IdP's expose a /.well-known/openid-
|
|
228
|
-
* Use that to
|
|
229
|
+
* Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.
|
|
230
|
+
* Use that to create your config.
|
|
229
231
|
* @param config
|
|
230
232
|
* @param fetch
|
|
231
233
|
*/
|
|
232
|
-
async function
|
|
233
|
-
var
|
|
234
|
-
const url = (_config$oauth$openIdC = config.oauth.openIdConfigUrl) != null ? _config$oauth$openIdC : `${config.oauth.baseUrl}/.well-known/openid-configuration`;
|
|
234
|
+
async function armorConfigFromOpenId(config, fetch) {
|
|
235
|
+
var _body$end_session_end;
|
|
235
236
|
const fetchToUse = fetch != null ? fetch : global.fetch;
|
|
236
|
-
const response = await fetchToUse(
|
|
237
|
+
const response = await fetchToUse(config.oauth.openIdConfigEndpoint, {
|
|
237
238
|
headers: {
|
|
238
239
|
Accept: "application/json"
|
|
239
240
|
}
|
|
@@ -243,7 +244,7 @@ async function armorFromOpenIdConfig(config, fetch) {
|
|
|
243
244
|
throw new ArmorOpenIdConfigError(text);
|
|
244
245
|
}
|
|
245
246
|
const body = await response.json();
|
|
246
|
-
return
|
|
247
|
+
return {
|
|
247
248
|
...config,
|
|
248
249
|
oauth: {
|
|
249
250
|
...config.oauth,
|
|
@@ -253,7 +254,7 @@ async function armorFromOpenIdConfig(config, fetch) {
|
|
|
253
254
|
jwksUrl: body.jwks_uri,
|
|
254
255
|
logoutEndpoint: (_body$end_session_end = body.end_session_endpoint) != null ? _body$end_session_end : undefined
|
|
255
256
|
}
|
|
256
|
-
}
|
|
257
|
+
};
|
|
257
258
|
}
|
|
258
259
|
function armorCookiesGetTokens(cookies) {
|
|
259
260
|
const tokens = cookieGet(cookies, COOKIE_TOKENS);
|
|
@@ -264,6 +265,6 @@ function armorCookiesGetTokens(cookies) {
|
|
|
264
265
|
exports.ARMOR_LOGIN = ARMOR_LOGIN;
|
|
265
266
|
exports.ARMOR_LOGOUT = ARMOR_LOGOUT;
|
|
266
267
|
exports.armor = armor;
|
|
268
|
+
exports.armorConfigFromOpenId = armorConfigFromOpenId;
|
|
267
269
|
exports.armorCookiesGetTokens = armorCookiesGetTokens;
|
|
268
|
-
exports.armorFromOpenIdConfig = armorFromOpenIdConfig;
|
|
269
270
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/utils/utils.ts","../src/utils/cookie.ts","../src/utils/jwt.ts","../src/routes/redirect-login.ts","../src/routes/login.ts","../src/routes/redirect-logout.ts","../src/routes/logout.ts","../src/routes/routes.ts","../src/errors.ts","../src/index.ts"],"sourcesContent":["import { strTrimEnd, strTrimStart } from \"@nekm/core\";\nimport type { ArmorTokenExchange } from \"../contracts\";\n\nexport function urlConcat(origin: string, path: string): string {\n\treturn [strTrimEnd(origin, \"/\"), strTrimStart(path, \"/\")].join(\"/\");\n}\n\nexport function isTokenExchange(value: unknown): value is ArmorTokenExchange {\n\tif (typeof value !== \"object\" || value === null) return false;\n\n\tconst obj = value as Record<string, unknown>;\n\n\treturn (\n\t\ttypeof obj.access_token === \"string\" &&\n\t\tobj.token_type === \"Bearer\" &&\n\t\ttypeof obj.expires_in === \"number\" &&\n\t\t// Optional fields\n\t\t(typeof obj.id_token === \"string\" || obj.id_token === undefined) &&\n\t\t(typeof obj.refresh_token === \"string\" ||\n\t\t\tobj.refresh_token === undefined) &&\n\t\t(typeof obj.scope === \"string\" || obj.scope === undefined)\n\t);\n}\n","import { Cookies } from \"@sveltejs/kit\";\n\nexport const COOKIE_TOKENS = \"tokens\";\nexport const COOKIE_STATE = \"state\";\n\nconst cookieDeleteOptions = Object.freeze({ path: \"/\" });\n\nconst cookieSetOptions = Object.freeze({\n\t...cookieDeleteOptions,\n\thttpOnly: true,\n\tsecure: true,\n\tsameSite: \"lax\",\n\tmaxAge: 1800, // 30 minutes\n});\n\nexport function cookieSet(\n\tcookies: Cookies,\n\tkey: string,\n\tvalue: string | object,\n) {\n\tcookies.set(key, JSON.stringify(value), cookieSetOptions);\n}\n\nexport function cookieGetAndDelete<T>(\n\tcookies: Cookies,\n\tkey: string,\n): T | undefined {\n\tconst value = cookieGet<T>(cookies, key);\n\n\tif (value) {\n\t\tcookies.delete(key, cookieDeleteOptions);\n\t}\n\n\treturn value;\n}\n\nexport function cookieGet<T>(cookies: Cookies, key: string): T | undefined {\n\tconst value = cookies.get(key);\n\n\treturn !value ? undefined : JSON.parse(value);\n}\n","import { ArmorConfig } from \"../contracts\";\nimport {\n\tjwtDecrypt,\n\tJWTPayload,\n\tjwtVerify,\n\tJWTVerifyGetKey,\n\tJWTVerifyOptions,\n} from \"jose\";\n\nexport function jwtVerifyAndDecryptIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyAndDecryptToken(\n\t\tconfig,\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n}\n\nexport function jwtVerifyAndDecryptAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyAndDecryptToken(\n\t\tconfig,\n\t\tjwks,\n\t\t{ issuer: config.oauth.issuer },\n\t\taccessToken,\n\t);\n}\n\nfunction jwtIsEncryptedToken(token: string): boolean {\n\tconst parts = token.split(\".\");\n\treturn parts.length === 5;\n}\n\nasync function jwtVerifyAndDecryptToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload> {\n\tif (jwtIsEncryptedToken(token)) {\n\t\tconst secret = new TextEncoder().encode(config.oauth.clientSecret);\n\t\tconst { payload } = await jwtDecrypt(token, secret, opts);\n\t\treturn payload;\n\t}\n\n\tconst { payload } = await jwtVerify(token, jwks, opts);\n\treturn payload;\n}\n","import { redirect } from \"@sveltejs/kit\";\nimport type {\n\tArmorConfig,\n\tArmorIdToken,\n\tArmorTokenExchange,\n} from \"../contracts\";\nimport { strTrimEnd, throwIfUndefined } from \"@nekm/core\";\nimport { createRemoteJWKSet } from \"jose\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat, isTokenExchange } from \"../utils/utils\";\nimport {\n\tCOOKIE_STATE,\n\tCOOKIE_TOKENS,\n\tcookieGetAndDelete,\n\tcookieSet,\n} from \"../utils/cookie\";\nimport {\n\tjwtVerifyAndDecryptAccessToken,\n\tjwtVerifyAndDecryptIdToken,\n} from \"../utils/jwt\";\n\nexport const ROUTE_PATH_REDIRECT_LOGIN = \"/_armor/redirect/login\";\n\nexport const routeRedirectLoginFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\tconst jwksUrl = new URL(\n\t\tconfig.oauth.jwksUrl ??\n\t\t\t`${strTrimEnd(config.oauth.issuer, \"/\")}/.well-known/jwks.json`,\n\t);\n\n\tconst tokenUrl =\n\t\tconfig.oauth.tokenEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/token\");\n\n\tconst sessionLogin =\n\t\tconfig.session?.login ??\n\t\t((event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens));\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\t\tcode,\n\t\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t}).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = event.url.searchParams.get(\"state\") ?? undefined;\n\t\t\tconst stateCookie = cookieGetAndDelete(event.cookies, COOKIE_STATE);\n\n\t\t\tif (state !== stateCookie) {\n\t\t\t\tthrow new Error(\"State do not match\");\n\t\t\t}\n\n\t\t\tconst code = event.url.searchParams.get(\"code\") ?? undefined;\n\t\t\tthrowIfUndefined(code);\n\n\t\t\tconst exchange = await exchangeCodeForToken(\n\t\t\t\tfetch,\n\t\t\t\tevent.url.origin,\n\t\t\t\tcode,\n\t\t\t);\n\n\t\t\tconst jwks = createRemoteJWKSet(jwksUrl);\n\n\t\t\tconst [idToken, accessToken] = await Promise.all([\n\t\t\t\tjwtVerifyAndDecryptIdToken(config, jwks, exchange.id_token),\n\t\t\t\tjwtVerifyAndDecryptAccessToken(config, jwks, exchange.access_token),\n\t\t\t]);\n\n\t\t\tawait sessionLogin(event, {\n\t\t\t\texchange,\n\t\t\t\tidToken: idToken as ArmorIdToken,\n\t\t\t\taccessToken,\n\t\t\t});\n\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGIN } from \"./redirect-login\";\nimport { randomUUID } from \"node:crypto\";\nimport type { RouteFactory } from \"./routes\";\nimport { COOKIE_STATE, cookieSet } from \"../utils/cookie\";\nimport { urlConcat } from \"../utils/utils\";\n\nexport const ROUTE_PATH_LOGIN = \"/_armor/login\";\n\nexport const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {\n\tconst authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { noop } from \"@nekm/core\";\nimport type { RouteFactory } from \"./routes\";\n\nexport const ROUTE_PATH_REDIRECT_LOGOUT = \"/_armor/redirect/logout\";\n\nexport const routeRedirectLogoutFactory: RouteFactory = (\n\tconfig: ArmorConfig,\n) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\tconst logout = config.session?.logout ?? noop;\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tawait logout(event);\n\t\t\tthrow redirect(302, \"/\");\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { queryParamsCreate } from \"@nekm/core\";\nimport { ROUTE_PATH_REDIRECT_LOGOUT } from \"./redirect-logout\";\nimport type { RouteFactory } from \"./routes\";\nimport { urlConcat } from \"../utils/utils\";\n\nexport const ROUTE_PATH_LOGOUT = \"/_armor/logout\";\n\nexport const routeLogoutFactory: RouteFactory = (config: ArmorConfig) => {\n\t// Check if the oauth provider supports a logout path.\n\tif (!config.oauth.logoutEndpoint) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGOUT,\n\t\tasync handle({ event }) {\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tlogout_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGOUT),\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${config.oauth.logoutEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import type { Handle } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { routeLoginFactory } from \"./login\";\nimport { routeLogoutFactory } from \"./logout\";\nimport { routeRedirectLogoutFactory } from \"./redirect-logout\";\nimport { routeRedirectLoginFactory } from \"./redirect-login\";\n\nexport interface Route {\n\treadonly path: string;\n\treadonly handle: Handle;\n}\n\nexport type RouteFactory = (config: ArmorConfig) => Route | undefined;\n\nconst routeFactories = Object.freeze([\n\trouteLoginFactory,\n\trouteLogoutFactory,\n\trouteRedirectLoginFactory,\n\trouteRedirectLogoutFactory,\n]);\n\nexport function routeCreate(config: ArmorConfig): Map<string, Handle> {\n\treturn new Map(\n\t\trouteFactories\n\t\t\t.map((routeFactory) => routeFactory(config))\n\t\t\t.filter((route) => Boolean(route))\n\t\t\t// @ts-expect-error Incorrect typing error.\n\t\t\t.map((route) => [route.path, route.handle]),\n\t);\n}\n","export class ArmorError extends Error {}\nexport class ArmorOpenIdConfigError extends Error {}\n","import { error, redirect, type Handle, Cookies } from \"@sveltejs/kit\";\nimport { ROUTE_PATH_LOGIN } from \"./routes/login\";\nimport type { ArmorConfig, ArmorOpenIdConfig, ArmorTokens } from \"./contracts\";\nimport { ROUTE_PATH_LOGOUT } from \"./routes/logout\";\nimport { routeCreate } from \"./routes/routes\";\nimport { COOKIE_TOKENS, cookieGet } from \"./utils/cookie\";\nimport { throwIfUndefined } from \"@nekm/core\";\nimport { ArmorOpenIdConfigError } from \"./errors\";\n\nexport type { ArmorConfig, ArmorTokens };\n\nexport const ARMOR_LOGIN = ROUTE_PATH_LOGIN;\nexport const ARMOR_LOGOUT = ROUTE_PATH_LOGOUT;\n\nexport function armor(config: ArmorConfig): Handle {\n\tconst routes = routeCreate(config);\n\tconst sessionExists =\n\t\tconfig.session?.exists ??\n\t\t((event) => Boolean(event.cookies.get(COOKIE_TOKENS)));\n\n\treturn async ({ event, resolve }) => {\n\t\tconst routeHandle = routes.get(event.url.pathname);\n\n\t\tif (routeHandle) {\n\t\t\tawait routeHandle({ event, resolve });\n\n\t\t\t// Handle should redirect. If it doesn't, something is wrong.\n\t\t\tthrow error(500, \"Illegal state\");\n\t\t}\n\n\t\tconst exists = await sessionExists(event);\n\n\t\tif (!exists) {\n\t\t\tthrow redirect(302, ROUTE_PATH_LOGIN);\n\t\t}\n\n\t\treturn resolve(event);\n\t};\n}\n\n/**\n * Some IdP's expose a /.well-known/openid-configuiration that specifies how to configure.\n * Use that to autoconfigure your instance.\n * @param config\n * @param fetch\n */\nexport async function armorFromOpenIdConfig(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n) {\n\tconst url =\n\t\tconfig.oauth.openIdConfigUrl ??\n\t\t`${config.oauth.baseUrl}/.well-known/openid-configuration`;\n\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(url, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn armor({\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\tjwksUrl: body.jwks_uri,\n\t\t\tlogoutEndpoint: body.end_session_endpoint ?? undefined,\n\t\t},\n\t});\n}\n\nexport function armorCookiesGetTokens(cookies: Cookies): ArmorTokens {\n\tconst tokens = cookieGet<ArmorTokens>(cookies, COOKIE_TOKENS);\n\tthrowIfUndefined(tokens);\n\treturn tokens;\n}\n"],"names":["urlConcat","origin","path","strTrimEnd","strTrimStart","join","isTokenExchange","value","obj","access_token","token_type","expires_in","id_token","undefined","refresh_token","scope","COOKIE_TOKENS","COOKIE_STATE","cookieDeleteOptions","Object","freeze","cookieSetOptions","httpOnly","secure","sameSite","maxAge","cookieSet","cookies","key","set","JSON","stringify","cookieGetAndDelete","cookieGet","delete","get","parse","jwtVerifyAndDecryptIdToken","config","jwks","idToken","jwtVerifyAndDecryptToken","issuer","oauth","audience","clientId","jwtVerifyAndDecryptAccessToken","accessToken","jwtIsEncryptedToken","token","parts","split","length","opts","secret","TextEncoder","encode","clientSecret","payload","jwtDecrypt","jwtVerify","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksUrl","_config$oauth$tokenEn","_config$session$login","_config$session","jwksUrl","URL","tokenUrl","tokenEndpoint","baseUrl","sessionLogin","session","login","event","tokens","exchangeCodeForToken","fetch","code","response","method","headers","Accept","body","URLSearchParams","grant_type","client_id","client_secret","redirect_uri","toString","ok","error","text","Error","json","handle","_event$url$searchPara","_event$url$searchPara2","state","url","searchParams","stateCookie","throwIfUndefined","exchange","createRemoteJWKSet","Promise","all","redirect","ROUTE_PATH_LOGIN","routeLoginFactory","_config$oauth$authori","authorizeEndpoint","randomUUID","params","queryParamsCreate","response_type","ROUTE_PATH_REDIRECT_LOGOUT","routeRedirectLogoutFactory","_config$session$logou","logoutEndpoint","logout","noop","ROUTE_PATH_LOGOUT","routeLogoutFactory","logout_uri","routeFactories","routeCreate","Map","map","routeFactory","filter","route","Boolean","ArmorOpenIdConfigError","ARMOR_LOGIN","ARMOR_LOGOUT","armor","_config$session$exist","routes","sessionExists","exists","resolve","routeHandle","pathname","armorFromOpenIdConfig","_config$oauth$openIdC","_body$end_session_end","openIdConfigUrl","fetchToUse","global","token_endpoint","authorization_endpoint","jwks_uri","end_session_endpoint","armorCookiesGetTokens"],"mappings":"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"}
|
|
1
|
+
{"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 { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from \"jose\";\n\nexport function jwtVerifyIdToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\tidToken: string,\n): Promise<JWTPayload> {\n\treturn jwtVerifyToken(\n\t\tjwks,\n\t\t{\n\t\t\tissuer: config.oauth.issuer,\n\t\t\taudience: config.oauth.clientId,\n\t\t},\n\t\tidToken,\n\t);\n}\n\nexport function jwtVerifyAccessToken(\n\tconfig: ArmorConfig,\n\tjwks: JWTVerifyGetKey,\n\taccessToken: string,\n): Promise<JWTPayload> {\n\tconst opts: JWTVerifyOptions = { issuer: config.oauth.issuer };\n\n\tif (config.oauth.audience) {\n\t\topts.audience = config.oauth.audience;\n\t}\n\n\treturn jwtVerifyToken(jwks, opts, accessToken);\n}\n\nasync function jwtVerifyToken(\n\tjwks: JWTVerifyGetKey,\n\topts: JWTVerifyOptions,\n\ttoken: string,\n): Promise<JWTPayload> {\n\tconst { payload } = await jwtVerify(token, jwks, opts);\n\treturn payload;\n}\n","import { 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 =\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\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\tasync function exchangeCodeForToken(\n\t\tfetch: typeof global.fetch,\n\t\torigin: string,\n\t\tcode: string,\n\t): Promise<ArmorTokenExchange> {\n\t\tconst params: Record<string, string> = {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: config.oauth.clientId,\n\t\t\tclient_secret: config.oauth.clientSecret,\n\t\t\tcode,\n\t\t\tredirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\tscope,\n\t\t};\n\n\t\tif (config.oauth.audience) {\n\t\t\tparams.audience = config.oauth.audience;\n\t\t}\n\n\t\tconst response = await fetch(tokenUrl, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\tAccept: \"application/json\",\n\t\t\t},\n\t\t\tbody: new URLSearchParams(params).toString(),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t\t}\n\n\t\tconst token = await response.json();\n\n\t\tif (!isTokenExchange(token)) {\n\t\t\tthrow new Error(\"Response is not a valid token exchange.\");\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tpath: ROUTE_PATH_REDIRECT_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\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 authorizeEndpoint =\n\t\tconfig.oauth.authorizeEndpoint ??\n\t\turlConcat(config.oauth.baseUrl, \"oauth2/authorize\");\n\n\tconst scope = config.oauth.scope ?? \"openid profile email\";\n\n\treturn {\n\t\tpath: ROUTE_PATH_LOGIN,\n\t\tasync handle({ event }) {\n\t\t\tconst state = randomUUID();\n\t\t\tcookieSet(event.cookies, COOKIE_STATE, state);\n\n\t\t\tconst params = queryParamsCreate({\n\t\t\t\tclient_id: config.oauth.clientId,\n\t\t\t\tresponse_type: \"code\",\n\t\t\t\tredirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),\n\t\t\t\tstate,\n\t\t\t\tscope,\n\t\t\t\taudience: config.oauth.audience,\n\t\t\t});\n\n\t\t\tthrow redirect(302, `${authorizeEndpoint}?${params}`);\n\t\t},\n\t};\n};\n","import { redirect } from \"@sveltejs/kit\";\nimport type { ArmorConfig } from \"../contracts\";\nimport { 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-configuration that specifies how to configure.\n * Use that to create your config.\n * @param config\n * @param fetch\n */\nexport async function armorConfigFromOpenId(\n\tconfig: ArmorOpenIdConfig,\n\tfetch?: typeof global.fetch,\n): Promise<ArmorConfig> {\n\tconst fetchToUse = fetch ?? global.fetch;\n\n\tconst response = await fetchToUse(config.oauth.openIdConfigEndpoint, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t});\n\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new ArmorOpenIdConfigError(text);\n\t}\n\n\tconst body = await response.json();\n\n\treturn {\n\t\t...config,\n\t\toauth: {\n\t\t\t...config.oauth,\n\t\t\ttokenEndpoint: body.token_endpoint,\n\t\t\tauthorizeEndpoint: body.authorization_endpoint,\n\t\t\tissuer: body.issuer,\n\t\t\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","jwtVerifyIdToken","config","jwks","idToken","jwtVerifyToken","issuer","oauth","audience","clientId","jwtVerifyAccessToken","accessToken","opts","token","payload","jwtVerify","ROUTE_PATH_REDIRECT_LOGIN","routeRedirectLoginFactory","_config$oauth$jwksUrl","_config$oauth$tokenEn","_config$session$login","_config$session","_config$oauth$scope","jwksUrl","URL","tokenUrl","tokenEndpoint","baseUrl","sessionLogin","session","login","event","tokens","exchangeCodeForToken","fetch","code","params","grant_type","client_id","client_secret","clientSecret","redirect_uri","response","method","headers","Accept","body","URLSearchParams","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","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","armorConfigFromOpenId","_body$end_session_end","fetchToUse","global","openIdConfigEndpoint","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
2
|
import { JWTPayload, JWTVerifyGetKey } from "jose";
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
3
|
+
export declare function jwtVerifyIdToken(config: ArmorConfig, jwks: JWTVerifyGetKey, idToken: string): Promise<JWTPayload>;
|
|
4
|
+
export declare function jwtVerifyAccessToken(config: ArmorConfig, jwks: JWTVerifyGetKey, accessToken: string): Promise<JWTPayload>;
|
package/package.json
CHANGED
package/src/contracts.ts
CHANGED
|
@@ -50,12 +50,16 @@ export interface ArmorConfig {
|
|
|
50
50
|
readonly authorizeEndpoint?: string;
|
|
51
51
|
readonly logoutEndpoint?: string;
|
|
52
52
|
readonly tokenEndpoint?: string;
|
|
53
|
+
readonly scope?: string;
|
|
54
|
+
readonly audience?: string;
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
export interface ArmorOpenIdConfig extends Pick<ArmorConfig, "session"> {
|
|
57
59
|
readonly oauth: ArmorCredentials & {
|
|
58
|
-
readonly
|
|
60
|
+
readonly openIdConfigEndpoint: string;
|
|
59
61
|
readonly baseUrl: string;
|
|
62
|
+
readonly scope?: string;
|
|
63
|
+
readonly audience?: string;
|
|
60
64
|
};
|
|
61
65
|
}
|
package/src/index.ts
CHANGED
|
@@ -39,22 +39,18 @@ export function armor(config: ArmorConfig): Handle {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
* Some IdP's expose a /.well-known/openid-
|
|
43
|
-
* Use that to
|
|
42
|
+
* Some IdP's expose a /.well-known/openid-configuration that specifies how to configure.
|
|
43
|
+
* Use that to create your config.
|
|
44
44
|
* @param config
|
|
45
45
|
* @param fetch
|
|
46
46
|
*/
|
|
47
|
-
export async function
|
|
47
|
+
export async function armorConfigFromOpenId(
|
|
48
48
|
config: ArmorOpenIdConfig,
|
|
49
49
|
fetch?: typeof global.fetch,
|
|
50
|
-
) {
|
|
51
|
-
const url =
|
|
52
|
-
config.oauth.openIdConfigUrl ??
|
|
53
|
-
`${config.oauth.baseUrl}/.well-known/openid-configuration`;
|
|
54
|
-
|
|
50
|
+
): Promise<ArmorConfig> {
|
|
55
51
|
const fetchToUse = fetch ?? global.fetch;
|
|
56
52
|
|
|
57
|
-
const response = await fetchToUse(
|
|
53
|
+
const response = await fetchToUse(config.oauth.openIdConfigEndpoint, {
|
|
58
54
|
headers: {
|
|
59
55
|
Accept: "application/json",
|
|
60
56
|
},
|
|
@@ -67,7 +63,7 @@ export async function armorFromOpenIdConfig(
|
|
|
67
63
|
|
|
68
64
|
const body = await response.json();
|
|
69
65
|
|
|
70
|
-
return
|
|
66
|
+
return {
|
|
71
67
|
...config,
|
|
72
68
|
oauth: {
|
|
73
69
|
...config.oauth,
|
|
@@ -77,7 +73,7 @@ export async function armorFromOpenIdConfig(
|
|
|
77
73
|
jwksUrl: body.jwks_uri,
|
|
78
74
|
logoutEndpoint: body.end_session_endpoint ?? undefined,
|
|
79
75
|
},
|
|
80
|
-
}
|
|
76
|
+
};
|
|
81
77
|
}
|
|
82
78
|
|
|
83
79
|
export function armorCookiesGetTokens(cookies: Cookies): ArmorTokens {
|
package/src/routes/login.ts
CHANGED
|
@@ -14,6 +14,8 @@ export const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {
|
|
|
14
14
|
config.oauth.authorizeEndpoint ??
|
|
15
15
|
urlConcat(config.oauth.baseUrl, "oauth2/authorize");
|
|
16
16
|
|
|
17
|
+
const scope = config.oauth.scope ?? "openid profile email";
|
|
18
|
+
|
|
17
19
|
return {
|
|
18
20
|
path: ROUTE_PATH_LOGIN,
|
|
19
21
|
async handle({ event }) {
|
|
@@ -25,6 +27,8 @@ export const routeLoginFactory: RouteFactory = (config: ArmorConfig) => {
|
|
|
25
27
|
response_type: "code",
|
|
26
28
|
redirect_uri: urlConcat(event.url.origin, ROUTE_PATH_REDIRECT_LOGIN),
|
|
27
29
|
state,
|
|
30
|
+
scope,
|
|
31
|
+
audience: config.oauth.audience,
|
|
28
32
|
});
|
|
29
33
|
|
|
30
34
|
throw redirect(302, `${authorizeEndpoint}?${params}`);
|
|
@@ -14,10 +14,7 @@ import {
|
|
|
14
14
|
cookieGetAndDelete,
|
|
15
15
|
cookieSet,
|
|
16
16
|
} from "../utils/cookie";
|
|
17
|
-
import {
|
|
18
|
-
jwtVerifyAndDecryptAccessToken,
|
|
19
|
-
jwtVerifyAndDecryptIdToken,
|
|
20
|
-
} from "../utils/jwt";
|
|
17
|
+
import { jwtVerifyAccessToken, jwtVerifyIdToken } from "../utils/jwt";
|
|
21
18
|
|
|
22
19
|
export const ROUTE_PATH_REDIRECT_LOGIN = "/_armor/redirect/login";
|
|
23
20
|
|
|
@@ -37,24 +34,33 @@ export const routeRedirectLoginFactory: RouteFactory = (
|
|
|
37
34
|
config.session?.login ??
|
|
38
35
|
((event, tokens) => cookieSet(event.cookies, COOKIE_TOKENS, tokens));
|
|
39
36
|
|
|
37
|
+
const scope = config.oauth.scope ?? "openid profile email";
|
|
38
|
+
|
|
40
39
|
async function exchangeCodeForToken(
|
|
41
40
|
fetch: typeof global.fetch,
|
|
42
41
|
origin: string,
|
|
43
42
|
code: string,
|
|
44
43
|
): Promise<ArmorTokenExchange> {
|
|
44
|
+
const params: Record<string, string> = {
|
|
45
|
+
grant_type: "authorization_code",
|
|
46
|
+
client_id: config.oauth.clientId,
|
|
47
|
+
client_secret: config.oauth.clientSecret,
|
|
48
|
+
code,
|
|
49
|
+
redirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),
|
|
50
|
+
scope,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
if (config.oauth.audience) {
|
|
54
|
+
params.audience = config.oauth.audience;
|
|
55
|
+
}
|
|
56
|
+
|
|
45
57
|
const response = await fetch(tokenUrl, {
|
|
46
58
|
method: "POST",
|
|
47
59
|
headers: {
|
|
48
60
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
49
61
|
Accept: "application/json",
|
|
50
62
|
},
|
|
51
|
-
body: new URLSearchParams(
|
|
52
|
-
grant_type: "authorization_code",
|
|
53
|
-
client_id: config.oauth.clientId,
|
|
54
|
-
client_secret: config.oauth.clientSecret,
|
|
55
|
-
code,
|
|
56
|
-
redirect_uri: urlConcat(origin, ROUTE_PATH_REDIRECT_LOGIN),
|
|
57
|
-
}).toString(),
|
|
63
|
+
body: new URLSearchParams(params).toString(),
|
|
58
64
|
});
|
|
59
65
|
|
|
60
66
|
if (!response.ok) {
|
|
@@ -93,8 +99,8 @@ export const routeRedirectLoginFactory: RouteFactory = (
|
|
|
93
99
|
const jwks = createRemoteJWKSet(jwksUrl);
|
|
94
100
|
|
|
95
101
|
const [idToken, accessToken] = await Promise.all([
|
|
96
|
-
|
|
97
|
-
|
|
102
|
+
jwtVerifyIdToken(config, jwks, exchange.id_token),
|
|
103
|
+
jwtVerifyAccessToken(config, jwks, exchange.access_token),
|
|
98
104
|
]);
|
|
99
105
|
|
|
100
106
|
await sessionLogin(event, {
|
package/src/utils/jwt.ts
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import { ArmorConfig } from "../contracts";
|
|
2
|
-
import {
|
|
3
|
-
jwtDecrypt,
|
|
4
|
-
JWTPayload,
|
|
5
|
-
jwtVerify,
|
|
6
|
-
JWTVerifyGetKey,
|
|
7
|
-
JWTVerifyOptions,
|
|
8
|
-
} from "jose";
|
|
2
|
+
import { JWTPayload, jwtVerify, JWTVerifyGetKey, JWTVerifyOptions } from "jose";
|
|
9
3
|
|
|
10
|
-
export function
|
|
4
|
+
export function jwtVerifyIdToken(
|
|
11
5
|
config: ArmorConfig,
|
|
12
6
|
jwks: JWTVerifyGetKey,
|
|
13
7
|
idToken: string,
|
|
14
8
|
): Promise<JWTPayload> {
|
|
15
|
-
return
|
|
16
|
-
config,
|
|
9
|
+
return jwtVerifyToken(
|
|
17
10
|
jwks,
|
|
18
11
|
{
|
|
19
12
|
issuer: config.oauth.issuer,
|
|
@@ -23,36 +16,25 @@ export function jwtVerifyAndDecryptIdToken(
|
|
|
23
16
|
);
|
|
24
17
|
}
|
|
25
18
|
|
|
26
|
-
export function
|
|
19
|
+
export function jwtVerifyAccessToken(
|
|
27
20
|
config: ArmorConfig,
|
|
28
21
|
jwks: JWTVerifyGetKey,
|
|
29
22
|
accessToken: string,
|
|
30
23
|
): Promise<JWTPayload> {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
);
|
|
37
|
-
}
|
|
24
|
+
const opts: JWTVerifyOptions = { issuer: config.oauth.issuer };
|
|
25
|
+
|
|
26
|
+
if (config.oauth.audience) {
|
|
27
|
+
opts.audience = config.oauth.audience;
|
|
28
|
+
}
|
|
38
29
|
|
|
39
|
-
|
|
40
|
-
const parts = token.split(".");
|
|
41
|
-
return parts.length === 5;
|
|
30
|
+
return jwtVerifyToken(jwks, opts, accessToken);
|
|
42
31
|
}
|
|
43
32
|
|
|
44
|
-
async function
|
|
45
|
-
config: ArmorConfig,
|
|
33
|
+
async function jwtVerifyToken(
|
|
46
34
|
jwks: JWTVerifyGetKey,
|
|
47
35
|
opts: JWTVerifyOptions,
|
|
48
36
|
token: string,
|
|
49
37
|
): 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
|
-
}
|
|
55
|
-
|
|
56
38
|
const { payload } = await jwtVerify(token, jwks, opts);
|
|
57
39
|
return payload;
|
|
58
40
|
}
|