sst 2.26.6 → 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.
@@ -42,7 +42,7 @@ export const bind = (program) => program
42
42
  if (!command) {
43
43
  throw new VisibleError("Command is required, e.g. sst bind npm run script");
44
44
  }
45
- await useIOT();
45
+ useIOT();
46
46
  const bus = useBus();
47
47
  const project = useProject();
48
48
  let p;
package/config.js CHANGED
@@ -179,6 +179,7 @@ async function* scanParameters(prefix) {
179
179
  Recursive: true,
180
180
  NextToken: token,
181
181
  }));
182
+ console.log("results", results.Parameters?.length);
182
183
  yield* results.Parameters || [];
183
184
  if (!results.NextToken)
184
185
  break;
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 && !this.isRunningSSTTest()) {
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);
@@ -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
+ }
@@ -1 +1,4 @@
1
- export {};
1
+ export class AdapterError extends Error {
2
+ }
3
+ export class AdapterUnknownError extends AdapterError {
4
+ }
@@ -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: "error",
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
  }
@@ -13,4 +13,9 @@ export declare const FacebookAdapter: (config: OauthBasicConfig) => () => Promis
13
13
  location: string;
14
14
  };
15
15
  };
16
- }>;
16
+ error?: undefined;
17
+ } | {
18
+ type: "error";
19
+ error: import("./oauth.js").OauthError;
20
+ properties?: undefined;
21
+ } | undefined>;
@@ -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 {};
@@ -7,7 +7,4 @@ export declare function LinkAdapter(config: {
7
7
  } | {
8
8
  type: "success";
9
9
  properties: any;
10
- } | {
11
- type: "error";
12
- properties?: undefined;
13
- }>;
10
+ } | undefined>;
@@ -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({
@@ -20,4 +20,9 @@ export declare const SpotifyAdapter: (config: OauthBasicConfig) => () => Promise
20
20
  location: string;
21
21
  };
22
22
  };
23
- }>;
23
+ error?: undefined;
24
+ } | {
25
+ type: "error";
26
+ error: import("./oauth.js").OauthError;
27
+ properties?: undefined;
28
+ } | undefined>;
@@ -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, SessionValue } from "./session.js";
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
- onSuccess: (input: Result, response: OnSuccessResponder<SessionValue | {
33
- [key in keyof Sessions["$type"]]: {
34
- type: key;
35
- properties: Sessions["$type"][key];
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
- }[keyof Sessions["$type"]]>) => Promise<ReturnType<OnSuccessResponder<SessionValue | {
38
- [key in keyof Sessions["$type"]]: {
39
- type: key;
40
- properties: Sessions["$type"][key];
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
- }[keyof Sessions["$type"]]>[keyof OnSuccessResponder<any>]>>;
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.onIndex) {
15
- return input.onIndex(evt);
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
- if (step === "authorize") {
94
- provider = useQueryParam("provider");
95
- if (input.onAuthorize) {
96
- const result = await input.onAuthorize(evt);
97
- if (result)
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 { response_type, client_id, redirect_uri, state } = {
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
- !(await input.allowClient(client_id, redirect_uri))) {
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,119 +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 response = input.onError?.(new UnknownProviderError(provider));
165
- if (response)
166
- return response;
167
- return {
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: `Was not able to find provider "${String(provider)}"`,
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
- const onSuccess = await input.onSuccess({
182
- provider,
183
- ...result.properties,
184
- }, {
185
- http(input) {
186
- return {
187
- type: "http",
188
- properties: input,
189
- };
190
- },
191
- session(input) {
192
- return {
193
- type: "session",
194
- properties: input,
195
- };
196
- },
197
- });
198
- if (onSuccess.type === "session") {
199
- const { type, properties, ...rest } = onSuccess.properties;
200
- // @ts-expect-error
201
- const priv = Config[process.env.AUTH_ID + "PrivateKey"];
202
- const signer = createSigner({
203
- ...rest,
204
- key: priv,
205
- algorithm: "RS512",
206
- });
207
- const token = signer({
208
- type,
209
- properties,
210
- });
211
- useResponse()
212
- .cookie({
213
- key: "sst_auth_token",
214
- value: token,
215
- maxAge: 10 * 365 * 24 * 60 * 60,
216
- })
217
- .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({
218
261
  provider: "",
219
262
  response_type: "",
220
- client_id: "",
221
- redirect_uri: "",
222
- state: "",
263
+ sst_auth_token: "",
223
264
  }, {
224
265
  expires: new Date(1),
225
266
  });
226
- const { client_id, response_type, redirect_uri, state } = {
227
- ...useCookies(),
228
- ...useQueryParams(),
229
- };
230
- if (response_type === "token") {
231
- const location = new URL(redirect_uri);
232
- location.hash = `access_token=${token}&state=${state || ""}`;
233
- return {
234
- statusCode: 302,
235
- headers: {
236
- Location: location.href,
237
- },
238
- };
239
- }
240
- if (response_type === "code") {
241
- // This allows the code to be reused within a 30 second window
242
- // The code should be single use but we're making this tradeoff to remain stateless
243
- // In the future can store this in a dynamo table to ensure single use
244
- const code = createSigner({
245
- expiresIn: 1000 * 60 * 5,
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,
246
296
  key: priv,
247
297
  algorithm: "RS512",
248
- })({
249
- client_id,
250
- redirect_uri,
251
- token: token,
252
298
  });
253
- const location = new URL(redirect_uri);
254
- location.searchParams.set("code", code);
255
- location.searchParams.set("state", state || "");
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
+ }
256
352
  return {
257
- statusCode: 302,
258
- headers: {
259
- Location: location.href,
260
- },
353
+ statusCode: 400,
354
+ body: `Unsupported response_type: ${response_type}`,
261
355
  };
262
356
  }
263
- return {
264
- statusCode: 400,
265
- body: `Unsupported response_type: ${response_type}`,
266
- };
267
- }
268
- if (onSuccess.type === "http") {
269
- return onSuccess.properties;
357
+ if (onSuccess.type === "http") {
358
+ return onSuccess.properties;
359
+ }
270
360
  }
271
361
  }
272
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);
273
377
  return {
274
- statusCode: 400,
275
- body: "an error has occured",
378
+ statusCode: 302,
379
+ headers: {
380
+ Location: location.toString(),
381
+ },
276
382
  };
277
383
  }
278
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 {};
@@ -142,5 +142,6 @@ export function createSessionBuilder() {
142
142
  return ctx;
143
143
  },
144
144
  $type: {},
145
+ $typeValues: {},
145
146
  };
146
147
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "sideEffects": false,
3
3
  "name": "sst",
4
- "version": "2.26.6",
4
+ "version": "2.26.7",
5
5
  "bin": {
6
6
  "sst": "cli/sst.js"
7
7
  },