sst 2.1.16 → 2.1.18

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.
Files changed (53) hide show
  1. package/bootstrap.js +1 -1
  2. package/cli/commands/bind.js +1 -1
  3. package/cli/commands/env.js +1 -1
  4. package/constructs/App.js +3 -3
  5. package/constructs/AstroSite.js +8 -41
  6. package/constructs/EdgeFunction.d.ts +19 -21
  7. package/constructs/EdgeFunction.js +235 -167
  8. package/constructs/Function.d.ts +1 -1
  9. package/constructs/Function.js +3 -3
  10. package/constructs/Job.js +2 -2
  11. package/constructs/NextjsSite.d.ts +6 -5
  12. package/constructs/NextjsSite.js +5 -3
  13. package/constructs/RDS.js +1 -1
  14. package/constructs/RemixSite.d.ts +2 -3
  15. package/constructs/RemixSite.js +42 -71
  16. package/constructs/SolidStartSite.js +8 -41
  17. package/constructs/SsrFunction.d.ts +9 -6
  18. package/constructs/SsrFunction.js +61 -50
  19. package/constructs/SsrSite.d.ts +6 -4
  20. package/constructs/SsrSite.js +0 -4
  21. package/constructs/Stack.js +2 -1
  22. package/constructs/future/Auth.d.ts +79 -0
  23. package/constructs/future/Auth.js +116 -0
  24. package/constructs/future/index.d.ts +1 -0
  25. package/constructs/future/index.js +1 -0
  26. package/context/handler.d.ts +1 -1
  27. package/node/api/index.d.ts +27 -4
  28. package/node/api/index.js +64 -2
  29. package/node/auth/index.d.ts +3 -0
  30. package/node/auth/index.js +3 -0
  31. package/node/future/auth/adapter/adapter.d.ts +10 -0
  32. package/node/future/auth/adapter/adapter.js +1 -0
  33. package/node/future/auth/adapter/github.d.ts +16 -0
  34. package/node/future/auth/adapter/github.js +22 -0
  35. package/node/future/auth/adapter/google.d.ts +20 -0
  36. package/node/future/auth/adapter/google.js +10 -0
  37. package/node/future/auth/adapter/link.d.ts +11 -0
  38. package/node/future/auth/adapter/link.js +48 -0
  39. package/node/future/auth/adapter/oauth.d.ts +34 -0
  40. package/node/future/auth/adapter/oauth.js +66 -0
  41. package/node/future/auth/adapter/oidc.d.ts +26 -0
  42. package/node/future/auth/adapter/oidc.js +62 -0
  43. package/node/future/auth/handler.d.ts +18 -0
  44. package/node/future/auth/handler.js +189 -0
  45. package/node/future/auth/index.d.ts +10 -0
  46. package/node/future/auth/index.js +10 -0
  47. package/node/future/auth/session.d.ts +46 -0
  48. package/node/future/auth/session.js +99 -0
  49. package/node/util/index.js +1 -1
  50. package/package.json +4 -1
  51. package/runtime/handlers/node.js +1 -1
  52. package/sst.mjs +4 -4
  53. package/support/nodejs-runtime/index.mjs +62 -14629
@@ -0,0 +1,116 @@
1
+ import { Effect, Policy, PolicyStatement } from "aws-cdk-lib/aws-iam";
2
+ import { Construct } from "constructs";
3
+ import { Api } from "../Api.js";
4
+ import { Stack } from "../Stack.js";
5
+ import { Secret } from "../Secret.js";
6
+ import { getParameterPath, } from "../util/functionBinding.js";
7
+ import { CustomResource } from "aws-cdk-lib";
8
+ /**
9
+ * SST Auth is a lightweight authentication solution for your applications. With a simple set of configuration you can deploy a function attached to your API that can handle various authentication flows. *
10
+ * @example
11
+ * ```
12
+ * import { Auth } from "@serverless-stack/resources"
13
+ *
14
+ * new Auth(stack, "auth", {
15
+ * authenticator: "functions/authenticator.handler"
16
+ * })
17
+ */
18
+ export class Auth extends Construct {
19
+ id;
20
+ authenticator;
21
+ api;
22
+ publicKey;
23
+ privateKey;
24
+ constructor(scope, id, props) {
25
+ super(scope, props.cdk?.id || id);
26
+ if (!props.authenticator ||
27
+ "defaults" in props ||
28
+ "login" in props ||
29
+ "triggers" in props ||
30
+ "identityPoolFederation" in props ||
31
+ "cdk" in props) {
32
+ throw new Error(`It looks like you may be passing in Cognito props to the Auth construct. The Auth construct was renamed to Cognito in version 1.10.0`);
33
+ }
34
+ this.id = id;
35
+ const stack = Stack.of(scope);
36
+ this.authenticator = props.authenticator;
37
+ this.api = new Api(this, id + "-api", {
38
+ routes: {
39
+ "ANY /{step}": {
40
+ function: this.authenticator,
41
+ },
42
+ "ANY /": {
43
+ function: this.authenticator,
44
+ },
45
+ },
46
+ customDomain: props.customDomain,
47
+ });
48
+ this.publicKey = new Secret(this, id + "PublicKey");
49
+ this.privateKey = new Secret(this, id + "PrivateKey");
50
+ const fn = this.api.getFunction("ANY /{step}");
51
+ fn.bind([this.publicKey, this.privateKey]);
52
+ const app = this.node.root;
53
+ fn.addEnvironment("AUTH_ID", id);
54
+ fn.attachPermissions([
55
+ new PolicyStatement({
56
+ actions: ["ssm:GetParameters"],
57
+ effect: Effect.ALLOW,
58
+ resources: [
59
+ `arn:${Stack.of(this).partition}:ssm:${app.region}:${app.account}:parameter${getParameterPath(this.publicKey, "value")}`,
60
+ `arn:${Stack.of(this).partition}:ssm:${app.region}:${app.account}:parameter${getParameterPath(this.privateKey, "value")}`,
61
+ ],
62
+ }),
63
+ ]);
64
+ const policy = new Policy(this, "CloudFrontInvalidatorPolicy", {
65
+ statements: [
66
+ new PolicyStatement({
67
+ actions: [
68
+ "ssm:GetParameter",
69
+ "ssm:PutParameter",
70
+ "ssm:DeleteParameter",
71
+ ],
72
+ resources: [
73
+ `arn:${stack.partition}:ssm:${stack.region}:${stack.account}:parameter/*`,
74
+ ],
75
+ }),
76
+ ],
77
+ });
78
+ stack.customResourceHandler.role?.attachInlinePolicy(policy);
79
+ const resource = new CustomResource(this, "StackMetadata", {
80
+ serviceToken: stack.customResourceHandler.functionArn,
81
+ resourceType: "Custom::AuthKeys",
82
+ properties: {
83
+ publicPath: getParameterPath(this.publicKey, "value"),
84
+ privatePath: getParameterPath(this.privateKey, "value"),
85
+ },
86
+ });
87
+ resource.node.addDependency(policy);
88
+ }
89
+ get url() {
90
+ return this.api.customDomainUrl || this.api.url;
91
+ }
92
+ /** @internal */
93
+ getConstructMetadata() {
94
+ return {
95
+ type: "Auth",
96
+ data: {},
97
+ };
98
+ }
99
+ /** @internal */
100
+ getFunctionBinding() {
101
+ return {
102
+ clientPackage: "future/auth",
103
+ variables: {
104
+ publicKey: {
105
+ type: "secret_reference",
106
+ secret: this.publicKey,
107
+ },
108
+ url: {
109
+ type: "plain",
110
+ value: this.url,
111
+ },
112
+ },
113
+ permissions: {},
114
+ };
115
+ }
116
+ }
@@ -0,0 +1 @@
1
+ export * from "./Auth.js";
@@ -0,0 +1 @@
1
+ export * from "./Auth.js";
@@ -2,7 +2,7 @@ import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2, Context as L
2
2
  export interface Handlers {
3
3
  api: {
4
4
  event: APIGatewayProxyEventV2;
5
- response: APIGatewayProxyStructuredResultV2;
5
+ response: APIGatewayProxyStructuredResultV2 | void;
6
6
  };
7
7
  sqs: {
8
8
  event: SQSEvent;
@@ -2,6 +2,7 @@
2
2
  /// <reference types="node/url.js" />
3
3
  /// <reference types=".pnpm/@types+node@17.0.45/node_modules/@types/node/url.js" />
4
4
  import { Handler } from "../../context/handler.js";
5
+ import { APIGatewayProxyStructuredResultV2 } from "aws-lambda";
5
6
  export interface ApiResources {
6
7
  }
7
8
  export interface AppSyncApiResources {
@@ -23,19 +24,41 @@ export declare const WebSocketApi: WebSocketApiResources;
23
24
  * })
24
25
  * ```
25
26
  */
26
- export declare function ApiHandler(cb: Parameters<typeof Handler<"api">>[1]): (event: import("aws-lambda").APIGatewayProxyEventV2, context: import("aws-lambda").Context) => Promise<import("aws-lambda").APIGatewayProxyStructuredResultV2>;
27
- export declare const useCookies: () => any;
28
- export declare function useCookie(name: string): any;
27
+ export declare function ApiHandler(cb: Parameters<typeof Handler<"api">>[1]): (event: import("aws-lambda").APIGatewayProxyEventV2, context: import("aws-lambda").Context) => Promise<APIGatewayProxyStructuredResultV2>;
28
+ export declare const useCookies: () => {
29
+ [k: string]: string;
30
+ };
31
+ export declare function useCookie(name: string): string | undefined;
29
32
  export declare const useBody: () => string | undefined;
30
33
  export declare const useJsonBody: () => any;
31
34
  export declare const useFormData: () => import("url").URLSearchParams | undefined;
32
35
  export declare const usePath: () => string[];
36
+ interface CookieOptions {
37
+ expires?: Date;
38
+ maxAge?: number;
39
+ domain?: string;
40
+ path?: string;
41
+ secure?: boolean;
42
+ httpOnly?: boolean;
43
+ sameSite?: "Strict" | "Lax" | "None";
44
+ }
45
+ export declare const useResponse: () => {
46
+ cookies(values: Record<string, string>, options: CookieOptions): any;
47
+ cookie(input: {
48
+ key: string;
49
+ value: string;
50
+ } & CookieOptions): any;
51
+ status(code: number): any;
52
+ header(key: string, value: string): any;
53
+ serialize(input: APIGatewayProxyStructuredResultV2): APIGatewayProxyStructuredResultV2;
54
+ };
33
55
  export declare function useDomainName(): string;
34
56
  export declare function useMethod(): string;
35
57
  export declare function useHeaders(): import("aws-lambda").APIGatewayProxyEventHeaders;
36
58
  export declare function useHeader(key: string): string | undefined;
37
59
  export declare function useFormValue(name: string): string | null | undefined;
38
60
  export declare function useQueryParams(): import("aws-lambda").APIGatewayProxyEventQueryStringParameters;
39
- export declare function useQueryParam(name: string): string | undefined;
61
+ export declare function useQueryParam<T = string>(name: string): T | undefined;
40
62
  export declare function usePathParams(): import("aws-lambda").APIGatewayProxyEventPathParameters;
41
63
  export declare function usePathParam(name: string): string | undefined;
64
+ export {};
package/node/api/index.js CHANGED
@@ -19,12 +19,16 @@ Object.assign(WebSocketApi, getVariables("WebSocketApi"));
19
19
  * ```
20
20
  */
21
21
  export function ApiHandler(cb) {
22
- return Handler("api", cb);
22
+ return Handler("api", async (evt, ctx) => {
23
+ const result = await cb(evt, ctx);
24
+ const serialized = useResponse().serialize(result || {});
25
+ return serialized;
26
+ });
23
27
  }
24
28
  export const useCookies = /* @__PURE__ */ Context.memo(() => {
25
29
  const evt = useEvent("api");
26
30
  const cookies = evt.cookies || [];
27
- return Object.fromEntries(cookies.map((c) => c.split("=")));
31
+ return Object.fromEntries(cookies.map((c) => c.split("=")).map(([k, v]) => [k, decodeURIComponent(v)]));
28
32
  });
29
33
  export function useCookie(name) {
30
34
  const cookies = useCookies();
@@ -56,6 +60,64 @@ export const usePath = /* @__PURE__ */ Context.memo(() => {
56
60
  const evt = useEvent("api");
57
61
  return evt.rawPath.split("/").filter(Boolean);
58
62
  });
63
+ export const useResponse = /* @__PURE__ */ Context.memo(() => {
64
+ const response = {
65
+ headers: {},
66
+ cookies: [],
67
+ };
68
+ const result = {
69
+ cookies(values, options) {
70
+ for (const [key, value] of Object.entries(values)) {
71
+ result.cookie({
72
+ key,
73
+ value,
74
+ ...options,
75
+ });
76
+ }
77
+ return result;
78
+ },
79
+ cookie(input) {
80
+ const value = encodeURIComponent(input.value);
81
+ const parts = [input.key + "=" + value];
82
+ if (input.domain)
83
+ parts.push("Domain=" + input.domain);
84
+ if (input.path)
85
+ parts.push("Path=" + input.path);
86
+ if (input.expires)
87
+ parts.push("Expires=" + input.expires.toUTCString());
88
+ if (input.maxAge)
89
+ parts.push("Max-Age=" + input.maxAge);
90
+ if (input.httpOnly)
91
+ parts.push("HttpOnly");
92
+ if (input.secure)
93
+ parts.push("Secure");
94
+ if (input.sameSite)
95
+ parts.push("SameSite=" + input.sameSite);
96
+ response.cookies.push(parts.join("; "));
97
+ return result;
98
+ },
99
+ status(code) {
100
+ response.statusCode = code;
101
+ return result;
102
+ },
103
+ header(key, value) {
104
+ response.headers[key] = value;
105
+ return result;
106
+ },
107
+ serialize(input) {
108
+ return {
109
+ ...response,
110
+ ...input,
111
+ cookies: [...(input.cookies || []), ...response.cookies],
112
+ headers: {
113
+ ...response.headers,
114
+ ...input.headers,
115
+ },
116
+ };
117
+ },
118
+ };
119
+ return result;
120
+ });
59
121
  export function useDomainName() {
60
122
  const evt = useEvent("api");
61
123
  return evt.requestContext.domainName;
@@ -8,3 +8,6 @@ export * from "./adapter/github.js";
8
8
  export * from "./adapter/oidc.js";
9
9
  export * from "./adapter/oauth.js";
10
10
  export * from "./adapter/link.js";
11
+ export interface AuthResources {
12
+ }
13
+ export declare const Auth: AuthResources;
@@ -8,3 +8,6 @@ export * from "./adapter/github.js";
8
8
  export * from "./adapter/oidc.js";
9
9
  export * from "./adapter/oauth.js";
10
10
  export * from "./adapter/link.js";
11
+ import { createProxy, getVariables } from "../util/index.js";
12
+ export const Auth = createProxy("Auth");
13
+ Object.assign(Auth, await getVariables("Auth"));
@@ -0,0 +1,10 @@
1
+ import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from "aws-lambda";
2
+ export type Adapter<T = any> = (evt: APIGatewayProxyEventV2) => Promise<{
3
+ type: "step";
4
+ properties: APIGatewayProxyStructuredResultV2;
5
+ } | {
6
+ type: "success";
7
+ properties: T;
8
+ } | {
9
+ type: "error";
10
+ }>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import { OauthBasicConfig } from "./oauth.js";
2
+ export declare const GithubAdapter: (config: OauthBasicConfig) => () => Promise<{
3
+ type: "success";
4
+ properties: {
5
+ tokenset: import("openid-client").TokenSet;
6
+ client: import("openid-client").BaseClient;
7
+ };
8
+ } | {
9
+ type: "step";
10
+ properties: {
11
+ statusCode: number;
12
+ headers: {
13
+ location: string;
14
+ };
15
+ };
16
+ }>;
@@ -0,0 +1,22 @@
1
+ import { Issuer } from "openid-client";
2
+ import { OauthAdapter } from "./oauth.js";
3
+ import { OidcAdapter } from "./oidc.js";
4
+ const issuer = new Issuer({
5
+ issuer: "https://github.com",
6
+ authorization_endpoint: "https://github.com/login/oauth/authorize",
7
+ token_endpoint: "https://github.com/login/oauth/access_token",
8
+ });
9
+ export const GithubAdapter =
10
+ /* @__PURE__ */
11
+ (config) => {
12
+ if (config.clientSecret) {
13
+ return OauthAdapter({
14
+ issuer,
15
+ ...config,
16
+ });
17
+ }
18
+ return OidcAdapter({
19
+ issuer,
20
+ ...config,
21
+ });
22
+ };
@@ -0,0 +1,20 @@
1
+ import { OidcBasicConfig } from "./oidc.js";
2
+ type GoogleConfig = OidcBasicConfig & {
3
+ mode: "oidc";
4
+ };
5
+ export declare function GoogleAdapter(config: GoogleConfig): () => Promise<{
6
+ type: "success";
7
+ properties: {
8
+ tokenset: import("openid-client").TokenSet;
9
+ client: import("openid-client").BaseClient;
10
+ };
11
+ } | {
12
+ type: "step";
13
+ properties: {
14
+ statusCode: number;
15
+ headers: {
16
+ location: string;
17
+ };
18
+ };
19
+ }>;
20
+ export {};
@@ -0,0 +1,10 @@
1
+ import { Issuer } from "openid-client";
2
+ import { OidcAdapter } from "./oidc.js";
3
+ const issuer = await Issuer.discover("https://accounts.google.com");
4
+ export function GoogleAdapter(config) {
5
+ return OidcAdapter({
6
+ issuer,
7
+ scope: "openid email profile",
8
+ ...config,
9
+ });
10
+ }
@@ -0,0 +1,11 @@
1
+ import { APIGatewayProxyStructuredResultV2 } from "aws-lambda";
2
+ export declare function LinkAdapter(config: {
3
+ onLink: (link: string, claims: Record<string, any>) => Promise<APIGatewayProxyStructuredResultV2>;
4
+ onError: () => Promise<APIGatewayProxyStructuredResultV2>;
5
+ }): () => Promise<{
6
+ type: "step";
7
+ properties: APIGatewayProxyStructuredResultV2;
8
+ } | {
9
+ type: "success";
10
+ properties: any;
11
+ }>;
@@ -0,0 +1,48 @@
1
+ import { createSigner, createVerifier } from "fast-jwt";
2
+ import { Config } from "../../../config/index.js";
3
+ import { useDomainName, usePathParam, useQueryParam, useQueryParams, } from "../../../api/index.js";
4
+ export function LinkAdapter(config) {
5
+ // @ts-expect-error
6
+ const key = Config[process.env.AUTH_ID + "PrivateKey"];
7
+ const signer = createSigner({
8
+ expiresIn: 1000 * 60 * 10,
9
+ key,
10
+ algorithm: "RS512",
11
+ });
12
+ return async function () {
13
+ const callback = "https://" + useDomainName() + "/callback";
14
+ const step = usePathParam("step");
15
+ if (step === "authorize") {
16
+ const url = new URL(callback);
17
+ const claims = useQueryParams();
18
+ url.searchParams.append("token", signer(claims));
19
+ return {
20
+ type: "step",
21
+ properties: await config.onLink(url.toString(), claims),
22
+ };
23
+ }
24
+ if (step === "callback") {
25
+ const token = useQueryParam("token");
26
+ if (!token)
27
+ throw new Error("Missing token parameter");
28
+ try {
29
+ const verifier = createVerifier({
30
+ algorithms: ["RS512"],
31
+ key,
32
+ });
33
+ const jwt = verifier(token);
34
+ return {
35
+ type: "success",
36
+ properties: jwt,
37
+ };
38
+ }
39
+ catch {
40
+ return {
41
+ type: "step",
42
+ properties: await config.onError(),
43
+ };
44
+ }
45
+ }
46
+ throw new Error("Invalid auth request");
47
+ };
48
+ }
@@ -0,0 +1,34 @@
1
+ import { BaseClient, Issuer, TokenSet } from "openid-client";
2
+ export interface OauthBasicConfig {
3
+ /**
4
+ * The clientID provided by the third party oauth service
5
+ */
6
+ clientID: string;
7
+ /**
8
+ * The clientSecret provided by the third party oauth service
9
+ */
10
+ clientSecret: string;
11
+ /**
12
+ * Various scopes requested for the access token
13
+ */
14
+ scope: string;
15
+ prompt?: string;
16
+ }
17
+ export interface OauthConfig extends OauthBasicConfig {
18
+ issuer: Issuer;
19
+ }
20
+ export declare const OauthAdapter: (config: OauthConfig) => () => Promise<{
21
+ type: "success";
22
+ properties: {
23
+ tokenset: TokenSet;
24
+ client: BaseClient;
25
+ };
26
+ } | {
27
+ type: "step";
28
+ properties: {
29
+ statusCode: number;
30
+ headers: {
31
+ location: string;
32
+ };
33
+ };
34
+ }>;
@@ -0,0 +1,66 @@
1
+ import { generators } from "openid-client";
2
+ import { useCookie, useDomainName, usePathParam, useQueryParams, useResponse, } from "../../../api/index.js";
3
+ export const OauthAdapter =
4
+ /* @__PURE__ */
5
+ (config) => {
6
+ return async function () {
7
+ const step = usePathParam("step");
8
+ const callback = "https://" + useDomainName() + "/callback";
9
+ const client = new config.issuer.Client({
10
+ client_id: config.clientID,
11
+ client_secret: config.clientSecret,
12
+ redirect_uris: [callback],
13
+ response_types: ["code"],
14
+ });
15
+ if (step === "authorize") {
16
+ const code_verifier = generators.codeVerifier();
17
+ const state = generators.state();
18
+ const code_challenge = generators.codeChallenge(code_verifier);
19
+ const url = client.authorizationUrl({
20
+ scope: config.scope,
21
+ code_challenge: code_challenge,
22
+ code_challenge_method: "S256",
23
+ state,
24
+ prompt: config.prompt,
25
+ });
26
+ useResponse().cookies({
27
+ auth_code_verifier: code_verifier,
28
+ auth_state: state,
29
+ }, {
30
+ httpOnly: true,
31
+ secure: true,
32
+ maxAge: 60 * 10,
33
+ sameSite: "None",
34
+ });
35
+ return {
36
+ type: "step",
37
+ properties: {
38
+ statusCode: 302,
39
+ headers: {
40
+ location: url,
41
+ },
42
+ },
43
+ };
44
+ }
45
+ if (step === "callback") {
46
+ const params = useQueryParams();
47
+ const code_verifier = useCookie("auth_code_verifier");
48
+ const state = useCookie("auth_state");
49
+ const tokenset = await client[config.issuer.metadata.userinfo_endpoint
50
+ ? "callback"
51
+ : "oauthCallback"](callback, params, {
52
+ code_verifier,
53
+ state,
54
+ });
55
+ const x = {
56
+ type: "success",
57
+ properties: {
58
+ tokenset,
59
+ client,
60
+ },
61
+ };
62
+ return x;
63
+ }
64
+ throw new Error("Invalid auth request");
65
+ };
66
+ };
@@ -0,0 +1,26 @@
1
+ import { Issuer } from "openid-client";
2
+ export interface OidcBasicConfig {
3
+ /**
4
+ * The clientID provided by the third party oauth service
5
+ */
6
+ clientID: string;
7
+ }
8
+ export interface OidcConfig extends OidcBasicConfig {
9
+ issuer: Issuer;
10
+ scope: string;
11
+ }
12
+ export declare const OidcAdapter: (config: OidcConfig) => () => Promise<{
13
+ type: "success";
14
+ properties: {
15
+ tokenset: import("openid-client").TokenSet;
16
+ client: import("openid-client").BaseClient;
17
+ };
18
+ } | {
19
+ type: "step";
20
+ properties: {
21
+ statusCode: number;
22
+ headers: {
23
+ location: string;
24
+ };
25
+ };
26
+ }>;
@@ -0,0 +1,62 @@
1
+ import { generators } from "openid-client";
2
+ import { useCookie, useDomainName, useFormData, usePathParam, useResponse, } from "../../../api/index.js";
3
+ export const OidcAdapter = /* @__PURE__ */ (config) => {
4
+ return async function () {
5
+ const step = usePathParam("step");
6
+ const callback = "https://" + useDomainName() + "/callback";
7
+ const client = new config.issuer.Client({
8
+ client_id: config.clientID,
9
+ redirect_uris: [callback],
10
+ response_types: ["id_token"],
11
+ });
12
+ if (step === "authorize") {
13
+ const nonce = generators.nonce();
14
+ const state = generators.state();
15
+ const url = client.authorizationUrl({
16
+ scope: config.scope,
17
+ response_mode: "form_post",
18
+ nonce,
19
+ state,
20
+ });
21
+ useResponse().cookies({
22
+ auth_nonce: nonce,
23
+ auth_state: state,
24
+ }, {
25
+ httpOnly: true,
26
+ secure: true,
27
+ maxAge: 60 * 10,
28
+ sameSite: "None",
29
+ });
30
+ return {
31
+ type: "step",
32
+ properties: {
33
+ statusCode: 302,
34
+ headers: {
35
+ location: url,
36
+ },
37
+ },
38
+ };
39
+ }
40
+ if (step === "callback") {
41
+ const form = useFormData();
42
+ if (!form)
43
+ throw new Error("Missing body");
44
+ const params = Object.fromEntries(form.entries());
45
+ const nonce = useCookie("auth_nonce");
46
+ const state = useCookie("auth_state");
47
+ const tokenset = await client.callback(callback, params, {
48
+ nonce,
49
+ state,
50
+ });
51
+ const x = {
52
+ type: "success",
53
+ properties: {
54
+ tokenset,
55
+ client,
56
+ },
57
+ };
58
+ return x;
59
+ }
60
+ throw new Error("Invalid auth request");
61
+ };
62
+ };
@@ -0,0 +1,18 @@
1
+ import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from "aws-lambda";
2
+ import { Adapter } from "./adapter/adapter.js";
3
+ import { SignerOptions } from "fast-jwt";
4
+ import { SessionValue } from "./session.js";
5
+ export declare function AuthHandler<Providers extends Record<string, Adapter<any>>, Result = {
6
+ [key in keyof Providers]: {
7
+ provider: key;
8
+ } & Extract<Awaited<ReturnType<Providers[key]>>, {
9
+ type: "success";
10
+ }>["properties"];
11
+ }[keyof Providers]>(input: {
12
+ providers: Providers;
13
+ clients: () => Promise<Record<string, string>>;
14
+ onAuthorize?: (event: APIGatewayProxyEventV2) => Promise<void | keyof Providers>;
15
+ onSuccess: (input: Result) => Promise<SessionCreateInput>;
16
+ onError: () => Promise<APIGatewayProxyStructuredResultV2>;
17
+ }): (event: APIGatewayProxyEventV2, context: import("aws-lambda").Context) => Promise<APIGatewayProxyStructuredResultV2>;
18
+ export type SessionCreateInput = SessionValue & Partial<SignerOptions>;