@infoxchange/make-it-so 2.10.0-internal-testing-vdt-199-add-oidc-auth.4 → 2.10.0-internal-testing-vdt-199-add-oidc-auth.6

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.
@@ -1,2 +1,2 @@
1
- export declare const handler: (event: any, context: any) => Promise<APIGatewayProxyStructuredResultV2>;
1
+ export {};
2
2
  //# sourceMappingURL=auth-check.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-check.d.ts","sourceRoot":"","sources":["../../../src/cdk-constructs/CloudWatchOidcAuth/auth-check.ts"],"names":[],"mappings":"AA+FA,eAAO,MAAM,OAAO,0EAiClB,CAAA"}
1
+ {"version":3,"file":"auth-check.d.ts","sourceRoot":"","sources":["../../../src/cdk-constructs/CloudWatchOidcAuth/auth-check.ts"],"names":[],"mappings":""}
@@ -1,7 +1,8 @@
1
1
  // Based off: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example_cloudfront_functions_kvs_jwt_verify_section.html
2
+ // Note that as a CloudFront Function, this code has limitations compared to a Lambda@Edge function.
3
+ // For example, no external libraries can be used, and the runtime is more limited.
2
4
  import crypto from "crypto";
3
5
  import cf from "cloudfront";
4
- import { ApiHandler, useCookie } from "sst/node/api";
5
6
  //Response when JWT is not valid.
6
7
  const redirectResponse = {
7
8
  statusCode: 302,
@@ -74,8 +75,9 @@ function _sign(input, key, method) {
74
75
  function _base64urlDecode(str) {
75
76
  return Buffer.from(str, "base64url").toString();
76
77
  }
77
- export const handler = ApiHandler(async (event) => {
78
- console.log("Auth check event:", event);
78
+ async function handler(event, context) {
79
+ console.log("🟢 Auth check event:", event);
80
+ console.log("🔵 Auth check context:", context);
79
81
  const request = event.request;
80
82
  const secret_key = await getSecret();
81
83
  if (!secret_key) {
@@ -85,7 +87,7 @@ export const handler = ApiHandler(async (event) => {
85
87
  // console.log(request.cookies);
86
88
  // console.log(request.cookies["auth-token"]);
87
89
  // console.log(Object.keys(request.cookies));
88
- const jwtToken = useCookie("auth-token");
90
+ const jwtToken = request.cookies["auth-token"] && request.cookies["auth-token"].value;
89
91
  console.log("jwtToken:", jwtToken);
90
92
  // console.log(Object.keys(request.cookies));
91
93
  // If no JWT token, then generate HTTP redirect 401 response.
@@ -104,7 +106,7 @@ export const handler = ApiHandler(async (event) => {
104
106
  // delete request.querystring.jwt;
105
107
  log("Valid JWT token");
106
108
  return request;
107
- });
109
+ }
108
110
  // Get secret from key value store
109
111
  async function getSecret() {
110
112
  try {
@@ -116,8 +118,13 @@ async function getSecret() {
116
118
  return null;
117
119
  }
118
120
  }
119
- const log = (...args) => {
121
+ const log = function () {
120
122
  if (loggingEnabled) {
121
- console.log(...args);
123
+ // @ts-expect-error We can't use spread or rest parameters in CloudFront Functions
124
+ // eslint-disable-next-line prefer-spread, prefer-rest-params
125
+ console.log.apply(console, arguments);
122
126
  }
123
127
  };
128
+ // This serves no purpose other than to make TypeScript and eslint happy by showing that that handler is used. We can't
129
+ // export handler as an alterative because CloudFront Functions don't support exports.
130
+ handler;
@@ -1 +1 @@
1
- {"version":3,"file":"auth-route.d.ts","sourceRoot":"","sources":["../../../src/cdk-constructs/CloudWatchOidcAuth/auth-route.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,OAAO,4CAiDnB,CAAC"}
1
+ {"version":3,"file":"auth-route.d.ts","sourceRoot":"","sources":["../../../src/cdk-constructs/CloudWatchOidcAuth/auth-route.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,OAAO,4CAyCnB,CAAC"}
@@ -18,7 +18,7 @@ if (!jwtSecret) {
18
18
  throw new Error("JWT_SECRET not set");
19
19
  }
20
20
  const oidcIssuerConfigUrl = new URL(`${process.env.OIDC_ISSUER_URL?.replace(/\/$/, "")}/.well-known/openid-configuration`);
21
- export const handler = convertApiGatewayHandlerToCloudFrontHandler(AuthHandler({
21
+ export const handler = addRequiredContext(AuthHandler({
22
22
  providers: {
23
23
  oidc: OidcAdapter({
24
24
  issuer: await Issuer.discover(oidcIssuerConfigUrl.href),
@@ -26,7 +26,7 @@ export const handler = convertApiGatewayHandlerToCloudFrontHandler(AuthHandler({
26
26
  scope: oidcScope,
27
27
  onSuccess: async (tokenset) => {
28
28
  console.log("tokenset", tokenset, tokenset.claims());
29
- console.log("Config.jwtSecret:", jwtSecret);
29
+ // console.log("Config.jwtSecret:", jwtSecret);
30
30
  // Payload to include in the token
31
31
  const payload = {
32
32
  userID: tokenset.claims().sub,
@@ -38,9 +38,7 @@ export const handler = convertApiGatewayHandlerToCloudFrontHandler(AuthHandler({
38
38
  };
39
39
  // Create the token
40
40
  const token = jwt.sign(payload, jwtSecret, options);
41
- const expires = new Date(
42
- // @ ts-ignore error in GH action
43
- Date.now() + 1000 * 60 * 60 * 24 * 7);
41
+ const expires = new Date(Date.now() + 1000 * 60 * 60 * 24 * 7);
44
42
  return {
45
43
  statusCode: 302,
46
44
  headers: {
@@ -50,35 +48,17 @@ export const handler = convertApiGatewayHandlerToCloudFrontHandler(AuthHandler({
50
48
  `auth-token=${token}; HttpOnly; SameSite=None; Secure; Path=/; Expires=${expires}`,
51
49
  ],
52
50
  };
53
- // return Session.cookie({
54
- // redirect: "https://openidconnect.net/callback",
55
- // type: "public",
56
- // properties: {
57
- // userID: tokenset.claims().sub,
58
- // },
59
- // });
60
51
  },
61
52
  }),
62
53
  },
63
54
  }));
64
- // @ts-expect-error - testing
65
- function convertApiGatewayHandlerToCloudFrontHandler(callback) {
66
- // @ts-expect-error - testing
67
- return async function (event, context) {
55
+ function addRequiredContext(handler) {
56
+ return async function (...args) {
57
+ const [event, context] = args;
68
58
  // Used by AuthHandler to create callback url sent to oidc server
69
59
  event.requestContext.domainName = event.headers["x-forwarded-host"];
70
- console.log("----", event, context);
71
- // console.log("event", event)
72
- // console.log("context", context)
73
- const response = await callback(event, context);
74
- // if (response.cookies) {
75
- // if (!response.headers) {
76
- // response.headers = {}
77
- // }
78
- // response.headers["set-cookie"] = response.cookies
79
- // }
80
- // response.headers.location += "&cake=blar"
81
- // response.headers.foo = "bar"
82
- return response;
60
+ console.log("🟢 event", event);
61
+ console.log("🔵 context", context);
62
+ return await handler(...args);
83
63
  };
84
64
  }
@@ -126,7 +126,7 @@ export class CloudWatchOidcAuth extends Construct {
126
126
  throw new Error("Could not find the underlying Lambda function of the AwsCustomResource");
127
127
  }
128
128
  fn.addEnvironment("NODE_OPTIONS", "--require=@aws-sdk/signature-v4-crt");
129
- const edgeFuncAuthCheck = new CloudFront.Function(scope, `${this.id}EdgeFunctionAuthCheck`, {
129
+ const edgeFuncAuthCheck = new CloudFront.Function(scope, `${this.id}AuthCheckFunction`, {
130
130
  code: CloudFront.FunctionCode.fromInline(fs.readFileSync(path.join(import.meta.dirname, "auth-check.js"), "utf8").replace("__placeholder-for-jwt-secret-key__", key)),
131
131
  runtime: CloudFront.FunctionRuntime.JS_2_0,
132
132
  keyValueStore: cfKeyValueStore,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infoxchange/make-it-so",
3
- "version": "2.10.0-internal-testing-vdt-199-add-oidc-auth.4",
3
+ "version": "2.10.0-internal-testing-vdt-199-add-oidc-auth.6",
4
4
  "description": "Makes deploying services to IX infra easy",
5
5
  "repository": "github:infoxchange/make-it-so",
6
6
  "type": "module",
@@ -1,8 +1,10 @@
1
1
  // Based off: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example_cloudfront_functions_kvs_jwt_verify_section.html
2
+ // Note that as a CloudFront Function, this code has limitations compared to a Lambda@Edge function.
3
+ // For example, no external libraries can be used, and the runtime is more limited.
4
+
2
5
 
3
6
  import crypto from "crypto";
4
7
  import cf from "cloudfront";
5
- import { ApiHandler, useCookie } from "sst/node/api";
6
8
 
7
9
  //Response when JWT is not valid.
8
10
  const redirectResponse = {
@@ -93,8 +95,9 @@ function _base64urlDecode(str: string) {
93
95
  return Buffer.from(str, "base64url").toString();
94
96
  }
95
97
 
96
- export const handler = ApiHandler(async (event) => {
97
- console.log("Auth check event:", event);
98
+ async function handler(event: AWSCloudFrontFunction.Event, context: AWSCloudFrontFunction.Context) {
99
+ console.log("🟢 Auth check event:", event);
100
+ console.log("🔵 Auth check context:", context);
98
101
  const request = event.request;
99
102
  const secret_key = await getSecret();
100
103
 
@@ -106,7 +109,7 @@ export const handler = ApiHandler(async (event) => {
106
109
  // console.log(request.cookies);
107
110
  // console.log(request.cookies["auth-token"]);
108
111
  // console.log(Object.keys(request.cookies));
109
- const jwtToken = useCookie("auth-token");
112
+ const jwtToken = request.cookies["auth-token"] && request.cookies["auth-token"].value;
110
113
  console.log("jwtToken:", jwtToken);
111
114
  // console.log(Object.keys(request.cookies));
112
115
 
@@ -126,7 +129,7 @@ export const handler = ApiHandler(async (event) => {
126
129
  // delete request.querystring.jwt;
127
130
  log("Valid JWT token");
128
131
  return request;
129
- })
132
+ }
130
133
 
131
134
  // Get secret from key value store
132
135
  async function getSecret() {
@@ -139,8 +142,14 @@ async function getSecret() {
139
142
  }
140
143
  }
141
144
 
142
- const log: typeof console.log = (...args) => {
145
+ const log: typeof console.log = function () {
143
146
  if (loggingEnabled) {
144
- console.log(...args);
147
+ // @ts-expect-error We can't use spread or rest parameters in CloudFront Functions
148
+ // eslint-disable-next-line prefer-spread, prefer-rest-params
149
+ console.log.apply(console, arguments);
145
150
  }
146
151
  }
152
+
153
+ // This serves no purpose other than to make TypeScript and eslint happy by showing that that handler is used. We can't
154
+ // export handler as an alterative because CloudFront Functions don't support exports.
155
+ handler;
@@ -23,7 +23,7 @@ const oidcIssuerConfigUrl = new URL(
23
23
  `${process.env.OIDC_ISSUER_URL?.replace(/\/$/, "")}/.well-known/openid-configuration`,
24
24
  );
25
25
 
26
- export const handler = convertApiGatewayHandlerToCloudFrontHandler(
26
+ export const handler = addRequiredContext(
27
27
  AuthHandler({
28
28
  providers: {
29
29
  oidc: OidcAdapter({
@@ -33,7 +33,7 @@ export const handler = convertApiGatewayHandlerToCloudFrontHandler(
33
33
  onSuccess: async (tokenset) => {
34
34
  console.log("tokenset", tokenset, tokenset.claims());
35
35
 
36
- console.log("Config.jwtSecret:", jwtSecret);
36
+ // console.log("Config.jwtSecret:", jwtSecret);
37
37
 
38
38
  // Payload to include in the token
39
39
  const payload = {
@@ -49,7 +49,6 @@ export const handler = convertApiGatewayHandlerToCloudFrontHandler(
49
49
  // Create the token
50
50
  const token = jwt.sign(payload, jwtSecret, options);
51
51
  const expires = new Date(
52
- // @ ts-ignore error in GH action
53
52
  Date.now() + 1000 * 60 * 60 * 24 * 7,
54
53
  );
55
54
  return {
@@ -61,37 +60,20 @@ export const handler = convertApiGatewayHandlerToCloudFrontHandler(
61
60
  `auth-token=${token}; HttpOnly; SameSite=None; Secure; Path=/; Expires=${expires}`,
62
61
  ],
63
62
  };
64
- // return Session.cookie({
65
- // redirect: "https://openidconnect.net/callback",
66
- // type: "public",
67
- // properties: {
68
- // userID: tokenset.claims().sub,
69
- // },
70
- // });
71
63
  },
72
64
  }),
73
65
  },
74
66
  }),
75
67
  );
76
68
 
77
- // @ts-expect-error - testing
78
- function convertApiGatewayHandlerToCloudFrontHandler(callback) {
79
- // @ts-expect-error - testing
80
- return async function (event, context) {
69
+ function addRequiredContext(handler: ReturnType<typeof AuthHandler>): ReturnType<typeof AuthHandler> {
70
+ return async function (...args) {
71
+ const [event, context] = args;
81
72
  // Used by AuthHandler to create callback url sent to oidc server
82
73
  event.requestContext.domainName = event.headers["x-forwarded-host"];
83
- console.log("----", event, context);
84
- // console.log("event", event)
85
- // console.log("context", context)
86
- const response = await callback(event, context);
87
- // if (response.cookies) {
88
- // if (!response.headers) {
89
- // response.headers = {}
90
- // }
91
- // response.headers["set-cookie"] = response.cookies
92
- // }
93
- // response.headers.location += "&cake=blar"
94
- // response.headers.foo = "bar"
95
- return response;
74
+ console.log("🟢 event", event)
75
+ console.log("🔵 context", context)
76
+
77
+ return await handler(...args);
96
78
  };
97
79
  }
@@ -195,7 +195,7 @@ export class CloudWatchOidcAuth extends Construct {
195
195
 
196
196
  const edgeFuncAuthCheck = new CloudFront.Function(
197
197
  scope,
198
- `${this.id}EdgeFunctionAuthCheck`,
198
+ `${this.id}AuthCheckFunction`,
199
199
  {
200
200
  code: CloudFront.FunctionCode.fromInline(
201
201
  fs.readFileSync(path.join(import.meta.dirname, "auth-check.js"), "utf8").replace("__placeholder-for-jwt-secret-key__", key),