sst 2.26.5 → 2.26.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/cli/commands/bind.js +1 -1
- package/cli/commands/dev.js +47 -56
- package/cli/commands/secrets/load.d.ts +2 -0
- package/cli/commands/secrets/load.js +11 -2
- package/config.js +1 -0
- package/constructs/App.js +3 -1
- package/node/api/index.js +1 -0
- package/node/auth/adapter/link.js +1 -1
- package/node/auth/adapter/oauth.js +1 -1
- package/node/auth/adapter/oidc.js +1 -1
- package/node/future/auth/adapter/adapter.d.ts +6 -1
- package/node/future/auth/adapter/adapter.js +4 -1
- package/node/future/auth/adapter/code.d.ts +1 -4
- package/node/future/auth/adapter/code.js +3 -5
- package/node/future/auth/adapter/facebook.d.ts +6 -1
- package/node/future/auth/adapter/github.d.ts +21 -2
- package/node/future/auth/adapter/google.d.ts +21 -2
- package/node/future/auth/adapter/link.d.ts +1 -4
- package/node/future/auth/adapter/link.js +1 -4
- package/node/future/auth/adapter/oauth.d.ts +9 -1
- package/node/future/auth/adapter/oauth.js +11 -2
- package/node/future/auth/adapter/oidc.js +1 -1
- package/node/future/auth/adapter/spotify.d.ts +6 -1
- package/node/future/auth/handler.d.ts +43 -15
- package/node/future/auth/handler.js +228 -123
- package/node/future/auth/session.d.ts +7 -0
- package/node/future/auth/session.js +1 -0
- package/package.json +1 -1
package/cli/commands/bind.js
CHANGED
package/cli/commands/dev.js
CHANGED
|
@@ -3,35 +3,20 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
3
3
|
type: "boolean",
|
|
4
4
|
description: "Increase function timeout",
|
|
5
5
|
}), async (args) => {
|
|
6
|
+
const { Logger } = await import("../../logger.js");
|
|
6
7
|
const { Colors } = await import("../colors.js");
|
|
7
8
|
const { printHeader } = await import("../ui/header.js");
|
|
8
9
|
const { mapValues } = await import("remeda");
|
|
9
10
|
const path = await import("path");
|
|
10
|
-
const { useRuntimeWorkers } = await import("../../runtime/workers.js");
|
|
11
|
-
const { useIOTBridge } = await import("../../runtime/iot.js");
|
|
12
|
-
const { useRuntimeServer } = await import("../../runtime/server.js");
|
|
13
11
|
const { useBus } = await import("../../bus.js");
|
|
14
12
|
const { useWatcher } = await import("../../watcher.js");
|
|
15
|
-
const { useAppMetadata, saveAppMetadata, Stacks } = await import("../../stacks/index.js");
|
|
16
13
|
const { exit, exitWithError, trackDevError, trackDevRunning } = await import("../program.js");
|
|
17
|
-
const { Logger } = await import("../../logger.js");
|
|
18
14
|
const { createSpinner } = await import("../spinner.js");
|
|
19
15
|
const { bold, dim, yellow } = await import("colorette");
|
|
20
|
-
const { render } = await import("ink");
|
|
21
|
-
const React = await import("react");
|
|
22
|
-
const { Context } = await import("../../context/context.js");
|
|
23
|
-
const { printDeploymentResults, DeploymentUI } = await import("../ui/deploy.js");
|
|
24
16
|
const { useLocalServer } = await import("../local/server.js");
|
|
25
17
|
const fs = await import("fs/promises");
|
|
26
18
|
const crypto = await import("crypto");
|
|
27
|
-
const { useFunctions } = await import("../../constructs/Function.js");
|
|
28
|
-
const { useSites } = await import("../../constructs/SsrSite.js");
|
|
29
|
-
const { usePothosBuilder } = await import("./plugins/pothos.js");
|
|
30
|
-
const { useKyselyTypeGenerator } = await import("./plugins/kysely.js");
|
|
31
|
-
const { useRDSWarmer } = await import("./plugins/warmer.js");
|
|
32
19
|
const { useProject } = await import("../../project.js");
|
|
33
|
-
const { useMetadataCache } = await import("../../stacks/metadata.js");
|
|
34
|
-
const { useIOT } = await import("../../iot.js");
|
|
35
20
|
const { clear } = await import("../terminal.js");
|
|
36
21
|
const { getCiInfo } = await import("../ci-info.js");
|
|
37
22
|
try {
|
|
@@ -40,6 +25,7 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
40
25
|
}
|
|
41
26
|
const project = useProject();
|
|
42
27
|
const useFunctionLogger = lazy(async () => {
|
|
28
|
+
const { useFunctions } = await import("../../constructs/Function.js");
|
|
43
29
|
const bus = useBus();
|
|
44
30
|
const colors = ["#01cdfe", "#ff71ce", "#05ffa1", "#b967ff"];
|
|
45
31
|
let index = 0;
|
|
@@ -141,11 +127,15 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
141
127
|
});
|
|
142
128
|
const useStackBuilder = lazy(async () => {
|
|
143
129
|
const watcher = useWatcher();
|
|
130
|
+
const { printDeploymentResults, DeploymentUI } = await import("../ui/deploy.js");
|
|
131
|
+
const { render } = await import("ink");
|
|
132
|
+
const React = await import("react");
|
|
144
133
|
const scriptVersion = Date.now().toString();
|
|
145
134
|
let lastDeployed;
|
|
146
135
|
let isWorking = false;
|
|
147
136
|
let isDirty = false;
|
|
148
137
|
async function build() {
|
|
138
|
+
const { Stacks } = await import("../../stacks/index.js");
|
|
149
139
|
if (isWorking) {
|
|
150
140
|
isDirty = true;
|
|
151
141
|
return;
|
|
@@ -205,15 +195,40 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
205
195
|
}
|
|
206
196
|
}
|
|
207
197
|
async function deploy(assembly) {
|
|
198
|
+
const metadata = await appMetadata();
|
|
199
|
+
if (!project.config.advanced?.disableAppModeCheck &&
|
|
200
|
+
!getCiInfo().isCI &&
|
|
201
|
+
metadata &&
|
|
202
|
+
metadata.mode !== "dev") {
|
|
203
|
+
async function promptChangeMode() {
|
|
204
|
+
const readline = await import("readline");
|
|
205
|
+
const rl = readline.createInterface({
|
|
206
|
+
input: process.stdin,
|
|
207
|
+
output: process.stdout,
|
|
208
|
+
});
|
|
209
|
+
return new Promise((resolve) => {
|
|
210
|
+
console.log("");
|
|
211
|
+
rl.question(`You have previously deployed the stage "${project.config.stage}" in production. It is recommended that you use a different stage for development. Read more here — https://docs.sst.dev/live-lambda-development\n\nAre you sure you want to run this stage in dev mode? [y/N] `, async (input) => {
|
|
212
|
+
rl.close();
|
|
213
|
+
resolve(input.trim() === "y");
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
if (!(await promptChangeMode())) {
|
|
218
|
+
await exit();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
208
221
|
const nextChecksum = await checksum(assembly.directory);
|
|
222
|
+
const { useSites } = await import("../../constructs/SsrSite.js");
|
|
209
223
|
const component = render(React.createElement(DeploymentUI, { assembly: assembly }));
|
|
224
|
+
const { Stacks } = await import("../../stacks/index.js");
|
|
210
225
|
const results = await Stacks.deployMany(assembly.stacks);
|
|
211
226
|
component.clear();
|
|
212
227
|
component.unmount();
|
|
213
228
|
printDeploymentResults(assembly, results);
|
|
214
229
|
// Run after initial deploy
|
|
215
230
|
if (!lastDeployed) {
|
|
216
|
-
await saveAppMetadata({ mode: "dev" });
|
|
231
|
+
await import("../../stacks/app-metadata.js").then((mod) => mod.saveAppMetadata({ mode: "dev" }));
|
|
217
232
|
// Check failed stacks
|
|
218
233
|
const failed = Object.values(results).find((result) => Stacks.isFailed(result.status));
|
|
219
234
|
failed
|
|
@@ -280,7 +295,7 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
280
295
|
});
|
|
281
296
|
const useDisconnector = lazy(async () => {
|
|
282
297
|
const bus = useBus();
|
|
283
|
-
const iot = await useIOT();
|
|
298
|
+
const iot = await import("../../iot.js").then((mod) => mod.useIOT());
|
|
284
299
|
bus.subscribe("cli.dev", async (evt) => {
|
|
285
300
|
const topic = `${iot.prefix}/events`;
|
|
286
301
|
iot.publish(topic, "cli.dev", evt.properties);
|
|
@@ -299,49 +314,25 @@ export const dev = (program) => program.command(["dev", "start"], "Work on your
|
|
|
299
314
|
await exit();
|
|
300
315
|
});
|
|
301
316
|
});
|
|
302
|
-
|
|
303
|
-
|
|
317
|
+
console.log("wtf");
|
|
318
|
+
Logger.debug("dev is ready");
|
|
319
|
+
const appMetadata = lazy(() => import("../../stacks/app-metadata.js").then((mod) => mod.useAppMetadata()));
|
|
320
|
+
clear();
|
|
321
|
+
await printHeader({ console: true, hint: "ready!" });
|
|
322
|
+
await Promise.all([
|
|
323
|
+
useStackBuilder(),
|
|
324
|
+
useDisconnector(),
|
|
325
|
+
import("../../runtime/workers.js").then((mod) => mod.useRuntimeWorkers()),
|
|
326
|
+
import("../../runtime/iot.js").then((mod) => mod.useIOTBridge()),
|
|
327
|
+
import("../../runtime/server.js").then((mod) => mod.useRuntimeServer()),
|
|
304
328
|
useLocalServer({
|
|
305
329
|
key: "",
|
|
306
330
|
cert: "",
|
|
307
331
|
live: true,
|
|
308
332
|
}),
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
const rl = readline.createInterface({
|
|
313
|
-
input: process.stdin,
|
|
314
|
-
output: process.stdout,
|
|
315
|
-
});
|
|
316
|
-
return new Promise((resolve) => {
|
|
317
|
-
console.log("");
|
|
318
|
-
rl.question(`You have previously deployed the stage "${project.config.stage}" in production. It is recommended that you use a different stage for development. Read more here — https://docs.sst.dev/live-lambda-development\n\nAre you sure you want to run this stage in dev mode? [y/N] `, async (input) => {
|
|
319
|
-
rl.close();
|
|
320
|
-
resolve(input.trim() === "y");
|
|
321
|
-
});
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
// Check app mode changed
|
|
325
|
-
if (!project.config.advanced?.disableAppModeCheck &&
|
|
326
|
-
!getCiInfo().isCI &&
|
|
327
|
-
appMetadata &&
|
|
328
|
-
appMetadata.mode !== "dev") {
|
|
329
|
-
if (!(await promptChangeMode())) {
|
|
330
|
-
await exit();
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
clear();
|
|
334
|
-
await printHeader({ console: true, hint: "ready!" });
|
|
335
|
-
await useStackBuilder();
|
|
336
|
-
await Promise.all([
|
|
337
|
-
useDisconnector(),
|
|
338
|
-
useRuntimeWorkers(),
|
|
339
|
-
useIOTBridge(),
|
|
340
|
-
useRuntimeServer(),
|
|
341
|
-
usePothosBuilder(),
|
|
342
|
-
useMetadataCache(),
|
|
343
|
-
useKyselyTypeGenerator(),
|
|
344
|
-
useRDSWarmer(),
|
|
333
|
+
import("./plugins/pothos.js").then((mod) => mod.usePothosBuilder()),
|
|
334
|
+
import("./plugins/kysely.js").then((mod) => mod.useKyselyTypeGenerator()),
|
|
335
|
+
import("./plugins/warmer.js").then((mod) => mod.useRDSWarmer()),
|
|
345
336
|
useFunctionLogger(),
|
|
346
337
|
]);
|
|
347
338
|
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
export const load = (program) => program.command("load <filename>", "Loads secrets from an .env file", (yargs) => yargs
|
|
1
|
+
export const load = (program) => program.command("load <filename>", "Loads secrets from an .env file", (yargs) => yargs
|
|
2
|
+
.positional("filename", {
|
|
2
3
|
type: "string",
|
|
3
4
|
demandOption: true,
|
|
5
|
+
})
|
|
6
|
+
.option("fallback", {
|
|
7
|
+
type: "boolean",
|
|
8
|
+
describe: "Load the fallback values",
|
|
4
9
|
}), async (args) => {
|
|
5
10
|
const { exit, exitWithError } = await import("../../program.js");
|
|
6
11
|
const { Config } = await import("../../../config.js");
|
|
@@ -16,7 +21,11 @@ export const load = (program) => program.command("load <filename>", "Loads secre
|
|
|
16
21
|
// Set secrets
|
|
17
22
|
const setting = createSpinner(` Setting secrets from "${args.filename}"`).start();
|
|
18
23
|
for (const [key, value] of Object.entries(envVars)) {
|
|
19
|
-
await Config.setSecret({
|
|
24
|
+
await Config.setSecret({
|
|
25
|
+
key: key,
|
|
26
|
+
value: value,
|
|
27
|
+
fallback: args.fallback === true,
|
|
28
|
+
});
|
|
20
29
|
}
|
|
21
30
|
setting.succeed();
|
|
22
31
|
// Restart functions & sites
|
package/config.js
CHANGED
package/constructs/App.js
CHANGED
|
@@ -257,7 +257,9 @@ export class App extends CDKApp {
|
|
|
257
257
|
// Tag stacks
|
|
258
258
|
Tags.of(child).add("sst:app", this.name);
|
|
259
259
|
Tags.of(child).add("sst:stage", this.stage);
|
|
260
|
-
if (child instanceof Stack &&
|
|
260
|
+
if (child instanceof Stack &&
|
|
261
|
+
!this.isRunningSSTTest() &&
|
|
262
|
+
this.mode !== "dev") {
|
|
261
263
|
const bootstrap = await useBootstrap();
|
|
262
264
|
const functions = useFunctions();
|
|
263
265
|
const sourcemaps = functions.sourcemaps.forStack(child.stackName);
|
package/node/api/index.js
CHANGED
|
@@ -12,7 +12,7 @@ export const LinkAdapter = /* @__PURE__ */ createAdapter((config) => {
|
|
|
12
12
|
const [step] = usePath().slice(-1);
|
|
13
13
|
const callback = "https://" +
|
|
14
14
|
[useDomainName(), ...usePath().slice(0, -1), "callback"].join("/");
|
|
15
|
-
if (step === "authorize") {
|
|
15
|
+
if (step === "authorize" || step === "connect") {
|
|
16
16
|
const url = new URL(callback);
|
|
17
17
|
const claims = useQueryParams();
|
|
18
18
|
url.searchParams.append("token", signer(claims));
|
|
@@ -12,7 +12,7 @@ export const OauthAdapter = /* @__PURE__ */ createAdapter((config) => {
|
|
|
12
12
|
redirect_uris: [callback],
|
|
13
13
|
response_types: ["code"],
|
|
14
14
|
});
|
|
15
|
-
if (step === "authorize") {
|
|
15
|
+
if (step === "authorize" || step === "connect") {
|
|
16
16
|
const code_verifier = generators.codeVerifier();
|
|
17
17
|
const state = generators.state();
|
|
18
18
|
const code_challenge = generators.codeChallenge(code_verifier);
|
|
@@ -11,7 +11,7 @@ export const OidcAdapter = /* @__PURE__ */ createAdapter((config) => {
|
|
|
11
11
|
redirect_uris: [callback],
|
|
12
12
|
response_types: ["id_token"],
|
|
13
13
|
});
|
|
14
|
-
if (step === "authorize") {
|
|
14
|
+
if (step === "authorize" || step === "connect") {
|
|
15
15
|
const nonce = generators.nonce();
|
|
16
16
|
const state = generators.state();
|
|
17
17
|
const url = client.authorizationUrl({
|
|
@@ -7,4 +7,9 @@ export type Adapter<T = any> = (evt: APIGatewayProxyEventV2) => Promise<{
|
|
|
7
7
|
properties: T;
|
|
8
8
|
} | {
|
|
9
9
|
type: "error";
|
|
10
|
-
|
|
10
|
+
error: AdapterError;
|
|
11
|
+
} | undefined>;
|
|
12
|
+
export declare class AdapterError extends Error {
|
|
13
|
+
}
|
|
14
|
+
export declare class AdapterUnknownError extends AdapterError {
|
|
15
|
+
}
|
|
@@ -6,12 +6,9 @@ export declare function CodeAdapter(config: {
|
|
|
6
6
|
}): () => Promise<{
|
|
7
7
|
type: "step";
|
|
8
8
|
properties: APIGatewayProxyStructuredResultV2;
|
|
9
|
-
} | {
|
|
10
|
-
type: "error";
|
|
11
|
-
properties?: undefined;
|
|
12
9
|
} | {
|
|
13
10
|
type: "success";
|
|
14
11
|
properties: {
|
|
15
12
|
claims: any;
|
|
16
13
|
};
|
|
17
|
-
}>;
|
|
14
|
+
} | undefined>;
|
|
@@ -12,7 +12,7 @@ export function CodeAdapter(config) {
|
|
|
12
12
|
}
|
|
13
13
|
return async function () {
|
|
14
14
|
const step = usePathParam("step");
|
|
15
|
-
if (step === "authorize") {
|
|
15
|
+
if (step === "authorize" || step === "connect") {
|
|
16
16
|
const code = generate();
|
|
17
17
|
const claims = useQueryParams();
|
|
18
18
|
delete claims["client_id"];
|
|
@@ -39,7 +39,8 @@ export function CodeAdapter(config) {
|
|
|
39
39
|
const { code, claims } = JSON.parse(decrypt(useCookie("authorization")));
|
|
40
40
|
if (!code || !claims) {
|
|
41
41
|
return {
|
|
42
|
-
type: "
|
|
42
|
+
type: "step",
|
|
43
|
+
properties: await config.onCodeInvalid(code, claims),
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
46
|
const compare = useQueryParam("code");
|
|
@@ -61,8 +62,5 @@ export function CodeAdapter(config) {
|
|
|
61
62
|
},
|
|
62
63
|
};
|
|
63
64
|
}
|
|
64
|
-
return {
|
|
65
|
-
type: "error",
|
|
66
|
-
};
|
|
67
65
|
};
|
|
68
66
|
}
|
|
@@ -5,7 +5,7 @@ type Config = ({
|
|
|
5
5
|
} & OauthBasicConfig) | ({
|
|
6
6
|
mode: "oidc";
|
|
7
7
|
} & OidcBasicConfig);
|
|
8
|
-
export declare const GithubAdapter: (config: Config) => () => Promise<{
|
|
8
|
+
export declare const GithubAdapter: (config: Config) => (() => Promise<{
|
|
9
9
|
type: "success";
|
|
10
10
|
properties: {
|
|
11
11
|
tokenset: import("openid-client").TokenSet;
|
|
@@ -19,5 +19,24 @@ export declare const GithubAdapter: (config: Config) => () => Promise<{
|
|
|
19
19
|
location: string;
|
|
20
20
|
};
|
|
21
21
|
};
|
|
22
|
-
}
|
|
22
|
+
}>) | (() => Promise<{
|
|
23
|
+
type: "success";
|
|
24
|
+
properties: {
|
|
25
|
+
tokenset: import("openid-client").TokenSet;
|
|
26
|
+
client: import("openid-client").BaseClient;
|
|
27
|
+
};
|
|
28
|
+
} | {
|
|
29
|
+
type: "step";
|
|
30
|
+
properties: {
|
|
31
|
+
statusCode: number;
|
|
32
|
+
headers: {
|
|
33
|
+
location: string;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
error?: undefined;
|
|
37
|
+
} | {
|
|
38
|
+
type: "error";
|
|
39
|
+
error: import("./oauth.js").OauthError;
|
|
40
|
+
properties?: undefined;
|
|
41
|
+
} | undefined>);
|
|
23
42
|
export {};
|
|
@@ -10,7 +10,7 @@ type GoogleConfig = (OauthBasicConfig & {
|
|
|
10
10
|
mode: "oidc";
|
|
11
11
|
prompt?: GooglePrompt;
|
|
12
12
|
});
|
|
13
|
-
export declare function GoogleAdapter(config: GoogleConfig): () => Promise<{
|
|
13
|
+
export declare function GoogleAdapter(config: GoogleConfig): (() => Promise<{
|
|
14
14
|
type: "success";
|
|
15
15
|
properties: {
|
|
16
16
|
tokenset: import("openid-client").TokenSet;
|
|
@@ -24,5 +24,24 @@ export declare function GoogleAdapter(config: GoogleConfig): () => Promise<{
|
|
|
24
24
|
location: string;
|
|
25
25
|
};
|
|
26
26
|
};
|
|
27
|
-
}
|
|
27
|
+
}>) | (() => Promise<{
|
|
28
|
+
type: "success";
|
|
29
|
+
properties: {
|
|
30
|
+
tokenset: import("openid-client").TokenSet;
|
|
31
|
+
client: import("openid-client").BaseClient;
|
|
32
|
+
};
|
|
33
|
+
} | {
|
|
34
|
+
type: "step";
|
|
35
|
+
properties: {
|
|
36
|
+
statusCode: number;
|
|
37
|
+
headers: {
|
|
38
|
+
location: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
error?: undefined;
|
|
42
|
+
} | {
|
|
43
|
+
type: "error";
|
|
44
|
+
error: import("./oauth.js").OauthError;
|
|
45
|
+
properties?: undefined;
|
|
46
|
+
} | undefined>);
|
|
28
47
|
export {};
|
|
@@ -14,7 +14,7 @@ export function LinkAdapter(config) {
|
|
|
14
14
|
});
|
|
15
15
|
const callback = "https://" + useDomainName() + "/callback";
|
|
16
16
|
const step = usePathParam("step");
|
|
17
|
-
if (step === "authorize") {
|
|
17
|
+
if (step === "authorize" || step === "connect") {
|
|
18
18
|
const url = new URL(callback);
|
|
19
19
|
const claims = useQueryParams();
|
|
20
20
|
url.searchParams.append("token", signer(claims));
|
|
@@ -40,8 +40,5 @@ export function LinkAdapter(config) {
|
|
|
40
40
|
}
|
|
41
41
|
catch (ex) { }
|
|
42
42
|
}
|
|
43
|
-
return {
|
|
44
|
-
type: "error",
|
|
45
|
-
};
|
|
46
43
|
};
|
|
47
44
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseClient, Issuer, TokenSet } from "openid-client";
|
|
2
|
+
import { AdapterError } from "./adapter.js";
|
|
2
3
|
export interface OauthBasicConfig {
|
|
3
4
|
/**
|
|
4
5
|
* The clientID provided by the third party oauth service
|
|
@@ -24,6 +25,8 @@ export interface OauthBasicConfig {
|
|
|
24
25
|
export interface OauthConfig extends OauthBasicConfig {
|
|
25
26
|
issuer: Issuer;
|
|
26
27
|
}
|
|
28
|
+
export declare class OauthError extends AdapterError {
|
|
29
|
+
}
|
|
27
30
|
export declare const OauthAdapter: (config: OauthConfig) => () => Promise<{
|
|
28
31
|
type: "success";
|
|
29
32
|
properties: {
|
|
@@ -38,4 +41,9 @@ export declare const OauthAdapter: (config: OauthConfig) => () => Promise<{
|
|
|
38
41
|
location: string;
|
|
39
42
|
};
|
|
40
43
|
};
|
|
41
|
-
|
|
44
|
+
error?: undefined;
|
|
45
|
+
} | {
|
|
46
|
+
type: "error";
|
|
47
|
+
error: OauthError;
|
|
48
|
+
properties?: undefined;
|
|
49
|
+
} | undefined>;
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { generators } from "openid-client";
|
|
2
2
|
import { useCookie, useDomainName, usePathParam, useQueryParams, useResponse, } from "../../../api/index.js";
|
|
3
|
+
import { AdapterError } from "./adapter.js";
|
|
4
|
+
export class OauthError extends AdapterError {
|
|
5
|
+
}
|
|
3
6
|
export const OauthAdapter =
|
|
4
7
|
/* @__PURE__ */
|
|
5
8
|
(config) => {
|
|
6
9
|
return async function () {
|
|
7
10
|
const step = usePathParam("step");
|
|
8
11
|
const callback = "https://" + useDomainName() + "/callback";
|
|
12
|
+
console.log("callback", callback);
|
|
9
13
|
const client = new config.issuer.Client({
|
|
10
14
|
client_id: config.clientID,
|
|
11
15
|
client_secret: config.clientSecret,
|
|
12
16
|
redirect_uris: [callback],
|
|
13
17
|
response_types: ["code"],
|
|
14
18
|
});
|
|
15
|
-
if (step === "authorize") {
|
|
19
|
+
if (step === "authorize" || step === "connect") {
|
|
16
20
|
const code_verifier = generators.codeVerifier();
|
|
17
21
|
const state = generators.state();
|
|
18
22
|
const code_challenge = generators.codeChallenge(code_verifier);
|
|
@@ -45,6 +49,12 @@ export const OauthAdapter =
|
|
|
45
49
|
}
|
|
46
50
|
if (step === "callback") {
|
|
47
51
|
const params = useQueryParams();
|
|
52
|
+
if (params.error) {
|
|
53
|
+
return {
|
|
54
|
+
type: "error",
|
|
55
|
+
error: new OauthError(params.error),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
48
58
|
const code_verifier = useCookie("auth_code_verifier");
|
|
49
59
|
const state = useCookie("auth_state");
|
|
50
60
|
const tokenset = await client[config.issuer.metadata.userinfo_endpoint
|
|
@@ -62,6 +72,5 @@ export const OauthAdapter =
|
|
|
62
72
|
};
|
|
63
73
|
return x;
|
|
64
74
|
}
|
|
65
|
-
throw new Error("Invalid auth request");
|
|
66
75
|
};
|
|
67
76
|
};
|
|
@@ -9,7 +9,7 @@ export const OidcAdapter = /* @__PURE__ */ (config) => {
|
|
|
9
9
|
redirect_uris: [callback],
|
|
10
10
|
response_types: ["id_token"],
|
|
11
11
|
});
|
|
12
|
-
if (step === "authorize") {
|
|
12
|
+
if (step === "authorize" || step === "connect") {
|
|
13
13
|
const nonce = generators.nonce();
|
|
14
14
|
const state = generators.state();
|
|
15
15
|
const url = client.authorizationUrl({
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from "aws-lambda";
|
|
2
2
|
import { Adapter } from "./adapter/adapter.js";
|
|
3
3
|
import { SignerOptions } from "fast-jwt";
|
|
4
|
-
import { SessionBuilder
|
|
5
|
-
interface OnSuccessResponder<T
|
|
4
|
+
import { SessionBuilder } from "./session.js";
|
|
5
|
+
interface OnSuccessResponder<T extends {
|
|
6
|
+
type: any;
|
|
7
|
+
properties: any;
|
|
8
|
+
}> {
|
|
6
9
|
session(input: T & Partial<SignerOptions>): {
|
|
7
10
|
type: "session";
|
|
8
11
|
properties: T;
|
|
@@ -12,10 +15,25 @@ interface OnSuccessResponder<T> {
|
|
|
12
15
|
properties: typeof input;
|
|
13
16
|
};
|
|
14
17
|
}
|
|
15
|
-
export declare class UnknownProviderError {
|
|
18
|
+
export declare class UnknownProviderError extends Error {
|
|
16
19
|
provider?: string | undefined;
|
|
17
20
|
constructor(provider?: string | undefined);
|
|
18
21
|
}
|
|
22
|
+
export declare class MissingParameterError extends Error {
|
|
23
|
+
parameter: string;
|
|
24
|
+
constructor(parameter: string);
|
|
25
|
+
}
|
|
26
|
+
export declare class UnknownStateError extends Error {
|
|
27
|
+
constructor();
|
|
28
|
+
}
|
|
29
|
+
export declare class UnauthorizedClientError extends Error {
|
|
30
|
+
client: string;
|
|
31
|
+
redirect_uri: string;
|
|
32
|
+
constructor(client: string, redirect_uri: string);
|
|
33
|
+
}
|
|
34
|
+
export declare class InvalidSessionError extends Error {
|
|
35
|
+
constructor();
|
|
36
|
+
}
|
|
19
37
|
export declare function AuthHandler<Providers extends Record<string, Adapter<any>>, Sessions extends SessionBuilder, Result = {
|
|
20
38
|
[key in keyof Providers]: {
|
|
21
39
|
provider: key;
|
|
@@ -25,22 +43,32 @@ export declare function AuthHandler<Providers extends Record<string, Adapter<any
|
|
|
25
43
|
}[keyof Providers]>(input: {
|
|
26
44
|
providers: Providers;
|
|
27
45
|
sessions?: Sessions;
|
|
28
|
-
/** @deprecated use allowClient callback instead */
|
|
46
|
+
/** @deprecated use on.auth.allowClient callback instead */
|
|
29
47
|
clients?: () => Promise<Record<string, string>>;
|
|
48
|
+
/** @deprecated use on.auth.allowClient callback instead */
|
|
30
49
|
allowClient?: (clientID: string, redirect: string) => Promise<boolean>;
|
|
50
|
+
/** @deprecated use on.auth.start callback instead */
|
|
31
51
|
onAuthorize?: (event: APIGatewayProxyEventV2) => Promise<void | keyof Providers>;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
52
|
+
/** @deprecated use on.auth.success callback instead */
|
|
53
|
+
onSuccess?: (input: Result, response: OnSuccessResponder<Sessions["$typeValues"]>) => Promise<ReturnType<OnSuccessResponder<Sessions["$typeValues"]>[keyof OnSuccessResponder<any>]>>;
|
|
54
|
+
/** @deprecated on.index callback instead */
|
|
55
|
+
onIndex?: (event: APIGatewayProxyEventV2) => Promise<APIGatewayProxyStructuredResultV2>;
|
|
56
|
+
/** @deprecated use on.error callback instead */
|
|
57
|
+
onError?: (error: MissingParameterError | UnauthorizedClientError | UnknownProviderError) => Promise<APIGatewayProxyStructuredResultV2 | undefined>;
|
|
58
|
+
callbacks: {
|
|
59
|
+
index?(event: APIGatewayProxyEventV2): Promise<APIGatewayProxyStructuredResultV2>;
|
|
60
|
+
error?(error: UnknownStateError): Promise<APIGatewayProxyStructuredResultV2 | undefined>;
|
|
61
|
+
auth: {
|
|
62
|
+
error?(error: MissingParameterError | UnauthorizedClientError | UnknownProviderError): Promise<APIGatewayProxyStructuredResultV2 | undefined>;
|
|
63
|
+
start?(event: APIGatewayProxyEventV2): Promise<void>;
|
|
64
|
+
allowClient(clientID: string, redirect: string): Promise<boolean>;
|
|
65
|
+
success(input: Result, response: OnSuccessResponder<Sessions["$typeValues"]>): Promise<ReturnType<OnSuccessResponder<Sessions["$typeValues"]>[keyof OnSuccessResponder<any>]>>;
|
|
36
66
|
};
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
67
|
+
connect?: {
|
|
68
|
+
error?(error: InvalidSessionError | UnknownProviderError): Promise<APIGatewayProxyStructuredResultV2 | undefined>;
|
|
69
|
+
start?(session: Sessions["$typeValues"], event: APIGatewayProxyEventV2): Promise<void>;
|
|
70
|
+
success?(session: Sessions["$typeValues"], input: Result): Promise<APIGatewayProxyStructuredResultV2>;
|
|
41
71
|
};
|
|
42
|
-
}
|
|
43
|
-
onIndex?: (event: APIGatewayProxyEventV2) => Promise<APIGatewayProxyStructuredResultV2>;
|
|
44
|
-
onError?: (error: UnknownProviderError) => Promise<APIGatewayProxyStructuredResultV2 | undefined>;
|
|
72
|
+
};
|
|
45
73
|
}): (event: APIGatewayProxyEventV2, context: import("aws-lambda").Context) => Promise<APIGatewayProxyStructuredResultV2>;
|
|
46
74
|
export {};
|
|
@@ -1,18 +1,64 @@
|
|
|
1
1
|
import { createSigner, createVerifier } from "fast-jwt";
|
|
2
2
|
import { ApiHandler, useCookie, useCookies, useFormValue, usePathParam, useQueryParam, useQueryParams, useResponse, } from "../../api/index.js";
|
|
3
3
|
import { Config } from "../../config/index.js";
|
|
4
|
-
export class UnknownProviderError {
|
|
4
|
+
export class UnknownProviderError extends Error {
|
|
5
5
|
provider;
|
|
6
6
|
constructor(provider) {
|
|
7
|
+
super("Unknown provider: " + provider);
|
|
7
8
|
this.provider = provider;
|
|
8
9
|
}
|
|
9
10
|
}
|
|
11
|
+
export class MissingParameterError extends Error {
|
|
12
|
+
parameter;
|
|
13
|
+
constructor(parameter) {
|
|
14
|
+
super("Missing parameter: " + parameter);
|
|
15
|
+
this.parameter = parameter;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class UnknownStateError extends Error {
|
|
19
|
+
constructor() {
|
|
20
|
+
super("The user's browser was in an unknown state. This could be because certain cookies expired or the user switched browsers in the middle of an authentication flow");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export class UnauthorizedClientError extends Error {
|
|
24
|
+
client;
|
|
25
|
+
redirect_uri;
|
|
26
|
+
constructor(client, redirect_uri) {
|
|
27
|
+
super("Unauthorized client");
|
|
28
|
+
this.client = client;
|
|
29
|
+
this.redirect_uri = redirect_uri;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class InvalidSessionError extends Error {
|
|
33
|
+
constructor() {
|
|
34
|
+
super("Invalid session");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
10
37
|
export function AuthHandler(input) {
|
|
38
|
+
// Remap deprecrated stuff
|
|
39
|
+
const { allowClient, clients, onError, onSuccess, onAuthorize, onIndex } = input;
|
|
40
|
+
if (onError && !input.callbacks.auth.error)
|
|
41
|
+
input.callbacks.auth.error = onError;
|
|
42
|
+
if (onSuccess && !input.callbacks.auth.success)
|
|
43
|
+
input.callbacks.auth.success = onSuccess;
|
|
44
|
+
if (onIndex && !input.callbacks.index)
|
|
45
|
+
input.callbacks.index = onIndex;
|
|
46
|
+
if (onAuthorize && !input.callbacks.auth.start)
|
|
47
|
+
input.callbacks.auth.start = async (evt) => {
|
|
48
|
+
await onAuthorize(evt);
|
|
49
|
+
};
|
|
50
|
+
if (allowClient && !input.callbacks.auth.allowClient)
|
|
51
|
+
input.callbacks.auth.allowClient = allowClient;
|
|
52
|
+
if (clients && !input.callbacks.auth.allowClient)
|
|
53
|
+
input.callbacks.auth.allowClient = async (clientID, redirect) => {
|
|
54
|
+
const list = await clients();
|
|
55
|
+
return list[clientID].startsWith(redirect);
|
|
56
|
+
};
|
|
11
57
|
return ApiHandler(async (evt) => {
|
|
12
58
|
const step = usePathParam("step");
|
|
13
59
|
if (!step) {
|
|
14
|
-
if (input.
|
|
15
|
-
return input.
|
|
60
|
+
if (input.callbacks.index) {
|
|
61
|
+
return input.callbacks.index(evt);
|
|
16
62
|
}
|
|
17
63
|
const clients = (await input.clients?.()) || {};
|
|
18
64
|
return {
|
|
@@ -90,62 +136,75 @@ export function AuthHandler(input) {
|
|
|
90
136
|
};
|
|
91
137
|
}
|
|
92
138
|
let provider = useCookie("provider");
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
provider = result;
|
|
99
|
-
}
|
|
139
|
+
let response_type = useCookie("response_type");
|
|
140
|
+
let redirect_uri = useCookie("redirect_uri");
|
|
141
|
+
console.log("step", step);
|
|
142
|
+
if (step === "connect") {
|
|
143
|
+
provider = useFormValue("provider") || undefined;
|
|
100
144
|
if (!provider) {
|
|
101
145
|
return {
|
|
102
146
|
statusCode: 400,
|
|
103
147
|
body: "Missing provider",
|
|
104
148
|
};
|
|
105
149
|
}
|
|
106
|
-
const
|
|
150
|
+
const token = useFormValue("token");
|
|
151
|
+
const verified = input.sessions?.verify(token);
|
|
152
|
+
if (!verified) {
|
|
153
|
+
return ((await input.callbacks.connect?.error?.(new InvalidSessionError())) || {
|
|
154
|
+
statusCode: 401,
|
|
155
|
+
body: "Invalid session",
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
await input.callbacks.connect?.start?.(verified, evt);
|
|
159
|
+
response_type = "connect";
|
|
160
|
+
useResponse().cookies({
|
|
161
|
+
provider,
|
|
162
|
+
response_type: "connect",
|
|
163
|
+
sst_auth_token: token,
|
|
164
|
+
}, {
|
|
165
|
+
maxAge: 60 * 15,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (step === "authorize") {
|
|
169
|
+
provider = useQueryParam("provider");
|
|
170
|
+
response_type = useQueryParam("response_type") || response_type;
|
|
171
|
+
redirect_uri = useQueryParam("redirect_uri") || redirect_uri;
|
|
172
|
+
const { client_id, state } = {
|
|
107
173
|
...useCookies(),
|
|
108
174
|
...useQueryParams(),
|
|
109
175
|
};
|
|
110
|
-
if (!redirect_uri) {
|
|
111
|
-
return {
|
|
112
|
-
statusCode: 400,
|
|
113
|
-
body: "Missing redirect_uri",
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
176
|
if (!provider) {
|
|
117
|
-
return {
|
|
177
|
+
return ((await input.callbacks.auth.error?.(new MissingParameterError("provider"))) || {
|
|
118
178
|
statusCode: 400,
|
|
119
179
|
body: "Missing provider",
|
|
120
|
-
};
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
if (!redirect_uri) {
|
|
183
|
+
return ((await input.callbacks.auth.error?.(new MissingParameterError("redirect_uri"))) || {
|
|
184
|
+
statusCode: 400,
|
|
185
|
+
body: "Missing redirect_uri",
|
|
186
|
+
});
|
|
121
187
|
}
|
|
122
188
|
if (!response_type) {
|
|
123
|
-
return {
|
|
189
|
+
return ((await input.callbacks.auth.error?.(new MissingParameterError("response_type"))) || {
|
|
124
190
|
statusCode: 400,
|
|
125
191
|
body: "Missing response_type",
|
|
126
|
-
};
|
|
192
|
+
});
|
|
127
193
|
}
|
|
128
194
|
if (!client_id) {
|
|
129
|
-
return {
|
|
195
|
+
return ((await input.callbacks.auth.error?.(new MissingParameterError("client_id"))) || {
|
|
130
196
|
statusCode: 400,
|
|
131
197
|
body: "Missing client_id",
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
if (input.clients) {
|
|
135
|
-
const clients = await input.clients();
|
|
136
|
-
if (clients[client_id] !== redirect_uri) {
|
|
137
|
-
return {
|
|
138
|
-
statusCode: 400,
|
|
139
|
-
body: "Invalid redirect_uri",
|
|
140
|
-
};
|
|
141
|
-
}
|
|
198
|
+
});
|
|
142
199
|
}
|
|
143
|
-
if (input.allowClient
|
|
144
|
-
|
|
145
|
-
return {
|
|
200
|
+
if (!(await input.callbacks.auth.allowClient(client_id, redirect_uri))) {
|
|
201
|
+
return ((await input.callbacks.auth.error?.(new UnauthorizedClientError(client_id, redirect_uri))) || {
|
|
146
202
|
statusCode: 400,
|
|
147
203
|
body: "Invalid redirect_uri",
|
|
148
|
-
};
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
if (input.callbacks.auth.start) {
|
|
207
|
+
await input.callbacks.auth.start(evt);
|
|
149
208
|
}
|
|
150
209
|
useResponse().cookies({
|
|
151
210
|
provider: provider,
|
|
@@ -160,120 +219,166 @@ export function AuthHandler(input) {
|
|
|
160
219
|
httpOnly: true,
|
|
161
220
|
});
|
|
162
221
|
}
|
|
222
|
+
if (!response_type) {
|
|
223
|
+
return ((await input.callbacks.error?.(new UnknownStateError())) || {
|
|
224
|
+
statusCode: 400,
|
|
225
|
+
body: new UnknownStateError().message,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
163
228
|
if (!provider || !input.providers[provider]) {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
229
|
+
const err = new UnknownProviderError(provider);
|
|
230
|
+
return ((response_type === "connect"
|
|
231
|
+
? input.callbacks.connect?.error
|
|
232
|
+
: input.callbacks.auth.error)?.(err) || {
|
|
168
233
|
statusCode: 400,
|
|
169
|
-
body:
|
|
234
|
+
body: err.toString(),
|
|
170
235
|
headers: {
|
|
171
236
|
"Content-Type": "text/html",
|
|
172
237
|
},
|
|
173
|
-
};
|
|
238
|
+
});
|
|
174
239
|
}
|
|
175
240
|
const adapter = input.providers[provider];
|
|
176
241
|
const result = await adapter(evt);
|
|
242
|
+
if (!result) {
|
|
243
|
+
return {
|
|
244
|
+
statusCode: 404,
|
|
245
|
+
body: "Not found",
|
|
246
|
+
};
|
|
247
|
+
}
|
|
177
248
|
if (result.type === "step") {
|
|
178
249
|
return result.properties;
|
|
179
250
|
}
|
|
180
251
|
if (result.type === "success") {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
},
|
|
191
|
-
session(input) {
|
|
192
|
-
return {
|
|
193
|
-
type: "session",
|
|
194
|
-
properties: input,
|
|
195
|
-
};
|
|
196
|
-
},
|
|
197
|
-
});
|
|
198
|
-
console.log("onSuccess", onSuccess);
|
|
199
|
-
if (onSuccess.type === "session") {
|
|
200
|
-
const { type, properties, ...rest } = onSuccess.properties;
|
|
201
|
-
// @ts-expect-error
|
|
202
|
-
const priv = Config[process.env.AUTH_ID + "PrivateKey"];
|
|
203
|
-
const signer = createSigner({
|
|
204
|
-
...rest,
|
|
205
|
-
key: priv,
|
|
206
|
-
algorithm: "RS512",
|
|
207
|
-
});
|
|
208
|
-
const token = signer({
|
|
209
|
-
type,
|
|
210
|
-
properties,
|
|
211
|
-
});
|
|
212
|
-
useResponse()
|
|
213
|
-
.cookie({
|
|
214
|
-
key: "sst_auth_token",
|
|
215
|
-
value: token,
|
|
216
|
-
maxAge: 10 * 365 * 24 * 60 * 60,
|
|
217
|
-
})
|
|
218
|
-
.cookies({
|
|
252
|
+
if (response_type === "connect") {
|
|
253
|
+
const session = input.sessions?.use();
|
|
254
|
+
if (!session) {
|
|
255
|
+
return ((await input.callbacks.connect?.error?.(new InvalidSessionError())) || {
|
|
256
|
+
statusCode: 401,
|
|
257
|
+
body: "Invalid session",
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
useResponse().cookies({
|
|
219
261
|
provider: "",
|
|
220
262
|
response_type: "",
|
|
221
|
-
|
|
222
|
-
redirect_uri: "",
|
|
223
|
-
state: "",
|
|
263
|
+
sst_auth_token: "",
|
|
224
264
|
}, {
|
|
225
265
|
expires: new Date(1),
|
|
226
266
|
});
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
...
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
267
|
+
return input.callbacks.connect?.success(session, {
|
|
268
|
+
provider,
|
|
269
|
+
...result.properties,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
if (response_type === "token" || response_type === "code") {
|
|
273
|
+
const onSuccess = await input.callbacks.auth.success({
|
|
274
|
+
provider,
|
|
275
|
+
...result.properties,
|
|
276
|
+
}, {
|
|
277
|
+
http(input) {
|
|
278
|
+
return {
|
|
279
|
+
type: "http",
|
|
280
|
+
properties: input,
|
|
281
|
+
};
|
|
282
|
+
},
|
|
283
|
+
session(input) {
|
|
284
|
+
return {
|
|
285
|
+
type: "session",
|
|
286
|
+
properties: input,
|
|
287
|
+
};
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
if (onSuccess.type === "session") {
|
|
291
|
+
const { type, properties, ...rest } = onSuccess.properties;
|
|
292
|
+
// @ts-expect-error
|
|
293
|
+
const priv = Config[process.env.AUTH_ID + "PrivateKey"];
|
|
294
|
+
const signer = createSigner({
|
|
295
|
+
...rest,
|
|
247
296
|
key: priv,
|
|
248
297
|
algorithm: "RS512",
|
|
249
|
-
})({
|
|
250
|
-
client_id,
|
|
251
|
-
redirect_uri,
|
|
252
|
-
token: token,
|
|
253
298
|
});
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
299
|
+
const token = signer({
|
|
300
|
+
type,
|
|
301
|
+
properties,
|
|
302
|
+
});
|
|
303
|
+
useResponse()
|
|
304
|
+
.cookie({
|
|
305
|
+
key: "sst_auth_token",
|
|
306
|
+
value: token,
|
|
307
|
+
maxAge: 10 * 365 * 24 * 60 * 60,
|
|
308
|
+
})
|
|
309
|
+
.cookies({
|
|
310
|
+
provider: "",
|
|
311
|
+
response_type: "",
|
|
312
|
+
client_id: "",
|
|
313
|
+
redirect_uri: "",
|
|
314
|
+
state: "",
|
|
315
|
+
}, {
|
|
316
|
+
expires: new Date(1),
|
|
317
|
+
});
|
|
318
|
+
const { client_id, redirect_uri, state } = useCookies();
|
|
319
|
+
if (response_type === "token") {
|
|
320
|
+
const location = new URL(redirect_uri);
|
|
321
|
+
location.hash = `access_token=${token}&state=${state || ""}`;
|
|
322
|
+
return {
|
|
323
|
+
statusCode: 302,
|
|
324
|
+
headers: {
|
|
325
|
+
Location: location.href,
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
if (response_type === "code") {
|
|
330
|
+
// This allows the code to be reused within a 30 second window
|
|
331
|
+
// The code should be single use but we're making this tradeoff to remain stateless
|
|
332
|
+
// In the future can store this in a dynamo table to ensure single use
|
|
333
|
+
const code = createSigner({
|
|
334
|
+
expiresIn: 1000 * 60 * 5,
|
|
335
|
+
key: priv,
|
|
336
|
+
algorithm: "RS512",
|
|
337
|
+
})({
|
|
338
|
+
client_id,
|
|
339
|
+
redirect_uri,
|
|
340
|
+
token: token,
|
|
341
|
+
});
|
|
342
|
+
const location = new URL(redirect_uri);
|
|
343
|
+
location.searchParams.set("code", code);
|
|
344
|
+
location.searchParams.set("state", state || "");
|
|
345
|
+
return {
|
|
346
|
+
statusCode: 302,
|
|
347
|
+
headers: {
|
|
348
|
+
Location: location.href,
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
}
|
|
257
352
|
return {
|
|
258
|
-
statusCode:
|
|
259
|
-
|
|
260
|
-
Location: location.href,
|
|
261
|
-
},
|
|
353
|
+
statusCode: 400,
|
|
354
|
+
body: `Unsupported response_type: ${response_type}`,
|
|
262
355
|
};
|
|
263
356
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
if (onSuccess.type === "http") {
|
|
270
|
-
return onSuccess.properties;
|
|
357
|
+
if (onSuccess.type === "http") {
|
|
358
|
+
return onSuccess.properties;
|
|
359
|
+
}
|
|
271
360
|
}
|
|
272
361
|
}
|
|
273
362
|
if (result.type === "error") {
|
|
363
|
+
if (response_type === "connect") {
|
|
364
|
+
return ((await input.callbacks.connect?.error?.(result.error)) || {
|
|
365
|
+
statusCode: 400,
|
|
366
|
+
body: result.error.message,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
if (!redirect_uri) {
|
|
370
|
+
return ((await input.callbacks.auth.error?.(new UnknownStateError())) || {
|
|
371
|
+
statusCode: 400,
|
|
372
|
+
body: new UnknownStateError().message,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
const location = new URL(redirect_uri);
|
|
376
|
+
location.searchParams.set("error", result.error.message);
|
|
274
377
|
return {
|
|
275
|
-
statusCode:
|
|
276
|
-
|
|
378
|
+
statusCode: 302,
|
|
379
|
+
headers: {
|
|
380
|
+
Location: location.toString(),
|
|
381
|
+
},
|
|
277
382
|
};
|
|
278
383
|
}
|
|
279
384
|
});
|
|
@@ -67,5 +67,12 @@ export declare function createSessionBuilder<SessionTypes extends Record<string,
|
|
|
67
67
|
properties: {};
|
|
68
68
|
};
|
|
69
69
|
$type: SessionTypes;
|
|
70
|
+
$typeValues: { [type in keyof SessionTypes]: {
|
|
71
|
+
type: type;
|
|
72
|
+
properties: SessionTypes[type];
|
|
73
|
+
}; }[keyof SessionTypes] | {
|
|
74
|
+
type: "public";
|
|
75
|
+
properties: {};
|
|
76
|
+
};
|
|
70
77
|
};
|
|
71
78
|
export {};
|