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.
- package/bootstrap.js +1 -1
- package/cli/commands/bind.js +1 -1
- package/cli/commands/env.js +1 -1
- package/constructs/App.js +3 -3
- package/constructs/AstroSite.js +8 -41
- package/constructs/EdgeFunction.d.ts +19 -21
- package/constructs/EdgeFunction.js +235 -167
- package/constructs/Function.d.ts +1 -1
- package/constructs/Function.js +3 -3
- package/constructs/Job.js +2 -2
- package/constructs/NextjsSite.d.ts +6 -5
- package/constructs/NextjsSite.js +5 -3
- package/constructs/RDS.js +1 -1
- package/constructs/RemixSite.d.ts +2 -3
- package/constructs/RemixSite.js +42 -71
- package/constructs/SolidStartSite.js +8 -41
- package/constructs/SsrFunction.d.ts +9 -6
- package/constructs/SsrFunction.js +61 -50
- package/constructs/SsrSite.d.ts +6 -4
- package/constructs/SsrSite.js +0 -4
- package/constructs/Stack.js +2 -1
- package/constructs/future/Auth.d.ts +79 -0
- package/constructs/future/Auth.js +116 -0
- package/constructs/future/index.d.ts +1 -0
- package/constructs/future/index.js +1 -0
- package/context/handler.d.ts +1 -1
- package/node/api/index.d.ts +27 -4
- package/node/api/index.js +64 -2
- package/node/auth/index.d.ts +3 -0
- package/node/auth/index.js +3 -0
- package/node/future/auth/adapter/adapter.d.ts +10 -0
- package/node/future/auth/adapter/adapter.js +1 -0
- package/node/future/auth/adapter/github.d.ts +16 -0
- package/node/future/auth/adapter/github.js +22 -0
- package/node/future/auth/adapter/google.d.ts +20 -0
- package/node/future/auth/adapter/google.js +10 -0
- package/node/future/auth/adapter/link.d.ts +11 -0
- package/node/future/auth/adapter/link.js +48 -0
- package/node/future/auth/adapter/oauth.d.ts +34 -0
- package/node/future/auth/adapter/oauth.js +66 -0
- package/node/future/auth/adapter/oidc.d.ts +26 -0
- package/node/future/auth/adapter/oidc.js +62 -0
- package/node/future/auth/handler.d.ts +18 -0
- package/node/future/auth/handler.js +189 -0
- package/node/future/auth/index.d.ts +10 -0
- package/node/future/auth/index.js +10 -0
- package/node/future/auth/session.d.ts +46 -0
- package/node/future/auth/session.js +99 -0
- package/node/util/index.js +1 -1
- package/package.json +4 -1
- package/runtime/handlers/node.js +1 -1
- package/sst.mjs +4 -4
- package/support/nodejs-runtime/index.mjs +62 -14629
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { createSigner, createVerifier } from "fast-jwt";
|
|
2
|
+
import { ApiHandler, useCookie, useCookies, useFormValue, usePathParam, useQueryParam, useQueryParams, useResponse, } from "../../api/index.js";
|
|
3
|
+
import { Config } from "../../config/index.js";
|
|
4
|
+
export function AuthHandler(input) {
|
|
5
|
+
return ApiHandler(async (evt) => {
|
|
6
|
+
const step = usePathParam("step");
|
|
7
|
+
if (!step) {
|
|
8
|
+
return {
|
|
9
|
+
statusCode: 200,
|
|
10
|
+
headers: {
|
|
11
|
+
"Content-Type": "text/html",
|
|
12
|
+
},
|
|
13
|
+
body: `
|
|
14
|
+
<html>
|
|
15
|
+
<body>
|
|
16
|
+
${Object.keys(input.providers).map((name) => {
|
|
17
|
+
return `<a href="/authorize?provider=${name}&response_type=code&client_id=local&redirect_uri=http://localhost:300">${name}</a>`;
|
|
18
|
+
})}
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
|
21
|
+
`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (step === "token") {
|
|
25
|
+
if (useFormValue("grant_type") !== "authorization_code") {
|
|
26
|
+
return {
|
|
27
|
+
statusCode: 400,
|
|
28
|
+
body: "Invalid grant_type",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const code = useFormValue("code");
|
|
32
|
+
if (!code) {
|
|
33
|
+
return {
|
|
34
|
+
statusCode: 400,
|
|
35
|
+
body: "Missing code",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// @ts-expect-error
|
|
39
|
+
const pub = Config[process.env.AUTH_ID + "PublicKey"];
|
|
40
|
+
const verified = createVerifier({
|
|
41
|
+
algorithms: ["RS512"],
|
|
42
|
+
key: pub,
|
|
43
|
+
})(code);
|
|
44
|
+
if (verified.redirect_uri !== useFormValue("redirect_uri")) {
|
|
45
|
+
return {
|
|
46
|
+
statusCode: 400,
|
|
47
|
+
body: "redirect_uri mismatch",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (verified.client_id !== useFormValue("client_id")) {
|
|
51
|
+
return {
|
|
52
|
+
statusCode: 400,
|
|
53
|
+
body: "client_id mismatch",
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
statusCode: 200,
|
|
58
|
+
headers: {
|
|
59
|
+
"content-type": "application/json",
|
|
60
|
+
},
|
|
61
|
+
body: JSON.stringify({
|
|
62
|
+
access_token: verified.token,
|
|
63
|
+
}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
let provider = useCookie("provider");
|
|
67
|
+
if (step === "authorize") {
|
|
68
|
+
provider = useQueryParam("provider");
|
|
69
|
+
if (input.onAuthorize) {
|
|
70
|
+
const result = await input.onAuthorize(evt);
|
|
71
|
+
if (result)
|
|
72
|
+
provider = result;
|
|
73
|
+
}
|
|
74
|
+
if (!provider) {
|
|
75
|
+
return {
|
|
76
|
+
statusCode: 400,
|
|
77
|
+
body: "Missing provider",
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const { response_type, client_id, redirect_uri, state } = useQueryParams();
|
|
81
|
+
if (!provider) {
|
|
82
|
+
return {
|
|
83
|
+
statusCode: 400,
|
|
84
|
+
body: "Missing provider",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (!response_type) {
|
|
88
|
+
return {
|
|
89
|
+
statusCode: 400,
|
|
90
|
+
body: "Missing response_type",
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (!client_id) {
|
|
94
|
+
return {
|
|
95
|
+
statusCode: 400,
|
|
96
|
+
body: "Missing client_id",
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (!redirect_uri) {
|
|
100
|
+
return {
|
|
101
|
+
statusCode: 400,
|
|
102
|
+
body: "Missing redirect_uri",
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
useResponse().cookies({
|
|
106
|
+
provider: provider,
|
|
107
|
+
response_type: response_type,
|
|
108
|
+
client_id: client_id,
|
|
109
|
+
redirect_uri: redirect_uri,
|
|
110
|
+
state: state || "",
|
|
111
|
+
}, {
|
|
112
|
+
maxAge: 60 * 15,
|
|
113
|
+
secure: true,
|
|
114
|
+
sameSite: "None",
|
|
115
|
+
httpOnly: true,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
if (!provider || !input.providers[provider]) {
|
|
119
|
+
return {
|
|
120
|
+
statusCode: 400,
|
|
121
|
+
body: `Was not able to find provider "${String(provider)}"`,
|
|
122
|
+
headers: {
|
|
123
|
+
"Content-Type": "text/html",
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const adapter = input.providers[provider];
|
|
128
|
+
const result = await adapter(evt);
|
|
129
|
+
if (result.type === "step") {
|
|
130
|
+
return result.properties;
|
|
131
|
+
}
|
|
132
|
+
if (result.type === "success") {
|
|
133
|
+
const { type, properties, ...rest } = await input.onSuccess({
|
|
134
|
+
provider,
|
|
135
|
+
...result.properties,
|
|
136
|
+
});
|
|
137
|
+
// @ts-expect-error
|
|
138
|
+
const priv = Config[process.env.AUTH_ID + "PrivateKey"];
|
|
139
|
+
const signer = createSigner({
|
|
140
|
+
...rest,
|
|
141
|
+
key: priv,
|
|
142
|
+
algorithm: "RS512",
|
|
143
|
+
});
|
|
144
|
+
const token = signer({
|
|
145
|
+
type,
|
|
146
|
+
properties,
|
|
147
|
+
});
|
|
148
|
+
const { client_id, response_type, redirect_uri, state } = {
|
|
149
|
+
...useCookies(),
|
|
150
|
+
...useQueryParams(),
|
|
151
|
+
};
|
|
152
|
+
if (response_type === "token") {
|
|
153
|
+
return {
|
|
154
|
+
statusCode: 302,
|
|
155
|
+
headers: {
|
|
156
|
+
Location: `${redirect_uri}#access_token=${token}&state=${state || ""}`,
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
if (response_type === "code") {
|
|
161
|
+
// This allows the code to be reused within a 30 second window
|
|
162
|
+
// The code should be single use but we're making this tradeoff to remain stateless
|
|
163
|
+
// In the future can store this in a dynamo table to ensure single use
|
|
164
|
+
const code = createSigner({
|
|
165
|
+
expiresIn: 1000 * 60 * 5,
|
|
166
|
+
key: priv,
|
|
167
|
+
algorithm: "RS512",
|
|
168
|
+
})({
|
|
169
|
+
client_id,
|
|
170
|
+
redirect_uri,
|
|
171
|
+
token: token,
|
|
172
|
+
});
|
|
173
|
+
return {
|
|
174
|
+
statusCode: 302,
|
|
175
|
+
headers: {
|
|
176
|
+
Location: `${redirect_uri}?code=${code}&state=${state || ""}`,
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
statusCode: 400,
|
|
182
|
+
body: `Unsupported response_type: ${response_type}`,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
if (result.type === "error") {
|
|
186
|
+
return input.onError();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface AuthResources {
|
|
2
|
+
}
|
|
3
|
+
export declare const Auth: AuthResources;
|
|
4
|
+
export * from "./adapter/oidc.js";
|
|
5
|
+
export * from "./adapter/google.js";
|
|
6
|
+
export * from "./adapter/link.js";
|
|
7
|
+
export * from "./adapter/github.js";
|
|
8
|
+
export * from "./adapter/oauth.js";
|
|
9
|
+
export * from "./session.js";
|
|
10
|
+
export * from "./handler.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createProxy, getVariables } from "../../util/index.js";
|
|
2
|
+
export const Auth = createProxy("Auth");
|
|
3
|
+
Object.assign(Auth, getVariables("Auth"));
|
|
4
|
+
export * from "./adapter/oidc.js";
|
|
5
|
+
export * from "./adapter/google.js";
|
|
6
|
+
export * from "./adapter/link.js";
|
|
7
|
+
export * from "./adapter/github.js";
|
|
8
|
+
export * from "./adapter/oauth.js";
|
|
9
|
+
export * from "./session.js";
|
|
10
|
+
export * from "./handler.js";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { SignerOptions } from "fast-jwt";
|
|
2
|
+
export interface SessionTypes {
|
|
3
|
+
public: {};
|
|
4
|
+
}
|
|
5
|
+
export type SessionValue = {
|
|
6
|
+
[type in keyof SessionTypes]: {
|
|
7
|
+
type: type;
|
|
8
|
+
properties: SessionTypes[type];
|
|
9
|
+
};
|
|
10
|
+
}[keyof SessionTypes];
|
|
11
|
+
export declare function useSession<T = SessionValue>(): T;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new session token with provided information
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```js
|
|
17
|
+
* Session.create({
|
|
18
|
+
* type: "user",
|
|
19
|
+
* properties: {
|
|
20
|
+
* userID: "123"
|
|
21
|
+
* }
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare function create<T extends keyof SessionTypes>(input: {
|
|
26
|
+
type: T;
|
|
27
|
+
properties: SessionTypes[T];
|
|
28
|
+
options?: Partial<SignerOptions>;
|
|
29
|
+
}): string;
|
|
30
|
+
/**
|
|
31
|
+
* Verifies a session token and returns the session data
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```js
|
|
35
|
+
* Session.verify()
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare function verify<T = SessionValue>(token: string): T | {
|
|
39
|
+
type: string;
|
|
40
|
+
properties: {};
|
|
41
|
+
};
|
|
42
|
+
export declare const Session: {
|
|
43
|
+
create: typeof create;
|
|
44
|
+
verify: typeof verify;
|
|
45
|
+
};
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createSigner, createVerifier } from "fast-jwt";
|
|
2
|
+
import { Context } from "../../../context/context.js";
|
|
3
|
+
import { useCookie, useHeader } from "../../api/index.js";
|
|
4
|
+
import { Auth } from "../../auth/index.js";
|
|
5
|
+
import { Config } from "../../config/index.js";
|
|
6
|
+
const SessionMemo = /* @__PURE__ */ Context.memo(() => {
|
|
7
|
+
let token = "";
|
|
8
|
+
const header = useHeader("authorization");
|
|
9
|
+
if (header)
|
|
10
|
+
token = header.substring(7);
|
|
11
|
+
const cookie = useCookie("sst_auth_token");
|
|
12
|
+
if (cookie)
|
|
13
|
+
token = cookie;
|
|
14
|
+
if (token) {
|
|
15
|
+
try {
|
|
16
|
+
const jwt = createVerifier({
|
|
17
|
+
algorithms: ["RS512"],
|
|
18
|
+
key: getPublicKey(),
|
|
19
|
+
})(token);
|
|
20
|
+
return jwt;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return {
|
|
24
|
+
type: "public",
|
|
25
|
+
properties: {},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
type: "public",
|
|
31
|
+
properties: {},
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
// This is a crazy TS hack to prevent the types from being evaluated too soon
|
|
35
|
+
export function useSession() {
|
|
36
|
+
const ctx = SessionMemo();
|
|
37
|
+
return ctx;
|
|
38
|
+
}
|
|
39
|
+
function getPublicKey() {
|
|
40
|
+
const [first] = Object.values(Auth);
|
|
41
|
+
if (!first)
|
|
42
|
+
throw new Error("No auth provider found. Did you forget to add one?");
|
|
43
|
+
return first.publicKey;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Creates a new session token with provided information
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```js
|
|
50
|
+
* Session.create({
|
|
51
|
+
* type: "user",
|
|
52
|
+
* properties: {
|
|
53
|
+
* userID: "123"
|
|
54
|
+
* }
|
|
55
|
+
* })
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
function create(input) {
|
|
59
|
+
// @ts-expect-error
|
|
60
|
+
const key = Config[process.env.AUTH_ID + "PrivateKey"];
|
|
61
|
+
const signer = createSigner({
|
|
62
|
+
...input.options,
|
|
63
|
+
key,
|
|
64
|
+
algorithm: "RS512",
|
|
65
|
+
});
|
|
66
|
+
const token = signer({
|
|
67
|
+
type: input.type,
|
|
68
|
+
properties: input.properties,
|
|
69
|
+
});
|
|
70
|
+
return token;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Verifies a session token and returns the session data
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```js
|
|
77
|
+
* Session.verify()
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
function verify(token) {
|
|
81
|
+
if (token) {
|
|
82
|
+
try {
|
|
83
|
+
const jwt = createVerifier({
|
|
84
|
+
algorithms: ["RS512"],
|
|
85
|
+
key: getPublicKey(),
|
|
86
|
+
})(token);
|
|
87
|
+
return jwt;
|
|
88
|
+
}
|
|
89
|
+
catch { }
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
type: "public",
|
|
93
|
+
properties: {},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export const Session = {
|
|
97
|
+
create,
|
|
98
|
+
verify,
|
|
99
|
+
};
|
package/node/util/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sst",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.18",
|
|
4
4
|
"bin": {
|
|
5
5
|
"sst": "cli/sst.js"
|
|
6
6
|
},
|
|
@@ -14,8 +14,10 @@
|
|
|
14
14
|
},
|
|
15
15
|
"exports": {
|
|
16
16
|
"./constructs/deprecated": "./constructs/deprecated/index.js",
|
|
17
|
+
"./constructs/future": "./constructs/future/index.js",
|
|
17
18
|
"./constructs": "./constructs/index.js",
|
|
18
19
|
"./context": "./context/index.js",
|
|
20
|
+
"./node/future/*": "./node/future/*/index.js",
|
|
19
21
|
"./node/*": "./node/*/index.js",
|
|
20
22
|
".": "./index.js",
|
|
21
23
|
"./*": "./*"
|
|
@@ -113,6 +115,7 @@
|
|
|
113
115
|
"@types/ws": "^8.5.3",
|
|
114
116
|
"@types/yargs": "^17.0.13",
|
|
115
117
|
"tsx": "^3.12.1",
|
|
118
|
+
"typescript": "^4.9.5",
|
|
116
119
|
"vitest": "^0.28.3"
|
|
117
120
|
},
|
|
118
121
|
"peerDependencies": {
|
package/runtime/handlers/node.js
CHANGED
|
@@ -116,7 +116,7 @@ export const useNodeHandler = Context.memo(async () => {
|
|
|
116
116
|
? {
|
|
117
117
|
format: "esm",
|
|
118
118
|
target: "esnext",
|
|
119
|
-
mainFields:
|
|
119
|
+
mainFields: ["module", "main"],
|
|
120
120
|
banner: {
|
|
121
121
|
js: [
|
|
122
122
|
`import { createRequire as topLevelCreateRequire } from 'module';`,
|
package/sst.mjs
CHANGED
|
@@ -2919,7 +2919,7 @@ async function bootstrapCDK() {
|
|
|
2919
2919
|
AWS_PROFILE: profile
|
|
2920
2920
|
},
|
|
2921
2921
|
stdio: "pipe",
|
|
2922
|
-
shell:
|
|
2922
|
+
shell: true
|
|
2923
2923
|
}
|
|
2924
2924
|
);
|
|
2925
2925
|
let stderr = "";
|
|
@@ -4990,7 +4990,7 @@ var init_node = __esm({
|
|
|
4990
4990
|
...isESM ? {
|
|
4991
4991
|
format: "esm",
|
|
4992
4992
|
target: "esnext",
|
|
4993
|
-
mainFields:
|
|
4993
|
+
mainFields: ["module", "main"],
|
|
4994
4994
|
banner: {
|
|
4995
4995
|
js: [
|
|
4996
4996
|
`import { createRequire as topLevelCreateRequire } from 'module';`,
|
|
@@ -6720,7 +6720,7 @@ var env = (program2) => program2.command(
|
|
|
6720
6720
|
AWS_REGION: project.config.region
|
|
6721
6721
|
},
|
|
6722
6722
|
stdio: "inherit",
|
|
6723
|
-
shell:
|
|
6723
|
+
shell: true
|
|
6724
6724
|
});
|
|
6725
6725
|
process.exitCode = result.status || void 0;
|
|
6726
6726
|
break;
|
|
@@ -7061,7 +7061,7 @@ var bind = (program2) => program2.command(
|
|
|
7061
7061
|
AWS_REGION: project.config.region
|
|
7062
7062
|
},
|
|
7063
7063
|
stdio: "inherit",
|
|
7064
|
-
shell:
|
|
7064
|
+
shell: true
|
|
7065
7065
|
});
|
|
7066
7066
|
process.exitCode = result.status || void 0;
|
|
7067
7067
|
}
|