@oslokommune/auth-bff 2.1.0 → 2.2.1
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 +38 -3
- package/dist/package.json +1 -1
- package/dist/src/OpenIdConfigManager.d.ts +1 -1
- package/dist/src/OpenIdConfigManager.d.ts.map +1 -1
- package/dist/src/OpenIdConfigManager.js +2 -2
- package/dist/src/config/config.d.ts +147 -0
- package/dist/src/config/config.d.ts.map +1 -0
- package/dist/src/config/config.js +54 -0
- package/dist/src/config/variable-loaders.d.ts +3 -0
- package/dist/src/config/variable-loaders.d.ts.map +1 -0
- package/dist/src/config/variable-loaders.js +20 -0
- package/dist/src/config.d.ts +7 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +32 -15
- package/dist/src/middleware/OidcMiddleware.d.ts +1 -1
- package/dist/src/middleware/OidcMiddleware.d.ts.map +1 -1
- package/dist/src/middleware/inject-config.d.ts +4 -0
- package/dist/src/middleware/inject-config.d.ts.map +1 -0
- package/dist/src/middleware/inject-config.js +10 -0
- package/dist/src/middleware/proxy-routes.d.ts +1 -1
- package/dist/src/middleware/proxy-routes.d.ts.map +1 -1
- package/dist/src/middleware/security-headers.d.ts +1 -1
- package/dist/src/middleware/security-headers.d.ts.map +1 -1
- package/dist/src/middleware/sessions/sessions.d.ts +1 -1
- package/dist/src/middleware/sessions/sessions.d.ts.map +1 -1
- package/dist/src/middleware/static-routes.d.ts +1 -1
- package/dist/src/middleware/static-routes.d.ts.map +1 -1
- package/dist/src/middleware/static-routes.js +3 -7
- package/dist/src/server.js +10 -4
- package/dist/src/vite-plugin.d.ts.map +1 -1
- package/dist/src/vite-plugin.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ WORKDIR /application
|
|
|
81
81
|
EXPOSE 8080
|
|
82
82
|
COPY --from=build /home/app/dist /application/dist
|
|
83
83
|
ENV NODE_ENV=production
|
|
84
|
-
RUN npm install -g @oslokommune/auth-bff
|
|
84
|
+
RUN npm install -g @oslokommune/auth-bff@<version>
|
|
85
85
|
COPY bff.config.json /application/
|
|
86
86
|
CMD ["auth-bff"]
|
|
87
87
|
```
|
|
@@ -164,7 +164,7 @@ This loads from the configured AWS environment. For this to work on your local m
|
|
|
164
164
|
variable must be set, and you must be signed in to that profile
|
|
165
165
|
|
|
166
166
|
> [!NOTE]
|
|
167
|
-
>️ See [`config.ts`](src/config.ts) for a description of all config parameters
|
|
167
|
+
>️ See [`config.ts`](src/config/config.ts) for a description of all config parameters
|
|
168
168
|
|
|
169
169
|
### Mixing public and protected routes
|
|
170
170
|
|
|
@@ -419,4 +419,39 @@ To use a nonce in your app, use `__CSP_NONCE__` in your html. It will be replace
|
|
|
419
419
|
<script nonce="__CSP_NONCE__">
|
|
420
420
|
...
|
|
421
421
|
</script>
|
|
422
|
-
```
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## Inject config
|
|
425
|
+
|
|
426
|
+
If your application requires configuration that needs to be determined at runtime, you can use `injectConfig` to inject
|
|
427
|
+
these values into a served html file:
|
|
428
|
+
|
|
429
|
+
```json
|
|
430
|
+
{
|
|
431
|
+
"injectConfig": {
|
|
432
|
+
"enableSomeFeature": true,
|
|
433
|
+
"publicToken": "{env:MY_PUBLIC_TOKEN}"
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
Then add something this to your `index.html`:
|
|
439
|
+
```html
|
|
440
|
+
<script nonce="__CSP_NONCE__">
|
|
441
|
+
const injectedConfig = __INJECTED_CONFIG__
|
|
442
|
+
</script>
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
When rendered, `__INJECTED_CONFIG__` will be replaced with the values from `injectConfig`:
|
|
446
|
+
|
|
447
|
+
```html
|
|
448
|
+
<script nonce="abcdef123456">
|
|
449
|
+
const injectedConfig = {
|
|
450
|
+
"enableSomeFeature": true,
|
|
451
|
+
"publicToken": "pub123abc"
|
|
452
|
+
}
|
|
453
|
+
</script>
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
> [!WARNING]
|
|
457
|
+
> Do not put any secrets or other sensitive values in the injected config, they will be publicly visible.
|
package/dist/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenIdConfigManager.d.ts","sourceRoot":"","sources":["../../src/OpenIdConfigManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"OpenIdConfigManager.d.ts","sourceRoot":"","sources":["../../src/OpenIdConfigManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAU7C,qBAAa,mBAAmB;;gBAMlB,MAAM,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,cAAc;IAK/D,IAAI;IA4BJ,kBAAkB;IAuCxB,IAAI,YAAY,yBAEf;CAEF"}
|
|
@@ -14,7 +14,7 @@ var _OpenIdConfigManager_instances, _OpenIdConfigManager_bffConfig, _OpenIdConfi
|
|
|
14
14
|
import forge from 'node-forge';
|
|
15
15
|
import * as jose from 'jose';
|
|
16
16
|
import * as client from 'openid-client';
|
|
17
|
-
import { getSsmParameter } from "./config.js";
|
|
17
|
+
import { getSsmParameter } from "./config/variable-loaders.js";
|
|
18
18
|
export class OpenIdConfigManager {
|
|
19
19
|
constructor(config, serverMetadata) {
|
|
20
20
|
_OpenIdConfigManager_instances.add(this);
|
|
@@ -29,7 +29,7 @@ export class OpenIdConfigManager {
|
|
|
29
29
|
if (__classPrivateFieldGet(this, _OpenIdConfigManager_bffConfig, "f").okDataIdPortenKeyName) {
|
|
30
30
|
setInterval(async () => {
|
|
31
31
|
await this.updateOpenIdConfig();
|
|
32
|
-
}, 5 * 60 * 1000);
|
|
32
|
+
}, 5 * 60 * 1000).unref();
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
async updateOpenIdConfig() {
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { HelmetOptions } from "helmet";
|
|
2
|
+
import session from "express-session";
|
|
3
|
+
export type BffConfig = {
|
|
4
|
+
/**
|
|
5
|
+
* The port at which the app will be served. Only used in standalone mode, to change the port used during development,
|
|
6
|
+
* set it in your vite config instead.
|
|
7
|
+
*/
|
|
8
|
+
port: number;
|
|
9
|
+
/**
|
|
10
|
+
* The base root path. Change if app is served from a non-root path.
|
|
11
|
+
*
|
|
12
|
+
* Default: `/`
|
|
13
|
+
*/
|
|
14
|
+
basePath?: string;
|
|
15
|
+
/**
|
|
16
|
+
* The root path of the static resources to be served
|
|
17
|
+
*
|
|
18
|
+
* Default: `/dist`
|
|
19
|
+
*/
|
|
20
|
+
staticRootPath?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The issuer
|
|
23
|
+
*
|
|
24
|
+
* Example: `https://test.idporten.no/`
|
|
25
|
+
*/
|
|
26
|
+
issuer: string;
|
|
27
|
+
/**
|
|
28
|
+
* The ID of the client
|
|
29
|
+
*/
|
|
30
|
+
clientId: string;
|
|
31
|
+
/**
|
|
32
|
+
* Sets the scope parameter. Values are case-sensitive. Multiple values must be sepratated by space. Default: `openid profile`
|
|
33
|
+
*/
|
|
34
|
+
scope: string;
|
|
35
|
+
/**
|
|
36
|
+
* The client secret. Not used if `okDataIdPortenKeyName` is set.
|
|
37
|
+
*/
|
|
38
|
+
clientSecret?: string;
|
|
39
|
+
/**
|
|
40
|
+
* The redirect uri configured for the client
|
|
41
|
+
*/
|
|
42
|
+
redirectUri: string;
|
|
43
|
+
/**
|
|
44
|
+
* The intended audience for the tokens. Value(s) set here can be used to verify audience on the recipient end.
|
|
45
|
+
* See https://datatracker.ietf.org/doc/html/draft-ietf-oauth-resource-indicators-05.
|
|
46
|
+
*
|
|
47
|
+
* Example: `["https://example.com/api1", "https://example.com/api2"]`
|
|
48
|
+
*/
|
|
49
|
+
resources?: Array<string>;
|
|
50
|
+
/**
|
|
51
|
+
* express-session cookie options, note that if this is set, the below cookie*-options will have no effect
|
|
52
|
+
*/
|
|
53
|
+
cookie?: session.CookieOptions;
|
|
54
|
+
/**
|
|
55
|
+
* Sets the Path attribute of the cookie. Should most likely be the same as basePath. See https://expressjs.com/en/resources/middleware/session.html
|
|
56
|
+
*
|
|
57
|
+
* Default: `/`
|
|
58
|
+
*/
|
|
59
|
+
cookiePath?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Sets the Secure attribute of the cookie. See https://expressjs.com/en/resources/middleware/session.html
|
|
62
|
+
*
|
|
63
|
+
* Default: `true`
|
|
64
|
+
*/
|
|
65
|
+
cookieSecure?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Sets the SameSite attribute of the cookie. See https://expressjs.com/en/resources/middleware/session.html
|
|
68
|
+
*
|
|
69
|
+
* Default: `"lax"`
|
|
70
|
+
*/
|
|
71
|
+
cookieSameSite: boolean | "lax" | "none" | "strict";
|
|
72
|
+
/**
|
|
73
|
+
* The post logout redirect uri configured for the client
|
|
74
|
+
*/
|
|
75
|
+
postLogoutRedirectUri: string;
|
|
76
|
+
/**
|
|
77
|
+
* The name of the key that okdata stored in parameter store.
|
|
78
|
+
*
|
|
79
|
+
* Example: `/okdata/maskinporten/11111111-2222-3333-4444-555555555555/key.json`
|
|
80
|
+
*/
|
|
81
|
+
okDataIdPortenKeyName?: string;
|
|
82
|
+
/**
|
|
83
|
+
* Secret used to sign sessions. This can be any string, but should have at least 32 bytes of entropy in production.
|
|
84
|
+
*/
|
|
85
|
+
sessionSecret: string;
|
|
86
|
+
/**
|
|
87
|
+
* The type of session store used. Only `memory` and `dynamodb` currently supported. `memory` is only for dev use
|
|
88
|
+
*/
|
|
89
|
+
sessionStoreType: 'memory' | 'dynamodb';
|
|
90
|
+
/**
|
|
91
|
+
* Options that will be passed to the chosen sessionStore. Options depend on the type of store chosen
|
|
92
|
+
*
|
|
93
|
+
* Example: `{"table": "my-custom-dynamodb-table"}`
|
|
94
|
+
*/
|
|
95
|
+
sessionStoreOptions?: object;
|
|
96
|
+
/**
|
|
97
|
+
* Map of paths and remote targets that will be forwarded by the proxy
|
|
98
|
+
*
|
|
99
|
+
* Example: `{'/api': 'http://example.com/api'}`
|
|
100
|
+
*/
|
|
101
|
+
proxyTargets: {
|
|
102
|
+
[path: string]: string;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Like `proxyTargets`, but requests pass through anonymously — no session lookup, no Authorization
|
|
106
|
+
* header. Registered before `proxyTargets`, so a public path takes precedence over an overlapping
|
|
107
|
+
* protected one.
|
|
108
|
+
*
|
|
109
|
+
* Example: `{'/api/public': 'http://example.com/api/public'}`
|
|
110
|
+
*/
|
|
111
|
+
publicProxyTargets?: {
|
|
112
|
+
[path: string]: string;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* List of claims in the id_token that are returned by the /user-endpoint. By default all are returned
|
|
116
|
+
*
|
|
117
|
+
* Example: `["pid"]`
|
|
118
|
+
*/
|
|
119
|
+
userClaims?: Array<string>;
|
|
120
|
+
/**
|
|
121
|
+
* Content security policy configuration passed to helmet.
|
|
122
|
+
* See https://github.com/helmetjs/helmet for details. Note that since the config in limited to json,
|
|
123
|
+
* some features are not supported. To set a nonce value, use the special value `"{nonce}"` instead.
|
|
124
|
+
*
|
|
125
|
+
*
|
|
126
|
+
* Example:
|
|
127
|
+
* ```json
|
|
128
|
+
* {
|
|
129
|
+
* "directives": {
|
|
130
|
+
* "default-src": ["'self'", "https://*.oslo.kommune.no", "https://*.oslo.systems"],
|
|
131
|
+
* "script-src": ["'self'", "{nonce}"],
|
|
132
|
+
* ...
|
|
133
|
+
* }
|
|
134
|
+
* }
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
contentSecurityPolicy?: Exclude<HelmetOptions['contentSecurityPolicy'], Boolean>;
|
|
138
|
+
/**
|
|
139
|
+
* These values will be injected into index.html, replacing any `__INJECTED_CONFIG__` if present
|
|
140
|
+
*/
|
|
141
|
+
injectConfig?: string | boolean | number | null | {
|
|
142
|
+
[k: string]: string | boolean | number | null;
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
export declare function replaceConfigValues(value: unknown): any;
|
|
146
|
+
export declare function loadConfig(configFile?: string | Array<string>): Promise<BffConfig>;
|
|
147
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/config/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,aAAa,EAAC,MAAM,QAAQ,CAAC;AACrC,OAAO,OAAO,MAAM,iBAAiB,CAAC;AAGtC,MAAM,MAAM,SAAS,GAAG;IACtB;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACzB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAA;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;;OAIG;IACH,cAAc,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;IACnD;;OAEG;IACH,qBAAqB,EAAE,MAAM,CAAA;IAC7B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B;;OAEG;IACH,aAAa,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,gBAAgB,EAAE,QAAQ,GAAG,UAAU,CAAA;IACvC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;OAIG;IACH,YAAY,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IACxC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IAC/C;;;;OAIG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC1B;;;;;;;;;;;;;;;;OAgBG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC,CAAA;IAChF;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAA;KAAC,CAAA;CAClG,CAAA;AAaD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,OAAO,OAuBvD;AAED,wBAAsB,UAAU,CAAC,UAAU,GAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAqB,sBActF"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { findUp } from 'find-up';
|
|
2
|
+
import { getEnv, getSsmParameter } from "./variable-loaders.js";
|
|
3
|
+
const defaultConfig = {
|
|
4
|
+
basePath: "",
|
|
5
|
+
cookiePath: '/',
|
|
6
|
+
cookieSecure: true,
|
|
7
|
+
cookieSameSite: 'lax',
|
|
8
|
+
staticRootPath: './dist',
|
|
9
|
+
scope: 'openid profile'
|
|
10
|
+
};
|
|
11
|
+
let config;
|
|
12
|
+
export async function replaceConfigValues(value) {
|
|
13
|
+
if (typeof value === "string") {
|
|
14
|
+
const [, varType, varName] = value.match(/\{(\w+):(.*)}/) ?? [];
|
|
15
|
+
if (varType === 'env') {
|
|
16
|
+
return getEnv(varName);
|
|
17
|
+
}
|
|
18
|
+
else if (varType === 'ssm') {
|
|
19
|
+
return await getSsmParameter(varName);
|
|
20
|
+
}
|
|
21
|
+
else if (varType) {
|
|
22
|
+
throw Error(`unknown varType: ${varType}`);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else if (Array.isArray(value)) {
|
|
29
|
+
return Promise.all(value.map(replaceConfigValues));
|
|
30
|
+
}
|
|
31
|
+
else if (typeof value === "object" && value != null) {
|
|
32
|
+
const res = {};
|
|
33
|
+
for (const [key, val] of Object.entries(value)) {
|
|
34
|
+
res[key] = await replaceConfigValues(val);
|
|
35
|
+
}
|
|
36
|
+
return res;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export async function loadConfig(configFile = 'bff.config.json') {
|
|
43
|
+
if (config)
|
|
44
|
+
return config;
|
|
45
|
+
const userConfigPath = await findUp(configFile);
|
|
46
|
+
if (!userConfigPath) {
|
|
47
|
+
throw Error(`Could not find config file ${configFile}`);
|
|
48
|
+
}
|
|
49
|
+
console.log('Loading config at', userConfigPath);
|
|
50
|
+
const { default: loadedConfig } = await import(userConfigPath, { with: { type: 'json' } });
|
|
51
|
+
const processedConfig = await replaceConfigValues(loadedConfig);
|
|
52
|
+
config = { ...defaultConfig, ...processedConfig };
|
|
53
|
+
return config;
|
|
54
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variable-loaders.d.ts","sourceRoot":"","sources":["../../../src/config/variable-loaders.ts"],"names":[],"mappings":"AAEA,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,UAQzF;AAID,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,GAAE,OAAc,mBAMjF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { GetParameterCommand, SSMClient } from "@aws-sdk/client-ssm";
|
|
2
|
+
export function getEnv(env, defaultVal, parseFn) {
|
|
3
|
+
if (process.env[env]) {
|
|
4
|
+
return parseFn ? parseFn(process.env[env]) : process.env[env];
|
|
5
|
+
}
|
|
6
|
+
else if (defaultVal !== undefined) {
|
|
7
|
+
return defaultVal;
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
throw Error(`Missing env var: ${env}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
let ssmClient;
|
|
14
|
+
export async function getSsmParameter(name, withDecryption = true) {
|
|
15
|
+
ssmClient ?? (ssmClient = new SSMClient({}));
|
|
16
|
+
return ssmClient.send(new GetParameterCommand({
|
|
17
|
+
Name: name,
|
|
18
|
+
WithDecryption: withDecryption
|
|
19
|
+
})).then(p => p.Parameter.Value);
|
|
20
|
+
}
|
package/dist/src/config.d.ts
CHANGED
|
@@ -135,8 +135,15 @@ export type BffConfig = {
|
|
|
135
135
|
* ```
|
|
136
136
|
*/
|
|
137
137
|
contentSecurityPolicy?: Exclude<HelmetOptions['contentSecurityPolicy'], Boolean>;
|
|
138
|
+
/**
|
|
139
|
+
* These values will be injected into index.html, replacing any `__INJECTED_CONFIG__` if present
|
|
140
|
+
*/
|
|
141
|
+
injectConfig?: string | {
|
|
142
|
+
[k: string]: any;
|
|
143
|
+
};
|
|
138
144
|
};
|
|
139
145
|
export declare function getEnv(env: string, defaultVal?: string, parseFn?: (val: string) => string): string;
|
|
140
146
|
export declare function getSsmParameter(name: string, withDecryption?: boolean): Promise<string>;
|
|
147
|
+
export declare function replaceConfigValues(value: unknown): any;
|
|
141
148
|
export declare function loadConfig(configFile?: string | Array<string>): Promise<BffConfig>;
|
|
142
149
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/src/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,aAAa,EAAC,MAAM,QAAQ,CAAC;AACrC,OAAO,OAAO,MAAM,iBAAiB,CAAC;AAEtC,MAAM,MAAM,SAAS,GAAG;IACtB;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACzB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAA;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;;OAIG;IACH,cAAc,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;IACnD;;OAEG;IACH,qBAAqB,EAAE,MAAM,CAAA;IAC7B;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,CAAA;IAC7B;;OAEG;IACH,aAAa,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,gBAAgB,EAAE,QAAQ,GAAG,UAAU,CAAA;IACvC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;OAIG;IACH,YAAY,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IACxC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IAC/C;;;;OAIG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC1B;;;;;;;;;;;;;;;;OAgBG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,aAAa,EAAC,MAAM,QAAQ,CAAC;AACrC,OAAO,OAAO,MAAM,iBAAiB,CAAC;AAEtC,MAAM,MAAM,SAAS,GAAG;IACtB;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACzB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAA;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;;OAIG;IACH,cAAc,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;IACnD;;OAEG;IACH,qBAAqB,EAAE,MAAM,CAAA;IAC7B;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,CAAA;IAC7B;;OAEG;IACH,aAAa,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,gBAAgB,EAAE,QAAQ,GAAG,UAAU,CAAA;IACvC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;OAIG;IACH,YAAY,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IACxC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IAC/C;;;;OAIG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC1B;;;;;;;;;;;;;;;;OAgBG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC,CAAA;IAChF;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAAA;CAC3C,CAAA;AAWD,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,UAQzF;AAID,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,GAAE,OAAc,mBAMjF;AAID,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,OAAO,OAuBvD;AAED,wBAAsB,UAAU,CAAC,UAAU,GAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAqB,sBActF"}
|
package/dist/src/config.js
CHANGED
|
@@ -28,6 +28,36 @@ export async function getSsmParameter(name, withDecryption = true) {
|
|
|
28
28
|
})).then(p => p.Parameter.Value);
|
|
29
29
|
}
|
|
30
30
|
let config;
|
|
31
|
+
export async function replaceConfigValues(value) {
|
|
32
|
+
if (typeof value === "string") {
|
|
33
|
+
const [, varType, varName] = value.match(/\{(\w+):(.*)}/) ?? [];
|
|
34
|
+
if (varType === 'env') {
|
|
35
|
+
return getEnv(varName);
|
|
36
|
+
}
|
|
37
|
+
else if (varType === 'ssm') {
|
|
38
|
+
return await getSsmParameter(varName);
|
|
39
|
+
}
|
|
40
|
+
else if (varType) {
|
|
41
|
+
throw Error(`unknown varType: ${varType}`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (Array.isArray(value)) {
|
|
48
|
+
return Promise.all(value.map(replaceConfigValues));
|
|
49
|
+
}
|
|
50
|
+
else if (typeof value === "object" && value != null) {
|
|
51
|
+
const res = {};
|
|
52
|
+
for (const [key, val] of Object.entries(value)) {
|
|
53
|
+
res[key] = await replaceConfigValues(val);
|
|
54
|
+
}
|
|
55
|
+
return res;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
31
61
|
export async function loadConfig(configFile = 'bff.config.json') {
|
|
32
62
|
if (config)
|
|
33
63
|
return config;
|
|
@@ -37,20 +67,7 @@ export async function loadConfig(configFile = 'bff.config.json') {
|
|
|
37
67
|
}
|
|
38
68
|
console.log('Loading config at', userConfigPath);
|
|
39
69
|
const { default: loadedConfig } = await import(userConfigPath, { with: { type: 'json' } });
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const [, varType, varName] = value.match(/\{(\w+):(.*)}/) ?? [];
|
|
43
|
-
if (varType === 'env') {
|
|
44
|
-
loadedConfig[key] = getEnv(varName);
|
|
45
|
-
}
|
|
46
|
-
else if (varType === 'ssm') {
|
|
47
|
-
loadedConfig[key] = await getSsmParameter(varName);
|
|
48
|
-
}
|
|
49
|
-
else if (varType) {
|
|
50
|
-
throw Error(`unknown varType: ${varType}`);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
config = { ...defaultConfig, ...loadedConfig };
|
|
70
|
+
const processedConfig = await replaceConfigValues(loadedConfig);
|
|
71
|
+
config = { ...defaultConfig, ...processedConfig };
|
|
55
72
|
return config;
|
|
56
73
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OpenIdConfigManager } from "../OpenIdConfigManager.js";
|
|
2
|
-
import { BffConfig } from "../config.js";
|
|
2
|
+
import { BffConfig } from "../config/config.js";
|
|
3
3
|
import type { Request, Response, NextFunction } from 'express';
|
|
4
4
|
export declare class OidcMiddleware {
|
|
5
5
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OidcMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/OidcMiddleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,mBAAmB,EAAC,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAAC,SAAS,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"OidcMiddleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/OidcMiddleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,mBAAmB,EAAC,MAAM,2BAA2B,CAAC;AAE9D,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAC9C,OAAO,KAAK,EAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAC,MAAM,SAAS,CAAA;AAK5D,qBAAa,cAAc;;IAKzB;;;;OAIG;gBACS,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,mBAAmB;WASpD,MAAM,CAAC,MAAM,EAAE,SAAS;IAgErC,IAAI,gBAAgB,KACV,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAWxD;IAED,IAAI,KAAK,KACO,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,mBA+B9D;IAqBD,IAAI,QAAQ,KACI,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,mBAuC9D;IAED,IAAI,IAAI,KACQ,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,iDAc9D;IAED,IAAI,MAAM,KACA,KAAK,OAAO,EAAE,KAAK,QAAQ,UASpC;IAED,IAAI,kBAAkB,KACN,KAAK,OAAO,EAAE,KAAK,QAAQ,mBAc1C;CACF"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { BffConfig } from "../config/config.js";
|
|
2
|
+
import { Request, Response } from "express";
|
|
3
|
+
export declare function injectConfig(config: BffConfig): (req: Request, originalResponse: Response, next: import("express").NextFunction) => void;
|
|
4
|
+
//# sourceMappingURL=inject-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-config.d.ts","sourceRoot":"","sources":["../../../src/middleware/inject-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAC,MAAM,SAAS,CAAC;AAG1C,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,4FAQ7C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { stringReplace } from "string-replace-middleware";
|
|
2
|
+
export function injectConfig(config) {
|
|
3
|
+
const injectConfigString = JSON.stringify(config.injectConfig)?.replace(/[&'<>]/g, '_ILLEGAL_CHAR_');
|
|
4
|
+
return stringReplace({
|
|
5
|
+
'__CSP_NONCE__': (_, res) => res.locals.cspNonce,
|
|
6
|
+
'__INJECTED_CONFIG__': injectConfigString,
|
|
7
|
+
}, {
|
|
8
|
+
contentTypeFilterRegexp: /^text\/html/
|
|
9
|
+
});
|
|
10
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BffConfig } from "../config.js";
|
|
1
|
+
import { BffConfig } from "../config/config.js";
|
|
2
2
|
import { OidcMiddleware } from "./OidcMiddleware.js";
|
|
3
3
|
export declare function proxyRoutes(config: BffConfig, oidcMiddleware: OidcMiddleware): import("express-serve-static-core").Router;
|
|
4
4
|
//# sourceMappingURL=proxy-routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy-routes.d.ts","sourceRoot":"","sources":["../../../src/middleware/proxy-routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,SAAS,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"proxy-routes.d.ts","sourceRoot":"","sources":["../../../src/middleware/proxy-routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAEnD,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,8CAoD5E"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { BffConfig } from "../config.js";
|
|
2
|
+
import { BffConfig } from "../config/config.js";
|
|
3
3
|
export declare function securityHeaders(config: BffConfig): ((_: Request, res: Response, next: NextFunction) => void)[];
|
|
4
4
|
//# sourceMappingURL=security-headers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-headers.d.ts","sourceRoot":"","sources":["../../../src/middleware/security-headers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAC,MAAM,SAAS,CAAA;AACvD,OAAO,EAAC,SAAS,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"security-headers.d.ts","sourceRoot":"","sources":["../../../src/middleware/security-headers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAC,MAAM,SAAS,CAAA;AACvD,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAE9C,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,QAcR,OAAO,OAAO,QAAQ,QAAQ,YAAY,aAkBlF"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { BffConfig } from "../../config.js";
|
|
1
|
+
import { BffConfig } from "../../config/config.js";
|
|
2
2
|
export declare function sessions(config: BffConfig): import("express").RequestHandler<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>[];
|
|
3
3
|
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../../src/middleware/sessions/sessions.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,SAAS,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../../src/middleware/sessions/sessions.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,SAAS,EAAC,MAAM,wBAAwB,CAAC;AAGjD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,kJAiCzC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-routes.d.ts","sourceRoot":"","sources":["../../../src/middleware/static-routes.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,SAAS,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"static-routes.d.ts","sourceRoot":"","sources":["../../../src/middleware/static-routes.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAG9C,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,8CAY7C"}
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
import express from "express";
|
|
2
|
-
import { stringReplace } from "string-replace-middleware";
|
|
3
2
|
import path from "path";
|
|
3
|
+
import { injectConfig } from "./inject-config.js";
|
|
4
4
|
export function staticRoutes(config) {
|
|
5
5
|
const router = express.Router();
|
|
6
|
-
router.use(
|
|
7
|
-
'__CSP_NONCE__': (_, res) => res.locals.cspNonce
|
|
8
|
-
}, {
|
|
9
|
-
contentTypeFilterRegexp: /^text\/html/
|
|
10
|
-
}));
|
|
6
|
+
router.use(injectConfig(config));
|
|
11
7
|
const staticPath = path.resolve(process.cwd(), config.staticRootPath);
|
|
12
8
|
console.log(`Serving static content from '${staticPath}'`);
|
|
13
9
|
router.use(express.static(staticPath, { index: false }));
|
|
14
10
|
router.get('*', function (_, res) {
|
|
15
11
|
res.set('Cache-Control', 'no-store');
|
|
16
|
-
res.sendFile(path.resolve(staticPath, 'index.html'));
|
|
12
|
+
res.sendFile(path.resolve(staticPath, 'index.html'), { etag: false });
|
|
17
13
|
});
|
|
18
14
|
return router;
|
|
19
15
|
}
|
package/dist/src/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import express from "express";
|
|
3
3
|
import compression from "compression";
|
|
4
|
-
import { loadConfig } from './config.js';
|
|
4
|
+
import { loadConfig } from './config/config.js';
|
|
5
5
|
import { proxyRoutes } from "./middleware/proxy-routes.js";
|
|
6
6
|
import { staticRoutes } from "./middleware/static-routes.js";
|
|
7
7
|
import { securityHeaders } from "./middleware/security-headers.js";
|
|
@@ -35,9 +35,15 @@ app.use(basePath, staticRoutes(config));
|
|
|
35
35
|
const server = app.listen(port, () => {
|
|
36
36
|
console.log(`auth-bff ${packageJson.version} started on port ${port}`);
|
|
37
37
|
});
|
|
38
|
-
|
|
39
|
-
console.log(
|
|
38
|
+
const shutdown = (signal) => {
|
|
39
|
+
console.log(`${signal} received. Closing...`);
|
|
40
40
|
server.close(() => {
|
|
41
41
|
console.log('Server closed');
|
|
42
42
|
});
|
|
43
|
-
|
|
43
|
+
setTimeout(() => {
|
|
44
|
+
console.warn('Forced shutdown after timeout');
|
|
45
|
+
process.exit();
|
|
46
|
+
}, 10000).unref();
|
|
47
|
+
};
|
|
48
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
49
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../../src/vite-plugin.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,MAAM,EAAC,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../../src/vite-plugin.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,MAAM,EAAC,MAAM,MAAM,CAAA;AAwB1C,MAAM,CAAC,OAAO,UAAU,GAAG,CAAC,EAAC,UAAU,EAAC,GAAE;IAAC,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;CAAM,GAAG,MAAM,CAO5F"}
|
package/dist/src/vite-plugin.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import express from "express";
|
|
2
|
-
import { loadConfig } from "./config.js";
|
|
2
|
+
import { loadConfig } from "./config/config.js";
|
|
3
3
|
import { OidcMiddleware } from "./middleware/OidcMiddleware.js";
|
|
4
|
+
import { injectConfig } from "./middleware/inject-config.js";
|
|
4
5
|
function configureServer(configFilePath) {
|
|
5
6
|
return async ({ middlewares }) => {
|
|
6
7
|
const { oidcRoutes } = await import("./middleware/oidc-routes.js");
|
|
@@ -13,6 +14,7 @@ function configureServer(configFilePath) {
|
|
|
13
14
|
app.use(sessions(config));
|
|
14
15
|
app.use(basePath, oidcRoutes(oidcMiddleware));
|
|
15
16
|
app.use(basePath, proxyRoutes(config, oidcMiddleware));
|
|
17
|
+
app.use(basePath, injectConfig(config));
|
|
16
18
|
middlewares.use(app);
|
|
17
19
|
};
|
|
18
20
|
}
|