@infoxchange/make-it-so 2.11.0-internal-testing-vdt-199-add-auth-token-verify-function.4 → 2.11.0-internal-testing-vdt-199-add-auth-token-verify-function-2.2
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/README.md +15 -29
- package/dist/cdk-constructs/IxNextjsSite.d.ts.map +1 -1
- package/dist/cdk-constructs/IxNextjsSite.js +2 -1
- package/dist/cdk-constructs/IxStaticSite.d.ts.map +1 -1
- package/dist/cdk-constructs/IxStaticSite.js +2 -1
- package/dist/cdk-constructs/SiteOidcAuth/auth-check-handler-body.d.ts +2 -0
- package/dist/cdk-constructs/SiteOidcAuth/auth-check-handler-body.d.ts.map +1 -0
- package/dist/cdk-constructs/{CloudFrontOidcAuth/auth-check.js → SiteOidcAuth/auth-check-handler-body.js} +39 -57
- package/dist/cdk-constructs/SiteOidcAuth/auth-route.d.ts.map +1 -0
- package/dist/cdk-constructs/SiteOidcAuth/index.d.ts +197 -0
- package/dist/cdk-constructs/SiteOidcAuth/index.d.ts.map +1 -0
- package/dist/cdk-constructs/SiteOidcAuth/index.js +184 -0
- package/dist/cdk-constructs/index.d.ts +1 -1
- package/dist/cdk-constructs/index.d.ts.map +1 -1
- package/dist/cdk-constructs/index.js +1 -1
- package/dist/lib/site/support.d.ts +15 -5
- package/dist/lib/site/support.d.ts.map +1 -1
- package/dist/lib/site/support.js +19 -0
- package/package.json +1 -1
- package/src/cdk-constructs/IxNextjsSite.ts +2 -0
- package/src/cdk-constructs/IxStaticSite.ts +2 -0
- package/src/cdk-constructs/{CloudFrontOidcAuth/auth-check.ts → SiteOidcAuth/auth-check-handler-body.ts} +44 -63
- package/src/cdk-constructs/SiteOidcAuth/index.ts +288 -0
- package/src/cdk-constructs/index.ts +1 -1
- package/src/lib/site/support.ts +80 -29
- package/dist/cdk-constructs/CloudFrontOidcAuth/auth-check.d.ts +0 -2
- package/dist/cdk-constructs/CloudFrontOidcAuth/auth-check.d.ts.map +0 -1
- package/dist/cdk-constructs/CloudFrontOidcAuth/auth-route.d.ts.map +0 -1
- package/dist/cdk-constructs/CloudFrontOidcAuth/index.d.ts +0 -27
- package/dist/cdk-constructs/CloudFrontOidcAuth/index.d.ts.map +0 -1
- package/dist/cdk-constructs/CloudFrontOidcAuth/index.js +0 -198
- package/src/cdk-constructs/CloudFrontOidcAuth/cloudfront.d.ts +0 -245
- package/src/cdk-constructs/CloudFrontOidcAuth/index.ts +0 -294
- /package/dist/cdk-constructs/{CloudFrontOidcAuth → SiteOidcAuth}/auth-route.d.ts +0 -0
- /package/dist/cdk-constructs/{CloudFrontOidcAuth → SiteOidcAuth}/auth-route.js +0 -0
- /package/src/cdk-constructs/{CloudFrontOidcAuth → SiteOidcAuth}/auth-route.ts +0 -0
package/README.md
CHANGED
|
@@ -89,6 +89,12 @@ Unlike [NextjsSite](https://v2.sst.dev/constructs/NextjsSite), any environment v
|
|
|
89
89
|
| customDomain.isIxManagedDomain | boolean | (optional) If true will attempt to create DNS records and certs for it using the IX shared infra. Only required if explicitly setting customDomains and you want DNS records + certs setup for them |
|
|
90
90
|
| customDomain.additionalDomainAliases | string[] | (optional) Works like `customDomain.domainAlias` but `domainAlias` only allows one domain, additionalDomainAliases allows setting additional domains |
|
|
91
91
|
| environment | Record<string, string \| {buildtime?: string, runtime?: string}> | (optional) As well as accepting strings for environment variable values as is already done by [NextjsSite](https://v2.sst.dev/constructs/NextjsSite) it also accepts an object with the properties `buildtime` and/or `runtime` which allows you to customise the environment variable value during those different steps. |
|
|
92
|
+
| auth | object | (optional) If provided will put the site behind auth. |
|
|
93
|
+
| auth.oidc | object | |
|
|
94
|
+
| auth.oidc.issuerUrl | string | An issuer URL for the OIDC server to use. |
|
|
95
|
+
| auth.oidc.clientId | string | The OIDC client ID to use. |
|
|
96
|
+
| auth.oidc.scope | string | The scope used for the auth request. |
|
|
97
|
+
| auth.prefix | string | (optional) A custom path to be used for the auth route. |
|
|
92
98
|
|
|
93
99
|
```typescript
|
|
94
100
|
import { IxNextjsSite } from "@infoxchange/make-it-so/cdk-constructs";
|
|
@@ -123,9 +129,15 @@ Also if `isIxManagedDomain` is true DNS records will be automatically created fo
|
|
|
123
129
|
|
|
124
130
|
| Prop | Type | Description |
|
|
125
131
|
| ------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
126
|
-
| [...
|
|
132
|
+
| [...StaticSiteProps] | | Any props accepted by [SST's StaticSite](https://v2.sst.dev/constructs/StaticSite) |
|
|
127
133
|
| customDomain.isIxManagedDomain | boolean | (optional) If true will attempt to create DNS records and certs for it using the IX shared infra. Only required if explicitly setting customDomains and you want DNS records + certs setup for them |
|
|
128
134
|
| customDomain.additionalDomainAliases | string[] | (optional) Works like `customDomain.domainAlias` but `domainAlias` only allows one domain, additionalDomainAliases allows setting additional domains |
|
|
135
|
+
| auth | object | (optional) If provided will put the site behind auth. |
|
|
136
|
+
| auth.oidc | object | |
|
|
137
|
+
| auth.oidc.issuerUrl | string | An issuer URL for the OIDC server to use. |
|
|
138
|
+
| auth.oidc.clientId | string | The OIDC client ID to use. |
|
|
139
|
+
| auth.oidc.scope | string | The scope used for the auth request. |
|
|
140
|
+
| auth.prefix | string | (optional) A custom path to be used for the auth route. |
|
|
129
141
|
|
|
130
142
|
```typescript
|
|
131
143
|
import { IxStaticSite } from "@infoxchange/make-it-so/cdk-constructs";
|
|
@@ -290,31 +302,7 @@ const vpcDetails = new IxVpcDetails(scope, "VpcDetails");
|
|
|
290
302
|
|
|
291
303
|
</details>
|
|
292
304
|
|
|
293
|
-
|
|
294
|
-
<summary><strong>CloudFrontOidcAuth</strong> - Adds OIDC authentication to a CloudFront distribution.</summary>
|
|
295
|
-
|
|
296
|
-
```typescript
|
|
297
|
-
import { CloudFrontOidcAuth } from "@infoxchange/make-it-so/cdk-constructs";
|
|
298
|
-
|
|
299
|
-
// You first create an instance of CloudFrontOidcAuth
|
|
300
|
-
const auth = new CloudFrontOidcAuth(stack, "CloudFrontOidcAuth", {
|
|
301
|
-
oidcIssuerUrl: "https://your-oidc-server.com/path/",
|
|
302
|
-
oidcClientId: "your-client-id",
|
|
303
|
-
oidcScope: "email",
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
// Then you apply it to the a CloudFront backed site when it's created
|
|
307
|
-
const site = new IxStaticSite(stack, "IxStaticSite", {
|
|
308
|
-
path: "path/to/site/files",
|
|
309
|
-
cdk: {
|
|
310
|
-
distribution: auth.addToDistributionDefinition(stack, {
|
|
311
|
-
distributionDefinition: {},
|
|
312
|
-
}),
|
|
313
|
-
},
|
|
314
|
-
});
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
## Full Example
|
|
305
|
+
## Example App Using Make It So
|
|
318
306
|
|
|
319
307
|
To deploy a Next.js based site you would include a `sst.config.ts` file at the root of repo with contents like this:
|
|
320
308
|
|
|
@@ -348,9 +336,7 @@ export default {
|
|
|
348
336
|
} satisfies SSTConfig;
|
|
349
337
|
```
|
|
350
338
|
|
|
351
|
-
Then simply configure the IX pipeline to deploy that repo as a serverless app.
|
|
352
|
-
|
|
353
|
-
important that sst and aws lib version match those used in ix-deploy-support
|
|
339
|
+
Then simply configure the IX pipeline to deploy that repo as a serverless app. Note it is important that any AWS CDK libraries included in package.json match version match the version used by SST.
|
|
354
340
|
|
|
355
341
|
# The Name
|
|
356
342
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IxNextjsSite.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/IxNextjsSite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EACL,KAAK,uBAAuB,
|
|
1
|
+
{"version":3,"file":"IxNextjsSite.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/IxNextjsSite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EACL,KAAK,uBAAuB,EAgB7B,MAAM,wBAAwB,CAAC;AAEhC,KAAK,cAAc,GAAG,qBAAqB,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAClE,KAAK,WAAW,GAAG,qBAAqB,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,KAAK,cAAc,GAAG,uBAAuB,CAAC;AAE9C,qBAAa,YAAa,SAAQ,UAAU;gBAExC,KAAK,EAAE,cAAc,EACrB,EAAE,EAAE,WAAW,EACf,KAAK,GAAE,cAAmB;IAmB5B,IAAW,aAAa,IAAI,MAAM,EAAE,CAEnC;IAED,IAAW,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAE9C;IAED,IAAW,WAAW,IAAI,MAAM,GAAG,IAAI,CAEtC;IAED,IAAW,kBAAkB,IAAI,MAAM,EAAE,CAExC;IAED,IAAW,aAAa,IAAI,MAAM,GAAG,IAAI,CAExC;IAED,IAAW,aAAa,IAAI,MAAM,GAAG,IAAI,CAExC;CACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextjsSite } from "sst/constructs";
|
|
2
2
|
import ixDeployConfig from "../deployConfig.js";
|
|
3
|
-
import { getAliasDomain, getAlternativeDomains, getCustomDomains, getPrimaryCustomDomain, getPrimaryDomain, getPrimaryOrigin, setupCertificate, setupCustomDomain, setupDnsRecords, setupDomainAliasRedirect, setupVpcDetails, setupDefaultEnvVars, applyConditionalEnvironmentVariables, parentCompatibleSsrProps, } from "../lib/site/support.js";
|
|
3
|
+
import { getAliasDomain, getAlternativeDomains, getCustomDomains, getPrimaryCustomDomain, getPrimaryDomain, getPrimaryOrigin, setupCertificate, setupCustomDomain, setupDnsRecords, setupDomainAliasRedirect, setupVpcDetails, setupDefaultEnvVars, applyConditionalEnvironmentVariables, parentCompatibleSsrProps, processAuthProps, } from "../lib/site/support.js";
|
|
4
4
|
export class IxNextjsSite extends NextjsSite {
|
|
5
5
|
constructor(scope, id, props = {}) {
|
|
6
6
|
if (ixDeployConfig.isIxDeploy) {
|
|
@@ -9,6 +9,7 @@ export class IxNextjsSite extends NextjsSite {
|
|
|
9
9
|
props = setupCertificate(scope, id, props);
|
|
10
10
|
props = setupDomainAliasRedirect(scope, id, props);
|
|
11
11
|
}
|
|
12
|
+
props = processAuthProps(scope, id, "SsrSite", props);
|
|
12
13
|
props = setupDefaultEnvVars(scope, id, props);
|
|
13
14
|
props = applyConditionalEnvironmentVariables(scope, id, props);
|
|
14
15
|
super(scope, id, parentCompatibleSsrProps(props));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IxStaticSite.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/IxStaticSite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EACL,uBAAuB,
|
|
1
|
+
{"version":3,"file":"IxStaticSite.d.ts","sourceRoot":"","sources":["../../src/cdk-constructs/IxStaticSite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EACL,uBAAuB,EAYxB,MAAM,wBAAwB,CAAC;AAEhC,KAAK,cAAc,GAAG,qBAAqB,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAClE,KAAK,WAAW,GAAG,qBAAqB,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,KAAK,cAAc,GAAG,uBAAuB,CAAC;AAE9C,qBAAa,YAAa,SAAQ,UAAU;IAE1C,OAAO,CAAC,aAAa,CAAiB;gBAGpC,KAAK,EAAE,cAAc,EACrB,EAAE,EAAE,WAAW,EACf,KAAK,GAAE,cAAmB;IAiB5B,IAAW,aAAa,IAAI,MAAM,EAAE,CAEnC;IAED,IAAW,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAE9C;IAED,IAAW,WAAW,IAAI,MAAM,GAAG,IAAI,CAEtC;IAED,IAAW,kBAAkB,IAAI,MAAM,EAAE,CAExC;IAED,IAAW,aAAa,IAAI,MAAM,GAAG,IAAI,CAExC;IAED,IAAW,aAAa,IAAI,MAAM,GAAG,IAAI,CAExC;CACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StaticSite } from "sst/constructs";
|
|
2
2
|
import ixDeployConfig from "../deployConfig.js";
|
|
3
|
-
import { getAliasDomain, getAlternativeDomains, getCustomDomains, getPrimaryCustomDomain, getPrimaryDomain, getPrimaryOrigin, setupCertificate, setupCustomDomain, setupDnsRecords, setupDomainAliasRedirect, } from "../lib/site/support.js";
|
|
3
|
+
import { getAliasDomain, getAlternativeDomains, getCustomDomains, getPrimaryCustomDomain, getPrimaryDomain, getPrimaryOrigin, processAuthProps, setupCertificate, setupCustomDomain, setupDnsRecords, setupDomainAliasRedirect, } from "../lib/site/support.js";
|
|
4
4
|
export class IxStaticSite extends StaticSite {
|
|
5
5
|
// StaticSite's props are private, so we need to store them separately
|
|
6
6
|
propsExtended;
|
|
@@ -10,6 +10,7 @@ export class IxStaticSite extends StaticSite {
|
|
|
10
10
|
props = setupCertificate(scope, id, props);
|
|
11
11
|
props = setupDomainAliasRedirect(scope, id, props);
|
|
12
12
|
}
|
|
13
|
+
props = processAuthProps(scope, id, "StaticSite", props);
|
|
13
14
|
super(scope, id, props);
|
|
14
15
|
this.propsExtended = props;
|
|
15
16
|
if (ixDeployConfig.isIxDeploy) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-check-handler-body.d.ts","sourceRoot":"","sources":["../../../src/cdk-constructs/SiteOidcAuth/auth-check-handler-body.ts"],"names":[],"mappings":""}
|
|
@@ -1,10 +1,30 @@
|
|
|
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
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
// Note that as a CloudFront Function, this code has limitations compared to a Lambda@Edge function. For example, no
|
|
3
|
+
// external libraries can be used, and the runtime is more limited. Because SST v2's SsrSite construct uses JS v1.0
|
|
4
|
+
// runtime for CloudFront Functions, this code must also be compatible with that runtime. Also this is used in the body
|
|
5
|
+
// of a function where the variables event and request are already defined.
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires -- v1 runtime for CloudFront Functions do not support import statements
|
|
7
|
+
const crypto = require("crypto");
|
|
8
|
+
const jwtSecret = "__placeholder-for-jwt-secret__";
|
|
7
9
|
const authRoutePrefix = "__placeholder-for-auth-route-prefix__";
|
|
10
|
+
// Set to true to enable console logging
|
|
11
|
+
const loggingEnabled = false;
|
|
12
|
+
const log = function () {
|
|
13
|
+
if (!loggingEnabled)
|
|
14
|
+
return;
|
|
15
|
+
// CloudFront Function runtime only prints first argument passed to console.log so add other args to the first one if given.
|
|
16
|
+
// eslint-disable-next-line prefer-rest-params -- We can't use spread or rest parameters in CloudFront Functions
|
|
17
|
+
let message = arguments[0];
|
|
18
|
+
if (arguments.length > 1) {
|
|
19
|
+
const otherArgs = [];
|
|
20
|
+
for (let i = 1; i < arguments.length; i++) {
|
|
21
|
+
// eslint-disable-next-line prefer-rest-params
|
|
22
|
+
otherArgs[i - 1] = arguments[i];
|
|
23
|
+
}
|
|
24
|
+
message += " - additional args: " + JSON.stringify(otherArgs);
|
|
25
|
+
}
|
|
26
|
+
console.log(message);
|
|
27
|
+
};
|
|
8
28
|
//Response when JWT is not valid.
|
|
9
29
|
const redirectResponse = {
|
|
10
30
|
statusCode: 302,
|
|
@@ -12,8 +32,6 @@ const redirectResponse = {
|
|
|
12
32
|
location: { value: `${authRoutePrefix}/oidc/authorize` },
|
|
13
33
|
},
|
|
14
34
|
};
|
|
15
|
-
// Set to true to enable console logging
|
|
16
|
-
const loggingEnabled = false;
|
|
17
35
|
function jwtDecode(token, key, noVerify) {
|
|
18
36
|
// check segments
|
|
19
37
|
const segments = token.split(".");
|
|
@@ -71,55 +89,19 @@ function _sign(input, key, method) {
|
|
|
71
89
|
function _base64urlDecode(str) {
|
|
72
90
|
return Buffer.from(str, "base64url").toString();
|
|
73
91
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
throw new Error("Error retrieving JWT secret key");
|
|
80
|
-
}
|
|
81
|
-
const jwtToken = request.cookies["auth-token"] && request.cookies["auth-token"].value;
|
|
82
|
-
if (!jwtToken) {
|
|
83
|
-
log("Error: No JWT in the cookies");
|
|
84
|
-
return redirectResponse;
|
|
85
|
-
}
|
|
86
|
-
try {
|
|
87
|
-
jwtDecode(jwtToken, secret_key);
|
|
88
|
-
}
|
|
89
|
-
catch (e) {
|
|
90
|
-
log(e);
|
|
91
|
-
return redirectResponse;
|
|
92
|
-
}
|
|
93
|
-
log("Valid JWT token");
|
|
94
|
-
return request;
|
|
92
|
+
const jwtToken = request.cookies["auth-token"] && request.cookies["auth-token"].value;
|
|
93
|
+
if (!jwtToken) {
|
|
94
|
+
log("Error: No JWT in the cookies");
|
|
95
|
+
// @ts-expect-error -- This code is added to a function body so we can use return here but typescript doesn't know that.
|
|
96
|
+
return redirectResponse;
|
|
95
97
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
try {
|
|
99
|
-
const kvsHandle = cf.kvs();
|
|
100
|
-
return await kvsHandle.get(kvsKey);
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
log(`Error reading value for key: ${kvsKey}, error: ${err}`);
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
98
|
+
try {
|
|
99
|
+
jwtDecode(jwtToken, jwtSecret);
|
|
106
100
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const otherArgs = [];
|
|
115
|
-
for (let i = 1; i < arguments.length; i++) {
|
|
116
|
-
// eslint-disable-next-line prefer-rest-params
|
|
117
|
-
otherArgs[i - 1] = arguments[i];
|
|
118
|
-
}
|
|
119
|
-
message += " - additional args: " + JSON.stringify(otherArgs);
|
|
120
|
-
}
|
|
121
|
-
console.log(message);
|
|
122
|
-
};
|
|
123
|
-
// This serves no purpose other than to make TypeScript and eslint happy by showing that that handler is used. We can't
|
|
124
|
-
// export handler as an alterative because CloudFront Functions don't support exports.
|
|
125
|
-
handler;
|
|
101
|
+
catch (e) {
|
|
102
|
+
log(e);
|
|
103
|
+
// @ts-expect-error -- This code is added to a function body so we can use return here but typescript doesn't know that.
|
|
104
|
+
return redirectResponse;
|
|
105
|
+
}
|
|
106
|
+
log("Valid JWT token");
|
|
107
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-route.d.ts","sourceRoot":"","sources":["../../../src/cdk-constructs/SiteOidcAuth/auth-route.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,OAAO,4CAiCnB,CAAC"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { Construct } from "constructs";
|
|
2
|
+
import CloudFront from "aws-cdk-lib/aws-cloudfront";
|
|
3
|
+
import CDK from "aws-cdk-lib";
|
|
4
|
+
import * as SST from "sst/constructs";
|
|
5
|
+
import type { ExtendedNextjsSiteProps, ExtendedStaticSiteProps } from "../../lib/site/support.js";
|
|
6
|
+
type ConstructScope = ConstructorParameters<typeof Construct>[0];
|
|
7
|
+
type ConstructId = ConstructorParameters<typeof Construct>[1];
|
|
8
|
+
export type Props = {
|
|
9
|
+
oidcIssuerUrl: string;
|
|
10
|
+
oidcClientId: string;
|
|
11
|
+
oidcScope: string;
|
|
12
|
+
};
|
|
13
|
+
export type AddToSiteProps = {
|
|
14
|
+
prefix?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare class SiteOidcAuth extends Construct {
|
|
17
|
+
readonly oidcIssuerUrl: string;
|
|
18
|
+
readonly oidcClientId: string;
|
|
19
|
+
readonly oidcScope: string;
|
|
20
|
+
readonly id: string;
|
|
21
|
+
constructor(scope: ConstructScope, id: ConstructId, props: Props);
|
|
22
|
+
addToStaticSiteProps<SiteProps extends ExtendedStaticSiteProps>(scope: ConstructScope, siteProps: SiteProps, { prefix }?: AddToSiteProps): SiteProps & {
|
|
23
|
+
cdk: {
|
|
24
|
+
distribution: {
|
|
25
|
+
additionalBehaviors: Record<string, CloudFront.BehaviorOptions>;
|
|
26
|
+
defaultBehavior: {
|
|
27
|
+
functionAssociations: CloudFront.FunctionAssociation[];
|
|
28
|
+
allowedMethods?: CloudFront.AllowedMethods | undefined;
|
|
29
|
+
cachedMethods?: CloudFront.CachedMethods | undefined;
|
|
30
|
+
cachePolicy?: CloudFront.ICachePolicy | undefined;
|
|
31
|
+
compress?: boolean | undefined;
|
|
32
|
+
originRequestPolicy?: CloudFront.IOriginRequestPolicy | undefined;
|
|
33
|
+
realtimeLogConfig?: CloudFront.IRealtimeLogConfig | undefined;
|
|
34
|
+
responseHeadersPolicy?: CloudFront.IResponseHeadersPolicy | undefined;
|
|
35
|
+
smoothStreaming?: boolean | undefined;
|
|
36
|
+
viewerProtocolPolicy?: CloudFront.ViewerProtocolPolicy | undefined;
|
|
37
|
+
edgeLambdas?: CloudFront.EdgeLambda[] | undefined;
|
|
38
|
+
trustedKeyGroups?: CloudFront.IKeyGroup[] | undefined;
|
|
39
|
+
origin?: CloudFront.IOrigin | undefined;
|
|
40
|
+
};
|
|
41
|
+
} | {
|
|
42
|
+
additionalBehaviors: Record<string, CloudFront.BehaviorOptions>;
|
|
43
|
+
defaultBehavior: {
|
|
44
|
+
functionAssociations: CloudFront.FunctionAssociation[];
|
|
45
|
+
allowedMethods?: CloudFront.AllowedMethods | undefined;
|
|
46
|
+
cachedMethods?: CloudFront.CachedMethods | undefined;
|
|
47
|
+
cachePolicy?: CloudFront.ICachePolicy | undefined;
|
|
48
|
+
compress?: boolean | undefined;
|
|
49
|
+
originRequestPolicy?: CloudFront.IOriginRequestPolicy | undefined;
|
|
50
|
+
realtimeLogConfig?: CloudFront.IRealtimeLogConfig | undefined;
|
|
51
|
+
responseHeadersPolicy?: CloudFront.IResponseHeadersPolicy | undefined;
|
|
52
|
+
smoothStreaming?: boolean | undefined;
|
|
53
|
+
viewerProtocolPolicy?: CloudFront.ViewerProtocolPolicy | undefined;
|
|
54
|
+
edgeLambdas?: CloudFront.EdgeLambda[] | undefined;
|
|
55
|
+
trustedKeyGroups?: CloudFront.IKeyGroup[] | undefined;
|
|
56
|
+
origin?: CloudFront.IOrigin | undefined;
|
|
57
|
+
};
|
|
58
|
+
distributionDomainName: string;
|
|
59
|
+
distributionId: string;
|
|
60
|
+
grant(identity: CDK.aws_iam.IGrantable, ...actions: string[]): CDK.aws_iam.Grant;
|
|
61
|
+
grantCreateInvalidation(identity: CDK.aws_iam.IGrantable): CDK.aws_iam.Grant;
|
|
62
|
+
stack: CDK.Stack;
|
|
63
|
+
env: CDK.ResourceEnvironment;
|
|
64
|
+
applyRemovalPolicy(policy: CDK.RemovalPolicy): void;
|
|
65
|
+
node: import("constructs").Node;
|
|
66
|
+
} | {
|
|
67
|
+
additionalBehaviors: Record<string, CloudFront.BehaviorOptions>;
|
|
68
|
+
defaultBehavior: {
|
|
69
|
+
functionAssociations: CloudFront.FunctionAssociation[];
|
|
70
|
+
allowedMethods?: CloudFront.AllowedMethods | undefined;
|
|
71
|
+
cachedMethods?: CloudFront.CachedMethods | undefined;
|
|
72
|
+
cachePolicy?: CloudFront.ICachePolicy | undefined;
|
|
73
|
+
compress?: boolean | undefined;
|
|
74
|
+
originRequestPolicy?: CloudFront.IOriginRequestPolicy | undefined;
|
|
75
|
+
realtimeLogConfig?: CloudFront.IRealtimeLogConfig | undefined;
|
|
76
|
+
responseHeadersPolicy?: CloudFront.IResponseHeadersPolicy | undefined;
|
|
77
|
+
smoothStreaming?: boolean | undefined;
|
|
78
|
+
viewerProtocolPolicy?: CloudFront.ViewerProtocolPolicy | undefined;
|
|
79
|
+
edgeLambdas?: CloudFront.EdgeLambda[] | undefined;
|
|
80
|
+
trustedKeyGroups?: CloudFront.IKeyGroup[] | undefined;
|
|
81
|
+
origin?: CloudFront.IOrigin | undefined;
|
|
82
|
+
};
|
|
83
|
+
certificate?: CDK.aws_certificatemanager.ICertificate | undefined;
|
|
84
|
+
comment?: string | undefined;
|
|
85
|
+
defaultRootObject?: string | undefined;
|
|
86
|
+
domainNames?: string[] | undefined;
|
|
87
|
+
enabled?: boolean | undefined;
|
|
88
|
+
enableIpv6?: boolean | undefined;
|
|
89
|
+
enableLogging?: boolean | undefined;
|
|
90
|
+
geoRestriction?: CloudFront.GeoRestriction | undefined;
|
|
91
|
+
httpVersion?: CloudFront.HttpVersion | undefined;
|
|
92
|
+
logBucket?: CDK.aws_s3.IBucket | undefined;
|
|
93
|
+
logIncludesCookies?: boolean | undefined;
|
|
94
|
+
logFilePrefix?: string | undefined;
|
|
95
|
+
priceClass?: CloudFront.PriceClass | undefined;
|
|
96
|
+
webAclId?: string | undefined;
|
|
97
|
+
errorResponses?: CloudFront.ErrorResponse[] | undefined;
|
|
98
|
+
minimumProtocolVersion?: CloudFront.SecurityPolicyProtocol | undefined;
|
|
99
|
+
sslSupportMethod?: CloudFront.SSLMethod | undefined;
|
|
100
|
+
publishAdditionalMetrics?: boolean | undefined;
|
|
101
|
+
};
|
|
102
|
+
id?: string | undefined;
|
|
103
|
+
bucket?: CDK.aws_s3.IBucket | CDK.aws_s3.BucketProps | undefined;
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
addToSsrSiteProps<SiteProps extends ExtendedNextjsSiteProps>(scope: ConstructScope, siteProps: SiteProps, { prefix }?: AddToSiteProps): SiteProps & {
|
|
107
|
+
cdk: {
|
|
108
|
+
distribution: {
|
|
109
|
+
additionalBehaviors: Record<string, CloudFront.BehaviorOptions>;
|
|
110
|
+
defaultBehavior?: (Omit<CloudFront.BehaviorOptions, "origin"> & {
|
|
111
|
+
origin?: CloudFront.IOrigin | undefined;
|
|
112
|
+
}) | undefined;
|
|
113
|
+
certificate?: CDK.aws_certificatemanager.ICertificate | undefined;
|
|
114
|
+
comment?: string | undefined;
|
|
115
|
+
defaultRootObject?: string | undefined;
|
|
116
|
+
domainNames?: string[] | undefined;
|
|
117
|
+
enabled?: boolean | undefined;
|
|
118
|
+
enableIpv6?: boolean | undefined;
|
|
119
|
+
enableLogging?: boolean | undefined;
|
|
120
|
+
geoRestriction?: CloudFront.GeoRestriction | undefined;
|
|
121
|
+
httpVersion?: CloudFront.HttpVersion | undefined;
|
|
122
|
+
logBucket?: CDK.aws_s3.IBucket | undefined;
|
|
123
|
+
logIncludesCookies?: boolean | undefined;
|
|
124
|
+
logFilePrefix?: string | undefined;
|
|
125
|
+
priceClass?: CloudFront.PriceClass | undefined;
|
|
126
|
+
webAclId?: string | undefined;
|
|
127
|
+
errorResponses?: CloudFront.ErrorResponse[] | undefined;
|
|
128
|
+
minimumProtocolVersion?: CloudFront.SecurityPolicyProtocol | undefined;
|
|
129
|
+
sslSupportMethod?: CloudFront.SSLMethod | undefined;
|
|
130
|
+
publishAdditionalMetrics?: boolean | undefined;
|
|
131
|
+
};
|
|
132
|
+
id?: string | undefined;
|
|
133
|
+
bucket?: CDK.aws_s3.IBucket | CDK.aws_s3.BucketProps | undefined;
|
|
134
|
+
s3Origin?: CDK.aws_cloudfront_origins.S3OriginProps | undefined;
|
|
135
|
+
serverCachePolicy?: CloudFront.ICachePolicy | undefined;
|
|
136
|
+
responseHeadersPolicy?: CloudFront.IResponseHeadersPolicy | undefined;
|
|
137
|
+
viewerProtocolPolicy?: CloudFront.ViewerProtocolPolicy | undefined;
|
|
138
|
+
server?: (Pick<CDK.aws_lambda.FunctionProps, "vpc" | "layers" | "vpcSubnets" | "securityGroups" | "allowAllOutbound" | "allowPublicSubnet" | "architecture" | "logRetention"> & Pick<SST.FunctionProps, "copyFiles">) | undefined;
|
|
139
|
+
transform?: ((args: {
|
|
140
|
+
cloudFrontFunctions?: Record<string, {
|
|
141
|
+
constructId: string;
|
|
142
|
+
injections: string[];
|
|
143
|
+
}> | undefined;
|
|
144
|
+
edgeFunctions?: Record<string, {
|
|
145
|
+
constructId: string;
|
|
146
|
+
function: import("sst/constructs/EdgeFunction.js").EdgeFunctionProps;
|
|
147
|
+
}> | undefined;
|
|
148
|
+
origins: Record<string, {
|
|
149
|
+
type: "function";
|
|
150
|
+
constructId: string;
|
|
151
|
+
function: import("sst/constructs/SsrFunction.js").SsrFunctionProps;
|
|
152
|
+
injections?: string[] | undefined;
|
|
153
|
+
streaming?: boolean | undefined;
|
|
154
|
+
} | {
|
|
155
|
+
type: "image-optimization-function";
|
|
156
|
+
function: CDK.aws_lambda.FunctionProps;
|
|
157
|
+
} | {
|
|
158
|
+
type: "s3";
|
|
159
|
+
originPath?: string | undefined;
|
|
160
|
+
copy: {
|
|
161
|
+
from: string;
|
|
162
|
+
to: string;
|
|
163
|
+
cached: boolean;
|
|
164
|
+
versionedSubDir?: string | undefined;
|
|
165
|
+
}[];
|
|
166
|
+
} | {
|
|
167
|
+
type: "group";
|
|
168
|
+
primaryOriginName: string;
|
|
169
|
+
fallbackOriginName: string;
|
|
170
|
+
fallbackStatusCodes?: number[] | undefined;
|
|
171
|
+
}>;
|
|
172
|
+
edge: boolean;
|
|
173
|
+
behaviors: {
|
|
174
|
+
cacheType: "server" | "static";
|
|
175
|
+
pattern?: string | undefined;
|
|
176
|
+
origin: string;
|
|
177
|
+
allowedMethods?: CloudFront.AllowedMethods | undefined;
|
|
178
|
+
cfFunction?: string | undefined;
|
|
179
|
+
edgeFunction?: string | undefined;
|
|
180
|
+
}[];
|
|
181
|
+
errorResponses?: CloudFront.ErrorResponse[] | undefined;
|
|
182
|
+
serverCachePolicy?: {
|
|
183
|
+
allowedHeaders?: string[] | undefined;
|
|
184
|
+
} | undefined;
|
|
185
|
+
buildId?: string | undefined;
|
|
186
|
+
}) => void) | undefined;
|
|
187
|
+
revalidation?: Pick<CDK.aws_lambda.FunctionProps, "vpc" | "vpcSubnets"> | undefined;
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
private createJwtSecret;
|
|
191
|
+
private getFunctionAssociation;
|
|
192
|
+
private getAuthCheckHandlerBodyCode;
|
|
193
|
+
private convertToCloudFrontFunctionCompatibleCode;
|
|
194
|
+
private getAuthBehaviorOptions;
|
|
195
|
+
}
|
|
196
|
+
export {};
|
|
197
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cdk-constructs/SiteOidcAuth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,UAAU,MAAM,4BAA4B,CAAC;AACpD,OAAO,GAAG,MAAM,aAAa,CAAC;AAE9B,OAAO,KAAK,GAAG,MAAM,gBAAgB,CAAC;AAOtC,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,KAAK,cAAc,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,KAAK,WAAW,GAAG,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9D,MAAM,MAAM,KAAK,GAAG;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAIjD,qBAAa,YAAa,SAAQ,SAAS;IACzC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;gBAER,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK;IAQhE,oBAAoB,CAAC,SAAS,SAAS,uBAAuB,EAC5D,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,SAAS,EACpB,EAAE,MAA+B,EAAE,GAAE,cAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4C1D,iBAAiB,CAAC,SAAS,SAAS,uBAAuB,EACzD,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,SAAS,EACpB,EAAE,MAA+B,EAAE,GAAE,cAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAqC1D,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,sBAAsB;IA6B9B,OAAO,CAAC,2BAA2B;IAgBnC,OAAO,CAAC,yCAAyC;IAejD,OAAO,CAAC,sBAAsB;CAiF/B"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { Construct } from "constructs";
|
|
2
|
+
import SecretsManager from "aws-cdk-lib/aws-secretsmanager";
|
|
3
|
+
import CloudFront from "aws-cdk-lib/aws-cloudfront";
|
|
4
|
+
import CDK from "aws-cdk-lib";
|
|
5
|
+
import Lambda from "aws-cdk-lib/aws-lambda";
|
|
6
|
+
import * as SST from "sst/constructs";
|
|
7
|
+
import { isCDKConstruct } from "sst/constructs/Construct.js";
|
|
8
|
+
import { Config as SSTInternalConfig } from "sst/config.js";
|
|
9
|
+
import CloudFrontOrigins from "aws-cdk-lib/aws-cloudfront-origins";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import fs from "node:fs";
|
|
12
|
+
import { transformSync } from "esbuild";
|
|
13
|
+
const defaultAuthRoutePrefix = "/auth";
|
|
14
|
+
export class SiteOidcAuth extends Construct {
|
|
15
|
+
oidcIssuerUrl;
|
|
16
|
+
oidcClientId;
|
|
17
|
+
oidcScope;
|
|
18
|
+
id;
|
|
19
|
+
constructor(scope, id, props) {
|
|
20
|
+
super(scope, id);
|
|
21
|
+
this.oidcIssuerUrl = props.oidcIssuerUrl;
|
|
22
|
+
this.oidcClientId = props.oidcClientId;
|
|
23
|
+
this.oidcScope = props.oidcScope;
|
|
24
|
+
this.id = id;
|
|
25
|
+
}
|
|
26
|
+
addToStaticSiteProps(scope, siteProps, { prefix = defaultAuthRoutePrefix } = {}) {
|
|
27
|
+
prefix = prefix.replace(/\/$/, ""); // Remove trailing slash from prefix if it has one
|
|
28
|
+
const behaviourName = `${prefix.replace(/^\//g, "")}/*`;
|
|
29
|
+
const distribution = siteProps.cdk?.distribution;
|
|
30
|
+
if (isCDKConstruct(distribution)) {
|
|
31
|
+
throw new Error(`CDK Construct for distribution is not supported when adding CloudFront OIDC Auth behavior for prefix ${prefix}`);
|
|
32
|
+
}
|
|
33
|
+
const updatedSiteProps = {
|
|
34
|
+
...siteProps,
|
|
35
|
+
cdk: {
|
|
36
|
+
...siteProps.cdk,
|
|
37
|
+
distribution: {
|
|
38
|
+
...siteProps.cdk?.distribution,
|
|
39
|
+
additionalBehaviors: distribution?.additionalBehaviors ?? {},
|
|
40
|
+
defaultBehavior: {
|
|
41
|
+
...distribution?.defaultBehavior,
|
|
42
|
+
functionAssociations: distribution?.defaultBehavior?.functionAssociations ?? [],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
if (updatedSiteProps.cdk.distribution.additionalBehaviors[behaviourName]) {
|
|
48
|
+
throw new Error(`Behavior for prefix ${prefix} already exists in distribution definition`);
|
|
49
|
+
}
|
|
50
|
+
const jwtSecret = this.createJwtSecret();
|
|
51
|
+
updatedSiteProps.cdk.distribution.defaultBehavior.functionAssociations.push(this.getFunctionAssociation(scope, jwtSecret, prefix));
|
|
52
|
+
updatedSiteProps.cdk.distribution.additionalBehaviors[behaviourName] =
|
|
53
|
+
this.getAuthBehaviorOptions(scope, jwtSecret, prefix);
|
|
54
|
+
return updatedSiteProps;
|
|
55
|
+
}
|
|
56
|
+
addToSsrSiteProps(scope, siteProps, { prefix = defaultAuthRoutePrefix } = {}) {
|
|
57
|
+
prefix = prefix.replace(/\/$/, ""); // Remove trailing slash from prefix if it has one
|
|
58
|
+
const behaviourName = `${prefix.replace(/^\//g, "")}/*`;
|
|
59
|
+
const updatedSiteProps = {
|
|
60
|
+
...siteProps,
|
|
61
|
+
cdk: {
|
|
62
|
+
...siteProps.cdk,
|
|
63
|
+
distribution: {
|
|
64
|
+
...siteProps.cdk?.distribution,
|
|
65
|
+
additionalBehaviors: siteProps.cdk?.distribution?.additionalBehaviors ?? {},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
if (updatedSiteProps.cdk.distribution.additionalBehaviors[behaviourName]) {
|
|
70
|
+
throw new Error(`Behavior for prefix ${prefix} already exists in distribution definition`);
|
|
71
|
+
}
|
|
72
|
+
const jwtSecret = this.createJwtSecret();
|
|
73
|
+
updatedSiteProps.cdk.transform = (plan) => {
|
|
74
|
+
siteProps?.cdk?.transform?.(plan);
|
|
75
|
+
plan.cloudFrontFunctions?.serverCfFunction.injections.push(this.getAuthCheckHandlerBodyCode(jwtSecret, prefix));
|
|
76
|
+
};
|
|
77
|
+
updatedSiteProps.cdk.distribution.additionalBehaviors[behaviourName] =
|
|
78
|
+
this.getAuthBehaviorOptions(scope, jwtSecret, prefix);
|
|
79
|
+
return updatedSiteProps;
|
|
80
|
+
}
|
|
81
|
+
createJwtSecret() {
|
|
82
|
+
return new SecretsManager.Secret(this, `${this.id}JwtSecret`, {
|
|
83
|
+
description: "JWT Signing Secret",
|
|
84
|
+
generateSecretString: {
|
|
85
|
+
passwordLength: 32,
|
|
86
|
+
excludePunctuation: true,
|
|
87
|
+
includeSpace: false,
|
|
88
|
+
requireEachIncludedType: true,
|
|
89
|
+
},
|
|
90
|
+
// Secret is only used for sessions so it's safe to delete on stack removal
|
|
91
|
+
removalPolicy: CDK.RemovalPolicy.DESTROY,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// Get the CloudFront Function Association for auth checking
|
|
95
|
+
// Roughly based off https://github.com/sst/v2/blob/4283d706f251724308b397996ff307929bf3a976/packages/sst/src/constructs/SsrSite.ts#L941
|
|
96
|
+
getFunctionAssociation(scope, jwtSecret, authRoutePrefix) {
|
|
97
|
+
const authCheckFunction = new CloudFront.Function(scope, `${this.id}AuthCheckFunction`, {
|
|
98
|
+
code: CloudFront.FunctionCode.fromInline(this.convertToCloudFrontFunctionCompatibleCode(`function handler(event) {
|
|
99
|
+
var request = event.request;
|
|
100
|
+
${this.getAuthCheckHandlerBodyCode(jwtSecret, authRoutePrefix)}
|
|
101
|
+
return request;
|
|
102
|
+
}`)),
|
|
103
|
+
// We could specify the JS v2.0 runtime here but for SSR sites SST does the function creation and that currently
|
|
104
|
+
// uses JS v1.0 so no point using v2.0 here as the code has to be compatible with v1.0 anyway.
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
function: authCheckFunction,
|
|
108
|
+
eventType: CloudFront.FunctionEventType.VIEWER_REQUEST,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
getAuthCheckHandlerBodyCode(jwtSecret, authRoutePrefix) {
|
|
112
|
+
return fs
|
|
113
|
+
.readFileSync(path.join(import.meta.dirname, "auth-check-handler-body.js"), "utf8")
|
|
114
|
+
.replace("__placeholder-for-jwt-secret__", jwtSecret.secretValue.toString())
|
|
115
|
+
.replace("__placeholder-for-auth-route-prefix__", authRoutePrefix);
|
|
116
|
+
}
|
|
117
|
+
convertToCloudFrontFunctionCompatibleCode(sourceCode) {
|
|
118
|
+
// ESBuild doesn't currently support transforming const/let to var, which is required for CloudFront Functions
|
|
119
|
+
// JS runtime 1.0.
|
|
120
|
+
sourceCode = sourceCode
|
|
121
|
+
.replaceAll(/const /g, "var ")
|
|
122
|
+
.replaceAll(/let /g, "var ");
|
|
123
|
+
return transformSync(sourceCode, {
|
|
124
|
+
minify: true,
|
|
125
|
+
target: "es5",
|
|
126
|
+
}).code;
|
|
127
|
+
}
|
|
128
|
+
// Get the behavior options for the auth route
|
|
129
|
+
getAuthBehaviorOptions(scope, jwtSecret, prefix) {
|
|
130
|
+
const authRouteFunction = new SST.Function(scope, `${this.id}AuthRouteFunction`, {
|
|
131
|
+
runtime: "nodejs20.x",
|
|
132
|
+
handler: path.join(import.meta.dirname, "auth-route.handler"),
|
|
133
|
+
environment: {
|
|
134
|
+
OIDC_ISSUER_URL: this.oidcIssuerUrl,
|
|
135
|
+
OIDC_CLIENT_ID: this.oidcClientId,
|
|
136
|
+
OIDC_SCOPE: this.oidcScope,
|
|
137
|
+
JWT_SECRET: jwtSecret.secretValue.toString(),
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
// authRouteFunction uses SST's AuthHandler construct which is normally run inside a lambda that's
|
|
141
|
+
// created by SST's Auth construct. AuthHandler expects certain environment variables to be set
|
|
142
|
+
// by the Auth construct so we have to set them ourselves here to keep it happy.
|
|
143
|
+
const envVarName = SSTInternalConfig.envFor({
|
|
144
|
+
type: "Auth",
|
|
145
|
+
id: "id", // It seems like the env var will still be found no matter what this value is
|
|
146
|
+
prop: "prefix",
|
|
147
|
+
});
|
|
148
|
+
authRouteFunction.addEnvironment(envVarName, prefix);
|
|
149
|
+
const authRouteFunctionUrl = authRouteFunction.addFunctionUrl({
|
|
150
|
+
authType: Lambda.FunctionUrlAuthType.NONE,
|
|
151
|
+
});
|
|
152
|
+
const forwardHostHeaderCfFunction = new CloudFront.Function(scope, `${this.id}ForwardHostHeaderFunction`, {
|
|
153
|
+
code: CloudFront.FunctionCode.fromInline(this.convertToCloudFrontFunctionCompatibleCode(`function handler(event) {
|
|
154
|
+
const request = event.request;
|
|
155
|
+
request.headers["x-forwarded-host"] = { value: request.headers.host.value };
|
|
156
|
+
return request;
|
|
157
|
+
}`)),
|
|
158
|
+
runtime: CloudFront.FunctionRuntime.JS_2_0,
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
origin: new CloudFrontOrigins.HttpOrigin(CDK.Fn.parseDomainName(authRouteFunctionUrl.url)),
|
|
162
|
+
allowedMethods: CloudFront.AllowedMethods.ALLOW_ALL,
|
|
163
|
+
cachePolicy: new CloudFront.CachePolicy(scope, `${this.id}AllowAllCookiesPolicy`, {
|
|
164
|
+
cachePolicyName: `${this.id}-AllowAllCookiesPolicy`,
|
|
165
|
+
comment: "Cache policy that forwards all cookies",
|
|
166
|
+
defaultTtl: CDK.Duration.seconds(1),
|
|
167
|
+
minTtl: CDK.Duration.seconds(1),
|
|
168
|
+
maxTtl: CDK.Duration.seconds(1),
|
|
169
|
+
cookieBehavior: CloudFront.CacheCookieBehavior.all(),
|
|
170
|
+
headerBehavior: CloudFront.CacheHeaderBehavior.allowList("X-Forwarded-Host"),
|
|
171
|
+
queryStringBehavior: CloudFront.CacheQueryStringBehavior.all(),
|
|
172
|
+
enableAcceptEncodingGzip: true,
|
|
173
|
+
enableAcceptEncodingBrotli: true,
|
|
174
|
+
}),
|
|
175
|
+
viewerProtocolPolicy: CloudFront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
|
|
176
|
+
functionAssociations: [
|
|
177
|
+
{
|
|
178
|
+
function: forwardHostHeaderCfFunction,
|
|
179
|
+
eventType: CloudFront.FunctionEventType.VIEWER_REQUEST,
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -6,5 +6,5 @@ export * from "./IxStaticSite.js";
|
|
|
6
6
|
export * from "./IxElasticache.js";
|
|
7
7
|
export * from "./IxApi.js";
|
|
8
8
|
export * from "./IxQuicksightWorkspace.js";
|
|
9
|
-
export * from "./
|
|
9
|
+
export * from "./SiteOidcAuth/index.js";
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|