@owlmeans/server-oidc-provider 0.1.18-rc.49 → 0.1.18-rc.50
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 +2 -2
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/server-oidc-provider/SKILL.md +1 -1
- package/build/iam.d.ts +2 -2
- package/build/iam.d.ts.map +1 -1
- package/build/iam.js.map +1 -1
- package/build/middleware.d.ts.map +1 -1
- package/build/middleware.js.map +1 -1
- package/build/service.js +2 -2
- package/build/service.js.map +1 -1
- package/build/types.d.ts +7 -4
- package/build/types.d.ts.map +1 -1
- package/build/utils/config/types.d.ts +11 -0
- package/build/utils/config/types.d.ts.map +1 -0
- package/build/utils/config/types.js +2 -0
- package/build/utils/config/types.js.map +1 -0
- package/build/utils/config.d.ts +5 -2
- package/build/utils/config.d.ts.map +1 -1
- package/build/utils/config.js +82 -46
- package/build/utils/config.js.map +1 -1
- package/build/utils/index.d.ts +1 -1
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +0 -1
- package/build/utils/index.js.map +1 -1
- package/package.json +10 -10
- package/src/iam.ts +2 -2
- package/src/middleware.ts +1 -1
- package/src/service.ts +2 -2
- package/src/types.ts +7 -3
- package/src/utils/config/types.ts +11 -0
- package/src/utils/config.ts +95 -47
- package/src/utils/index.ts +1 -2
- package/tests/config.spec.ts +9 -9
- package/tests/pairwise.spec.ts +2 -2
- package/build/utils/client.d.ts +0 -7
- package/build/utils/client.d.ts.map +0 -1
- package/build/utils/client.js +0 -33
- package/build/utils/client.js.map +0 -1
- package/src/utils/client.ts +0 -42
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Embedded OIDC identity provider — wraps the `oidc-provider` library as an OwlM
|
|
|
14
14
|
## Installation
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
bun add @owlmeans/server-oidc-provider@^0.1.18-rc.
|
|
17
|
+
bun add @owlmeans/server-oidc-provider@^0.1.18-rc.50
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
## Usage
|
|
@@ -72,7 +72,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
72
72
|
your project's skill store (`.agents/skills/`):
|
|
73
73
|
|
|
74
74
|
```sh
|
|
75
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
75
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.49
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/server-oidc-provider",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-10-
|
|
4
|
+
"version": "0.1.18-rc.50",
|
|
5
|
+
"generatedAt": "2026-10-05T21:03:06.408Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -8,7 +8,7 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/server-oidc-provider
|
|
9
9
|
|
|
10
10
|
**Layer:** Server
|
|
11
|
-
**Install:** `"@owlmeans/server-oidc-provider": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/server-oidc-provider": "^0.1.18-rc.50"` in `dependencies`
|
|
12
12
|
**Runtime deps:** `oidc-provider@9.11.1` (exact), `jose@6.2.5` (exact), `@types/oidc-provider@9.5.0`
|
|
13
13
|
|
|
14
14
|
Use this only when your service **is** the identity provider. For consuming someone else's issuer,
|
package/build/iam.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ToClientMetadata } from './types.js';
|
|
2
2
|
/** Convert an OidcRegisteredClient to the oidc-provider ClientMetadata shape. */
|
|
3
|
-
export declare const toClientMetadata:
|
|
3
|
+
export declare const toClientMetadata: ToClientMetadata;
|
|
4
4
|
//# sourceMappingURL=iam.d.ts.map
|
package/build/iam.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iam.d.ts","sourceRoot":"","sources":["../src/iam.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"iam.d.ts","sourceRoot":"","sources":["../src/iam.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA4C,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE5F,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,EAAE,gBAS7B,CAAA"}
|
package/build/iam.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iam.js","sourceRoot":"","sources":["../src/iam.ts"],"names":[],"mappings":"AAGA,iFAAiF;AACjF,MAAM,CAAC,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"iam.js","sourceRoot":"","sources":["../src/iam.ts"],"names":[],"mappings":"AAGA,iFAAiF;AACjF,MAAM,CAAC,MAAM,gBAAgB,GAAqB,CAAC,MAA4B,EAAsB,EAAE,CAAC,CAAC;IACvG,SAAS,EAAE,MAAM,CAAC,QAAQ;IAC1B,aAAa,EAAE,MAAM,CAAC,MAAM;IAC5B,aAAa,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE;IACxC,WAAW,EAAE,MAAM,CAAC,UAAU,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAAC;IACzE,cAAc,EAAE,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,CAAmB;IACpE,0BAA0B,EAAE,qBAAqB;IACjD,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,+BAA+B;IACtD,WAAW,EAAE,MAAM,CAAC,QAAQ;CAC7B,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAOnD,eAAO,MAAM,4BAA4B,SAAS,MAAM,
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAOnD,eAAO,MAAM,4BAA4B,SAAS,MAAM,SAAoB,MAAM,KAAmB,UAqBpG,CAAA"}
|
package/build/middleware.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClF,OAAO,EAAE,aAAa,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAEjE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAG3C,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,GAAG,GAAW,SAAS,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClF,OAAO,EAAE,aAAa,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAEjE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAG3C,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,GAAG,GAAW,SAAS,EAAE,IAAI,GAAW,aAAa,EAAc,EAAE;IAChH,MAAM,UAAU,GAAe;QAC7B,IAAI,EAAE,cAAc,CAAC,OAAO;QAC5B,KAAK,EAAE,eAAe,CAAC,OAAO;QAC9B,KAAK,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;YACjB,MAAM,OAAO,GAAG,aAAa,CAAkB,GAAyB,CAAY,CAAA;YACpF,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAY,GAAG,CAAC,CAAA;YAClD,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAsB,IAAI,CAAC,CAAA;YAE9D,MAAM,MAAM,GAAG,sBAAsB,GAAG,IAAI,IAAI,EAAE,CAAA;YAClD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC;gBAC3D,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;gBACpC,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;oBAC5B,GAAG,CAAC,GAAG,CAAC,OAAO,GAAG,EAAE,CAAA;gBACtB,CAAC;gBACD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;YACtC,CAAC;QACH,CAAC;KACF,CAAA;IAED,OAAO,UAAU,CAAA;AACnB,CAAC,CAAA"}
|
package/build/service.js
CHANGED
|
@@ -5,7 +5,7 @@ import Provider from 'oidc-provider';
|
|
|
5
5
|
import { logger } from '@owlmeans/log';
|
|
6
6
|
import { PARAM, SEP } from '@owlmeans/route';
|
|
7
7
|
import { makeSecurityHelper } from '@owlmeans/config';
|
|
8
|
-
import {
|
|
8
|
+
import { oidcConfigOf } from './utils/config.js';
|
|
9
9
|
import { makeInteractionPolicy } from './utils/policy.js';
|
|
10
10
|
const log = logger('server-oidc-provider');
|
|
11
11
|
/** An OIDC error the provider answers with a 4xx — the client's mistake, not the provider's. */
|
|
@@ -45,7 +45,7 @@ export const createOidcProviderService = (alias = DEFAULT_ALIAS) => {
|
|
|
45
45
|
const url = helper.makeUrl(serviceRoute, cfg.basePath ?? DEFAULT_PATH, { base: true });
|
|
46
46
|
const unsecure = context.cfg.security?.unsecure === false ? false : !url.startsWith('https');
|
|
47
47
|
const oidc = new Provider(url, {
|
|
48
|
-
...await combineConfig(
|
|
48
|
+
...await oidcConfigOf(context).combineConfig(unsecure),
|
|
49
49
|
adapter: cfg.adapterService != null
|
|
50
50
|
? name => context.service(cfg.adapterService).instance(name)
|
|
51
51
|
: undefined,
|
package/build/service.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACjE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAG3E,OAAO,QAAQ,MAAM,eAAe,CAAA;AAEpC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAGtC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACjE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAG3E,OAAO,QAAQ,MAAM,eAAe,CAAA;AAEpC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAGtC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,MAAM,GAAG,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAA;AAE1C,gGAAgG;AAChG,MAAM,aAAa,GAAG,CAAC,KAAc,EAAW,EAAE;IAChD,MAAM,MAAM,GAAI,KAAqC,EAAE,MAAM,CAAA;IAC7D,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,CAAA;AACpE,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAE,IAAY,EAAE,GAAmC,EAAE,KAAY,EAAQ,EAAE;IACpH,MAAM,KAAK,GAAG,GAAG,EAAE,IAEN,CAAA;IACb,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAG,KAA6B,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;IACnH,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC,iCAAiC,EAAE,IAAI,CAAC,CAAA;IACnD,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,KAAK,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAA;IACxC,CAAC;IACD,IAAI,KAAK,IAAI,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,GAAG,CAAC,KAAK,CAAC,2BAA2B,EAAE;YACrC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC;YAC/C,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI;gBACxB,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS;SAC/G,CAAC,CAAA;IACJ,CAAC;AACH,CAAC,CAAA;AAED,IAAI,gBAAgB,GAAyB,SAAS,CAAA;AACtD,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,KAAK,GAAW,aAAa,EAAuB,EAAE;IAC9F,MAAM,OAAO,GAAwB,aAAa,CAAsB,KAAK,EAAE;QAC7E,MAAM,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;YAClB,MAAM,OAAO,GAAG,aAAa,CAAkB,OAAO,CAAC,GAAc,EAAE,KAAK,CAAC,CAAA;YAC7E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAA;YAE5B,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAe,CAAA;YAC/F,MAAM,MAAM,GAAG,kBAAkB,CAAkB,OAAO,CAAC,CAAA;YAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,QAAQ,IAAI,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;YACtF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;YAE5F,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,GAAG,EAAE;gBAC7B,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC;gBAEtD,OAAO,EAAE,GAAG,CAAC,cAAc,IAAI,IAAI;oBACjC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAqB,GAAG,CAAC,cAAe,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;oBACjF,CAAC,CAAC,SAAS;gBAEb,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE;oBACrC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAChC,GAAG,CAAC,cAAc,IAAI,oBAAoB,CAC3C,CAAA;oBAED,MAAM,QAAQ,GAAI,IAAsD,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ;2BAC1F,KAA2C,EAAE,QAAQ,CAAA;oBAE3D,OAAO,UAAU,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;gBACvD,CAAC;gBAED,YAAY,EAAE;oBACZ,MAAM,EAAE,qBAAqB,EAAE;oBAC/B,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE;wBAC5B,iFAAiF;wBACjF,wEAAwE;wBACxE,uFAAuF;wBACvF,uFAAuF;wBACvF,sFAAsF;wBACtF,cAAc;wBACd,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAmB,WAAW,CAAC,CAAA;wBAC/D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC;6BACjC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,GAAG,KAAK,GAAG,eAAe,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;6BAC3E,IAAI,CAAC,GAAG,CAAC,CAAA;wBAEZ,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,CAAA;oBAC9C,CAAC;iBACF;aACF,CAAC,CAAA;YAEF,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,WAAW,IAAI,QAAQ,CAAA;YACxC,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,YAAY,CAAC,CAAA;YAEjD;;;;;;;;;;eAUG;YACH,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAa,EAAE,GAAmB,EAAE,IAAgB,EAAE,EAAE;gBAC5E,mFAAmF;gBACnF,uFAAuF;gBACvF,yFAAyF;gBACzF,oFAAoF;gBACpF,6DAA6D;gBAC7D,GAAG,CAAC,SAAS,CAAC,4BAA4B,EAAE,aAAa,CAAC,CAAA;gBAE1D,oFAAoF;gBACpF,8BAA8B;gBAC9B,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAA;gBACpD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;oBAClE,GAAG,CAAC,SAAS,CAAC,yBAAyB,EAAE,GAAG,CAAC,OAAO,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC,CAAA;gBAC9F,CAAC;gBAED,IAAI,EAAE,CAAA;YACR,CAAC,CAAC,CAAA;YAEF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;YAErC,0FAA0F;YAC1F,6FAA6F;YAC7F,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA,CAAC,CAAC,CAAC,CAAA;YACjG,IAAI,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA,CAAC,CAAC,CAAC,CAAA;YACnG,IAAI,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA,CAAC,CAAC,CAAC,CAAA;YAEvG,gBAAgB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAA;QACxC,CAAC;QAED,QAAQ,EAAE,GAAG,EAAE;YACb,OAAO,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,gBAAiB,CAAC,CAAA;QAC3D,CAAC;QAED,cAAc,EAAE,KAAK,EAAC,EAAE,EAAC,EAAE;YACzB,OAAO,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAA;QAC9D,CAAC;KACF,CAAC,CAAA;IAEF,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,GAAM,EAAE,KAAK,GAAW,aAAa,EAClC,EAAE;IACL,MAAM,OAAO,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAA;IAChD,MAAM,OAAO,GAAG,GAAQ,CAAA;IAExB,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;IAEhC,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
package/build/types.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ import type { OidcSharedConfig } from '@owlmeans/oidc';
|
|
|
3
3
|
import type { ApiServer, ApiServerAppend } from '@owlmeans/server-api';
|
|
4
4
|
import type { ServerConfig, ServerContext } from '@owlmeans/server-context';
|
|
5
5
|
import type { Account, Adapter, ClientMetadata, Configuration, Interaction, Provider } from 'oidc-provider';
|
|
6
|
-
import { toClientMetadata } from './iam.js';
|
|
7
6
|
export interface OidcProviderService extends InitializedService {
|
|
8
7
|
oidc: Provider;
|
|
9
8
|
update: (api: ApiServer) => Promise<void>;
|
|
@@ -79,14 +78,18 @@ export interface OidcRegisteredClient {
|
|
|
79
78
|
scope?: string;
|
|
80
79
|
}
|
|
81
80
|
/** Full oidc-provider ClientMetadata with our entity extension. */
|
|
82
|
-
export
|
|
81
|
+
export interface OidcClientMetadata extends ClientMetadata {
|
|
83
82
|
entityId?: string;
|
|
84
83
|
owlEntityId?: string;
|
|
85
|
-
}
|
|
84
|
+
}
|
|
85
|
+
/** Converts a stored client record to oidc-provider ClientMetadata. */
|
|
86
|
+
export interface ToClientMetadata {
|
|
87
|
+
(client: OidcRegisteredClient): OidcClientMetadata;
|
|
88
|
+
}
|
|
86
89
|
/** Extension seam for IAM integration into the OIDC provider — Phase 2 fills this */
|
|
87
90
|
export interface OidcProviderIamExtension {
|
|
88
91
|
/** Convert a stored client record to oidc-provider ClientMetadata */
|
|
89
|
-
toClientMetadata:
|
|
92
|
+
toClientMetadata: ToClientMetadata;
|
|
90
93
|
/** Type of a stored client record */
|
|
91
94
|
OidcRegisteredClient: OidcRegisteredClient;
|
|
92
95
|
/** Extended metadata type */
|
package/build/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { OidcCustomConfiguration } from '../../types.js';
|
|
2
|
+
/** The provider configuration one context's settings resolve to. */
|
|
3
|
+
export interface OidcConfigUtils {
|
|
4
|
+
/**
|
|
5
|
+
* The deployment's configuration merged over this package's defaults: its clients with their
|
|
6
|
+
* `{{service-alias}}` URIs expanded (and, in debug only, a generated secret), the claims behind
|
|
7
|
+
* every scope, the discovery extras and the signing key.
|
|
8
|
+
*/
|
|
9
|
+
combineConfig: (unsecure: boolean) => Promise<OidcCustomConfiguration>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/config/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAE7D,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,aAAa,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAA;CACvE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/config/types.ts"],"names":[],"mappings":""}
|
package/build/utils/config.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { Config, Context } from '../types.js';
|
|
2
|
+
import type { OidcConfigUtils } from './config/types.js';
|
|
3
|
+
export declare const makeOidcConfigUtils: (context: Context) => OidcConfigUtils;
|
|
4
|
+
/** The configuration utils of a context — one per context. */
|
|
5
|
+
export declare const oidcConfigOf: (target: Context<Config>) => OidcConfigUtils;
|
|
3
6
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAA2B,MAAM,aAAa,CAAA;AAQ3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAQxD,eAAO,MAAM,mBAAmB,YAAa,OAAO,KAAG,eAqFtD,CAAA;AAED,8DAA8D;AAC9D,eAAO,MAAM,YAAY,8CAA0C,CAAA"}
|
package/build/utils/config.js
CHANGED
|
@@ -1,55 +1,91 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomBytes } from '@noble/hashes/utils.js';
|
|
2
|
+
import { hex } from '@scure/base';
|
|
2
3
|
import { ORGANIZATIONS_CLAIM, ORGANIZATIONS_SCOPE, PERMISSIONS_CLAIM, PERMISSIONS_SCOPE } from '@owlmeans/oidc';
|
|
3
4
|
import { makeSecurityHelper } from '@owlmeans/config';
|
|
5
|
+
import { memoHelper } from '@owlmeans/context';
|
|
6
|
+
import { SEP } from '@owlmeans/route';
|
|
7
|
+
import { logger } from '@owlmeans/log';
|
|
4
8
|
import * as jose from 'jose';
|
|
9
|
+
const log = logger('server-oidc-provider');
|
|
5
10
|
/** A claim list is an array, or (as the provider's types also allow) a record keyed by claim name. */
|
|
6
11
|
const claimNamesOf = (claims) => claims == null ? [] : Array.isArray(claims) ? claims : Object.keys(claims);
|
|
7
|
-
export const
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
},
|
|
28
|
-
scopes: [
|
|
29
|
-
'openid', 'profile', 'offline_access', PERMISSIONS_SCOPE, ORGANIZATIONS_SCOPE,
|
|
30
|
-
...cfg.customConfiguration?.scopes ?? []
|
|
31
|
-
],
|
|
32
|
-
discovery: {
|
|
33
|
-
...cfg.customConfiguration?.discovery,
|
|
34
|
-
...Object.fromEntries(Object.entries(cfg.discoveryUris ?? {}).map(([field, uri]) => [field, updateUri(uri)])),
|
|
35
|
-
},
|
|
36
|
-
features: {
|
|
37
|
-
...cfg.customConfiguration?.features,
|
|
38
|
-
devInteractions: { enabled: false }
|
|
39
|
-
// devInteractions: {
|
|
40
|
-
// enabled: (
|
|
41
|
-
// (context.cfg.debug.all && context.cfg.debug.oidc !== false)
|
|
42
|
-
// || context.cfg.debug.oidc
|
|
43
|
-
// ) && unsecure,
|
|
44
|
-
// ...cfg.customConfiguration?.features?.devInteractions,
|
|
45
|
-
// },
|
|
46
|
-
},
|
|
47
|
-
jwks: {
|
|
48
|
-
keys: [
|
|
49
|
-
await jose.exportJWK(await jose.importPKCS8(cfg.defaultKeys.RS256.pk, 'RS256', { extractable: true }))
|
|
50
|
-
]
|
|
12
|
+
export const makeOidcConfigUtils = (context) => {
|
|
13
|
+
/** Expands a `{{service-alias}}/path` URI against that registered service; any other URI is kept. */
|
|
14
|
+
const uriUpdater = (helper) => (uri) => {
|
|
15
|
+
if (uri.startsWith('{{')) {
|
|
16
|
+
const [host, ...parts] = uri.split(SEP);
|
|
17
|
+
const service = context.cfg.services[host.slice(2, -2)];
|
|
18
|
+
return helper.makeUrl(service, parts.join(SEP));
|
|
19
|
+
}
|
|
20
|
+
return uri;
|
|
21
|
+
};
|
|
22
|
+
const updateClient = (client) => {
|
|
23
|
+
if (client.client_secret == null) {
|
|
24
|
+
if (!context.cfg.debug.all && !context.cfg.debug.oidc) {
|
|
25
|
+
throw new SyntaxError('Client secret is required');
|
|
26
|
+
}
|
|
27
|
+
client.client_secret = hex.encode(randomBytes(32));
|
|
28
|
+
// The secret itself is never written to a log.
|
|
29
|
+
log.warn('Exceptionally insecure: a client secret was generated for an OIDC client (debug only)', {
|
|
30
|
+
clientId: client.client_id,
|
|
31
|
+
});
|
|
51
32
|
}
|
|
33
|
+
const helper = makeSecurityHelper(context);
|
|
34
|
+
const updateUri = uriUpdater(helper);
|
|
35
|
+
client.redirect_uris = client.redirect_uris?.map(updateUri) ?? [];
|
|
36
|
+
client.post_logout_redirect_uris = client.post_logout_redirect_uris?.map(updateUri) ?? [];
|
|
37
|
+
return client;
|
|
38
|
+
};
|
|
39
|
+
const combineConfig = async (_unsecure) => {
|
|
40
|
+
const cfg = context.cfg.oidc;
|
|
41
|
+
const updateUri = uriUpdater(makeSecurityHelper(context));
|
|
42
|
+
const configuration = {
|
|
43
|
+
...cfg.customConfiguration,
|
|
44
|
+
clients: [
|
|
45
|
+
...cfg.clients,
|
|
46
|
+
...(cfg.customConfiguration?.clients ?? [])
|
|
47
|
+
].map(client => updateClient(client)),
|
|
48
|
+
claims: {
|
|
49
|
+
email: ['email', 'email_verified', ...claimNamesOf(cfg.customConfiguration?.claims?.email)],
|
|
50
|
+
profile: [
|
|
51
|
+
'username', 'family_name', 'given_name', 'locale', 'name', 'nickname', 'preferred_username',
|
|
52
|
+
...claimNamesOf(cfg.customConfiguration?.claims?.profile)
|
|
53
|
+
],
|
|
54
|
+
// Inert unless the account service actually emits the claim (integrated IAM mode)
|
|
55
|
+
[PERMISSIONS_SCOPE]: [PERMISSIONS_CLAIM],
|
|
56
|
+
// Inert likewise — and a static scope, so only a client whose allowlist names it may ask
|
|
57
|
+
[ORGANIZATIONS_SCOPE]: [ORGANIZATIONS_CLAIM],
|
|
58
|
+
...cfg.customConfiguration?.claims,
|
|
59
|
+
},
|
|
60
|
+
scopes: [
|
|
61
|
+
'openid', 'profile', 'offline_access', PERMISSIONS_SCOPE, ORGANIZATIONS_SCOPE,
|
|
62
|
+
...cfg.customConfiguration?.scopes ?? []
|
|
63
|
+
],
|
|
64
|
+
discovery: {
|
|
65
|
+
...cfg.customConfiguration?.discovery,
|
|
66
|
+
...Object.fromEntries(Object.entries(cfg.discoveryUris ?? {}).map(([field, uri]) => [field, updateUri(uri)])),
|
|
67
|
+
},
|
|
68
|
+
features: {
|
|
69
|
+
...cfg.customConfiguration?.features,
|
|
70
|
+
devInteractions: { enabled: false }
|
|
71
|
+
// devInteractions: {
|
|
72
|
+
// enabled: (
|
|
73
|
+
// (context.cfg.debug.all && context.cfg.debug.oidc !== false)
|
|
74
|
+
// || context.cfg.debug.oidc
|
|
75
|
+
// ) && unsecure,
|
|
76
|
+
// ...cfg.customConfiguration?.features?.devInteractions,
|
|
77
|
+
// },
|
|
78
|
+
},
|
|
79
|
+
jwks: {
|
|
80
|
+
keys: [
|
|
81
|
+
await jose.exportJWK(await jose.importPKCS8(cfg.defaultKeys.RS256.pk, 'RS256', { extractable: true }))
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
return configuration;
|
|
52
86
|
};
|
|
53
|
-
return
|
|
87
|
+
return { combineConfig };
|
|
54
88
|
};
|
|
89
|
+
/** The configuration utils of a context — one per context. */
|
|
90
|
+
export const oidcConfigOf = memoHelper.oncePer(makeOidcConfigUtils);
|
|
55
91
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
package/build/utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,mBAAmB,mBAAmB,CAAA"}
|
package/build/utils/index.js
CHANGED
package/build/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/server-oidc-provider",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.50",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@owlmeans/dep-config": "workspace:*",
|
|
26
|
-
"@owlmeans/context": "^0.1.18-rc.
|
|
26
|
+
"@owlmeans/context": "^0.1.18-rc.34",
|
|
27
27
|
"@types/bun": "^1.4.2",
|
|
28
28
|
"@types/node": "^26.6.4",
|
|
29
29
|
"@types/oidc-provider": "9.12.1",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@noble/hashes": "^2.4.0",
|
|
38
|
-
"@owlmeans/config": "^0.1.18-rc.
|
|
39
|
-
"@owlmeans/context": "^0.1.18-rc.
|
|
40
|
-
"@owlmeans/entrypoint": "^0.1.18-rc.
|
|
41
|
-
"@owlmeans/log": "^0.1.18-rc.
|
|
42
|
-
"@owlmeans/oidc": "^0.1.18-rc.
|
|
43
|
-
"@owlmeans/route": "^0.1.18-rc.
|
|
44
|
-
"@owlmeans/server-api": "^0.1.18-rc.
|
|
45
|
-
"@owlmeans/server-context": "^0.1.18-rc.
|
|
38
|
+
"@owlmeans/config": "^0.1.18-rc.44",
|
|
39
|
+
"@owlmeans/context": "^0.1.18-rc.34",
|
|
40
|
+
"@owlmeans/entrypoint": "^0.1.18-rc.41",
|
|
41
|
+
"@owlmeans/log": "^0.1.18-rc.2",
|
|
42
|
+
"@owlmeans/oidc": "^0.1.18-rc.55",
|
|
43
|
+
"@owlmeans/route": "^0.1.18-rc.35",
|
|
44
|
+
"@owlmeans/server-api": "^0.1.18-rc.51",
|
|
45
|
+
"@owlmeans/server-context": "^0.1.18-rc.43",
|
|
46
46
|
"@scure/base": "^2.4.0",
|
|
47
47
|
"jose": "6.2.12",
|
|
48
48
|
"oidc-provider": "9.12.2"
|
package/src/iam.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ResponseType } from 'oidc-provider'
|
|
2
|
-
import type { OidcClientMetadata, OidcRegisteredClient } from './types.js'
|
|
2
|
+
import type { OidcClientMetadata, OidcRegisteredClient, ToClientMetadata } from './types.js'
|
|
3
3
|
|
|
4
4
|
/** Convert an OidcRegisteredClient to the oidc-provider ClientMetadata shape. */
|
|
5
|
-
export const toClientMetadata = (client: OidcRegisteredClient): OidcClientMetadata => ({
|
|
5
|
+
export const toClientMetadata: ToClientMetadata = (client: OidcRegisteredClient): OidcClientMetadata => ({
|
|
6
6
|
client_id: client.clientId,
|
|
7
7
|
client_secret: client.secret,
|
|
8
8
|
redirect_uris: client.redirectUris ?? [],
|
package/src/middleware.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { ApiServer } from '@owlmeans/server-api'
|
|
|
5
5
|
import { DEFAULT_ALIAS } from './consts.js'
|
|
6
6
|
import type { Config, Context, OidcProviderService } from './types.js'
|
|
7
7
|
|
|
8
|
-
export const createOidcProviderMiddleware = (web: string = WEB_ALIAS, oidc = DEFAULT_ALIAS) => {
|
|
8
|
+
export const createOidcProviderMiddleware = (web: string = WEB_ALIAS, oidc: string = DEFAULT_ALIAS): Middleware => {
|
|
9
9
|
const middleware: Middleware = {
|
|
10
10
|
type: MiddlewareType.Context,
|
|
11
11
|
stage: MiddlewareStage.Loading,
|
package/src/service.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type { BasicRoute } from '@owlmeans/route'
|
|
|
10
10
|
import type { CommonEntrypoint } from '@owlmeans/entrypoint'
|
|
11
11
|
import { PARAM, SEP } from '@owlmeans/route'
|
|
12
12
|
import { makeSecurityHelper } from '@owlmeans/config'
|
|
13
|
-
import {
|
|
13
|
+
import { oidcConfigOf } from './utils/config.js'
|
|
14
14
|
import { makeInteractionPolicy } from './utils/policy.js'
|
|
15
15
|
|
|
16
16
|
const log = logger('server-oidc-provider')
|
|
@@ -57,7 +57,7 @@ export const createOidcProviderService = (alias: string = DEFAULT_ALIAS): OidcPr
|
|
|
57
57
|
const unsecure = context.cfg.security?.unsecure === false ? false : !url.startsWith('https')
|
|
58
58
|
|
|
59
59
|
const oidc = new Provider(url, {
|
|
60
|
-
...await combineConfig(
|
|
60
|
+
...await oidcConfigOf(context).combineConfig(unsecure),
|
|
61
61
|
|
|
62
62
|
adapter: cfg.adapterService != null
|
|
63
63
|
? name => context.service<OidcAdapterService>(cfg.adapterService!).instance(name)
|
package/src/types.ts
CHANGED
|
@@ -3,7 +3,6 @@ import type { OidcSharedConfig } from '@owlmeans/oidc'
|
|
|
3
3
|
import type { ApiServer, ApiServerAppend } from '@owlmeans/server-api'
|
|
4
4
|
import type { ServerConfig, ServerContext } from '@owlmeans/server-context'
|
|
5
5
|
import type { Account, Adapter, ClientMetadata, Configuration, Interaction, Provider } from 'oidc-provider'
|
|
6
|
-
import { toClientMetadata } from './iam.js'
|
|
7
6
|
|
|
8
7
|
export interface OidcProviderService extends InitializedService {
|
|
9
8
|
oidc: Provider
|
|
@@ -93,12 +92,17 @@ export interface OidcRegisteredClient {
|
|
|
93
92
|
}
|
|
94
93
|
|
|
95
94
|
/** Full oidc-provider ClientMetadata with our entity extension. */
|
|
96
|
-
export
|
|
95
|
+
export interface OidcClientMetadata extends ClientMetadata { entityId?: string; owlEntityId?: string }
|
|
96
|
+
|
|
97
|
+
/** Converts a stored client record to oidc-provider ClientMetadata. */
|
|
98
|
+
export interface ToClientMetadata {
|
|
99
|
+
(client: OidcRegisteredClient): OidcClientMetadata
|
|
100
|
+
}
|
|
97
101
|
|
|
98
102
|
/** Extension seam for IAM integration into the OIDC provider — Phase 2 fills this */
|
|
99
103
|
export interface OidcProviderIamExtension {
|
|
100
104
|
/** Convert a stored client record to oidc-provider ClientMetadata */
|
|
101
|
-
toClientMetadata:
|
|
105
|
+
toClientMetadata: ToClientMetadata
|
|
102
106
|
/** Type of a stored client record */
|
|
103
107
|
OidcRegisteredClient: OidcRegisteredClient
|
|
104
108
|
/** Extended metadata type */
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { OidcCustomConfiguration } from '../../types.js'
|
|
2
|
+
|
|
3
|
+
/** The provider configuration one context's settings resolve to. */
|
|
4
|
+
export interface OidcConfigUtils {
|
|
5
|
+
/**
|
|
6
|
+
* The deployment's configuration merged over this package's defaults: its clients with their
|
|
7
|
+
* `{{service-alias}}` URIs expanded (and, in debug only, a generated secret), the claims behind
|
|
8
|
+
* every scope, the discovery extras and the signing key.
|
|
9
|
+
*/
|
|
10
|
+
combineConfig: (unsecure: boolean) => Promise<OidcCustomConfiguration>
|
|
11
|
+
}
|
package/src/utils/config.ts
CHANGED
|
@@ -1,60 +1,108 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { randomBytes } from '@noble/hashes/utils.js'
|
|
2
|
+
import { hex } from '@scure/base'
|
|
3
|
+
import type { ClientMetadata } from 'oidc-provider'
|
|
4
|
+
import type { Config, Context, OidcCustomConfiguration } from '../types.js'
|
|
3
5
|
import { ORGANIZATIONS_CLAIM, ORGANIZATIONS_SCOPE, PERMISSIONS_CLAIM, PERMISSIONS_SCOPE } from '@owlmeans/oidc'
|
|
4
6
|
import { makeSecurityHelper } from '@owlmeans/config'
|
|
7
|
+
import type { SecurityHelper } from '@owlmeans/config'
|
|
8
|
+
import { memoHelper } from '@owlmeans/context'
|
|
9
|
+
import { SEP } from '@owlmeans/route'
|
|
10
|
+
import { logger } from '@owlmeans/log'
|
|
5
11
|
import * as jose from 'jose'
|
|
12
|
+
import type { OidcConfigUtils } from './config/types.js'
|
|
13
|
+
|
|
14
|
+
const log = logger('server-oidc-provider')
|
|
6
15
|
|
|
7
16
|
/** A claim list is an array, or (as the provider's types also allow) a record keyed by claim name. */
|
|
8
17
|
const claimNamesOf = (claims: readonly string[] | Readonly<Record<string, null>> | null | undefined): readonly string[] =>
|
|
9
18
|
claims == null ? [] : Array.isArray(claims) ? claims : Object.keys(claims)
|
|
10
19
|
|
|
11
|
-
export const
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
export const makeOidcConfigUtils = (context: Context): OidcConfigUtils => {
|
|
21
|
+
/** Expands a `{{service-alias}}/path` URI against that registered service; any other URI is kept. */
|
|
22
|
+
const uriUpdater = (helper: SecurityHelper): ((uri: string) => string) => (uri: string): string => {
|
|
23
|
+
if (uri.startsWith('{{')) {
|
|
24
|
+
const [host, ...parts] = uri.split(SEP)
|
|
25
|
+
|
|
26
|
+
const service = context.cfg.services[host.slice(2, -2)]
|
|
27
|
+
return helper.makeUrl(service, parts.join(SEP))
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return uri
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const updateClient = (client: ClientMetadata): ClientMetadata => {
|
|
34
|
+
if (client.client_secret == null) {
|
|
35
|
+
if (!context.cfg.debug.all && !context.cfg.debug.oidc) {
|
|
36
|
+
throw new SyntaxError('Client secret is required')
|
|
37
|
+
}
|
|
38
|
+
client.client_secret = hex.encode(randomBytes(32))
|
|
39
|
+
// The secret itself is never written to a log.
|
|
40
|
+
log.warn('Exceptionally insecure: a client secret was generated for an OIDC client (debug only)', {
|
|
41
|
+
clientId: client.client_id,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const helper = makeSecurityHelper<Config, Context>(context)
|
|
46
|
+
const updateUri = uriUpdater(helper)
|
|
47
|
+
client.redirect_uris = client.redirect_uris?.map(updateUri) ?? []
|
|
48
|
+
client.post_logout_redirect_uris = client.post_logout_redirect_uris?.map(updateUri) ?? []
|
|
49
|
+
|
|
50
|
+
return client
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const combineConfig = async (_unsecure: boolean): Promise<OidcCustomConfiguration> => {
|
|
54
|
+
const cfg = context.cfg.oidc
|
|
55
|
+
const updateUri = uriUpdater(makeSecurityHelper(context))
|
|
56
|
+
|
|
57
|
+
const configuration: OidcCustomConfiguration = {
|
|
58
|
+
...cfg.customConfiguration,
|
|
59
|
+
clients: [
|
|
60
|
+
...cfg.clients,
|
|
61
|
+
...(cfg.customConfiguration?.clients ?? [])
|
|
62
|
+
].map(client => updateClient(client)),
|
|
63
|
+
claims: {
|
|
64
|
+
email: ['email', 'email_verified', ...claimNamesOf(cfg.customConfiguration?.claims?.email)],
|
|
65
|
+
profile: [
|
|
66
|
+
'username', 'family_name', 'given_name', 'locale', 'name', 'nickname', 'preferred_username',
|
|
67
|
+
...claimNamesOf(cfg.customConfiguration?.claims?.profile)
|
|
68
|
+
],
|
|
69
|
+
// Inert unless the account service actually emits the claim (integrated IAM mode)
|
|
70
|
+
[PERMISSIONS_SCOPE]: [PERMISSIONS_CLAIM],
|
|
71
|
+
// Inert likewise — and a static scope, so only a client whose allowlist names it may ask
|
|
72
|
+
[ORGANIZATIONS_SCOPE]: [ORGANIZATIONS_CLAIM],
|
|
73
|
+
...cfg.customConfiguration?.claims,
|
|
74
|
+
},
|
|
75
|
+
scopes: [
|
|
76
|
+
'openid', 'profile', 'offline_access', PERMISSIONS_SCOPE, ORGANIZATIONS_SCOPE,
|
|
77
|
+
...cfg.customConfiguration?.scopes ?? []
|
|
26
78
|
],
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// || context.cfg.debug.oidc
|
|
48
|
-
// ) && unsecure,
|
|
49
|
-
// ...cfg.customConfiguration?.features?.devInteractions,
|
|
50
|
-
// },
|
|
51
|
-
},
|
|
52
|
-
jwks: {
|
|
53
|
-
keys: [
|
|
54
|
-
await jose.exportJWK(await jose.importPKCS8(cfg.defaultKeys.RS256.pk, 'RS256', { extractable: true }))
|
|
55
|
-
]
|
|
79
|
+
discovery: {
|
|
80
|
+
...cfg.customConfiguration?.discovery,
|
|
81
|
+
...Object.fromEntries(Object.entries(cfg.discoveryUris ?? {}).map(([field, uri]) => [field, updateUri(uri)])),
|
|
82
|
+
},
|
|
83
|
+
features: {
|
|
84
|
+
...cfg.customConfiguration?.features,
|
|
85
|
+
devInteractions: { enabled: false }
|
|
86
|
+
// devInteractions: {
|
|
87
|
+
// enabled: (
|
|
88
|
+
// (context.cfg.debug.all && context.cfg.debug.oidc !== false)
|
|
89
|
+
// || context.cfg.debug.oidc
|
|
90
|
+
// ) && unsecure,
|
|
91
|
+
// ...cfg.customConfiguration?.features?.devInteractions,
|
|
92
|
+
// },
|
|
93
|
+
},
|
|
94
|
+
jwks: {
|
|
95
|
+
keys: [
|
|
96
|
+
await jose.exportJWK(await jose.importPKCS8(cfg.defaultKeys.RS256.pk, 'RS256', { extractable: true }))
|
|
97
|
+
]
|
|
98
|
+
}
|
|
56
99
|
}
|
|
100
|
+
|
|
101
|
+
return configuration
|
|
57
102
|
}
|
|
58
103
|
|
|
59
|
-
return
|
|
104
|
+
return { combineConfig }
|
|
60
105
|
}
|
|
106
|
+
|
|
107
|
+
/** The configuration utils of a context — one per context. */
|
|
108
|
+
export const oidcConfigOf = memoHelper.oncePer(makeOidcConfigUtils)
|
package/src/utils/index.ts
CHANGED
package/tests/config.spec.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { BasicContext } from '@owlmeans/context'
|
|
|
5
5
|
import {
|
|
6
6
|
IAM_API_METADATA, ORGANIZATIONS_CLAIM, ORGANIZATIONS_SCOPE, PERMISSIONS_CLAIM, PERMISSIONS_SCOPE,
|
|
7
7
|
} from '@owlmeans/oidc'
|
|
8
|
-
import {
|
|
8
|
+
import { makeOidcConfigUtils } from '../src/utils/config.js'
|
|
9
9
|
import type { Config } from '../src/types.js'
|
|
10
10
|
|
|
11
11
|
const { privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 })
|
|
@@ -35,7 +35,7 @@ const makeTestContext = (oidc: Partial<Config['oidc']> = {}) => {
|
|
|
35
35
|
describe('combineConfig (jose v6 extractable key)', () => {
|
|
36
36
|
it('produces a JWKS with an RS256 key', async () => {
|
|
37
37
|
const context = makeTestContext()
|
|
38
|
-
const config = await
|
|
38
|
+
const config = await makeOidcConfigUtils(context as any).combineConfig(true)
|
|
39
39
|
|
|
40
40
|
expect(config.jwks).toBeDefined()
|
|
41
41
|
expect(Array.isArray(config.jwks?.keys)).toBe(true)
|
|
@@ -47,7 +47,7 @@ describe('combineConfig (jose v6 extractable key)', () => {
|
|
|
47
47
|
|
|
48
48
|
describe('combineConfig — scopes and the claims behind them', () => {
|
|
49
49
|
it('maps each integrated-IAM scope to its own claim', async () => {
|
|
50
|
-
const config = await
|
|
50
|
+
const config = await makeOidcConfigUtils(makeTestContext() as any).combineConfig(true)
|
|
51
51
|
|
|
52
52
|
expect(config.claims?.[PERMISSIONS_SCOPE]).toEqual([PERMISSIONS_CLAIM])
|
|
53
53
|
expect(config.claims?.[ORGANIZATIONS_SCOPE]).toEqual([ORGANIZATIONS_CLAIM])
|
|
@@ -58,19 +58,19 @@ describe('combineConfig — scopes and the claims behind them', () => {
|
|
|
58
58
|
|
|
59
59
|
describe('combineConfig — the discovery document', () => {
|
|
60
60
|
it('expands a service-relative field against the registered service', async () => {
|
|
61
|
-
const config = await
|
|
61
|
+
const config = await makeOidcConfigUtils(makeTestContext({
|
|
62
62
|
discoveryUris: { [IAM_API_METADATA]: '{{iam-api}}/iam/api/runtime' },
|
|
63
|
-
}) as any
|
|
63
|
+
}) as any).combineConfig(true)
|
|
64
64
|
|
|
65
65
|
expect((config.discovery as Record<string, unknown>)[IAM_API_METADATA])
|
|
66
66
|
.toBe('https://iam.example.test/iam/api/runtime')
|
|
67
67
|
})
|
|
68
68
|
|
|
69
69
|
it('keeps an absolute field and the custom discovery fields as given', async () => {
|
|
70
|
-
const config = await
|
|
70
|
+
const config = await makeOidcConfigUtils(makeTestContext({
|
|
71
71
|
discoveryUris: { [IAM_API_METADATA]: 'https://elsewhere.example.test/runtime' },
|
|
72
72
|
customConfiguration: { discovery: { service_documentation: 'https://docs.example.test' } },
|
|
73
|
-
}) as any
|
|
73
|
+
}) as any).combineConfig(true)
|
|
74
74
|
|
|
75
75
|
expect(config.discovery).toEqual({
|
|
76
76
|
service_documentation: 'https://docs.example.test',
|
|
@@ -83,9 +83,9 @@ describe('combineConfig — pairwise subjects pass through', () => {
|
|
|
83
83
|
it('keeps the subject options of the custom configuration', async () => {
|
|
84
84
|
const pairwiseIdentifier = async (_: unknown, accountId: string) => `pairwise:${accountId}`
|
|
85
85
|
const sectorIdentifierUriValidate = () => false
|
|
86
|
-
const config = await
|
|
86
|
+
const config = await makeOidcConfigUtils(makeTestContext({
|
|
87
87
|
customConfiguration: { subjectTypes: ['pairwise'], pairwiseIdentifier, sectorIdentifierUriValidate },
|
|
88
|
-
}) as any
|
|
88
|
+
}) as any).combineConfig(true)
|
|
89
89
|
|
|
90
90
|
expect(config.subjectTypes).toEqual(['pairwise'])
|
|
91
91
|
expect(config.pairwiseIdentifier).toBe(pairwiseIdentifier)
|
package/tests/pairwise.spec.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { sha256 } from '@noble/hashes/sha2.js'
|
|
|
9
9
|
import { base58 } from '@scure/base'
|
|
10
10
|
import { AppType, makeBasicContext } from '@owlmeans/context'
|
|
11
11
|
import { ORGANIZATIONS_CLAIM, ORGANIZATIONS_SCOPE, PERMISSIONS_CLAIM, PERMISSIONS_SCOPE } from '@owlmeans/oidc'
|
|
12
|
-
import {
|
|
12
|
+
import { makeOidcConfigUtils } from '../src/utils/config.js'
|
|
13
13
|
import { makeInteractionPolicy } from '../src/utils/policy.js'
|
|
14
14
|
import type { Config } from '../src/types.js'
|
|
15
15
|
|
|
@@ -80,7 +80,7 @@ const start = async () => {
|
|
|
80
80
|
|
|
81
81
|
const loaded: string[] = []
|
|
82
82
|
const provider = new Provider(base, {
|
|
83
|
-
...await
|
|
83
|
+
...await makeOidcConfigUtils(context as any).combineConfig(true),
|
|
84
84
|
findAccount: async (_, id) => {
|
|
85
85
|
loaded.push(id)
|
|
86
86
|
return {
|
package/build/utils/client.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { ClientMetadata } from 'oidc-provider';
|
|
2
|
-
import type { Context } from '../types.js';
|
|
3
|
-
import type { SecurityHelper } from '@owlmeans/config';
|
|
4
|
-
export declare const updateClient: (context: Context, client: ClientMetadata) => ClientMetadata;
|
|
5
|
-
/** Expands a `{{service-alias}}/path` URI against that registered service; any other URI is kept. */
|
|
6
|
-
export declare const makeUriUpdater: (context: Context, helper: SecurityHelper) => (uri: string) => string;
|
|
7
|
-
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/utils/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,KAAK,EAAU,OAAO,EAAE,MAAM,aAAa,CAAA;AAElD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAMtD,eAAO,MAAM,YAAY,YAAa,OAAO,UAAU,cAAc,KAAG,cAkBvE,CAAA;AAED,qGAAqG;AACrG,eAAO,MAAM,cAAc,YAAa,OAAO,UAAU,cAAc,WAAW,MAAM,KAAG,MAS1F,CAAA"}
|
package/build/utils/client.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from '@noble/hashes/utils.js';
|
|
2
|
-
import { hex } from '@scure/base';
|
|
3
|
-
import { makeSecurityHelper } from '@owlmeans/config';
|
|
4
|
-
import { SEP } from '@owlmeans/route';
|
|
5
|
-
import { logger } from '@owlmeans/log';
|
|
6
|
-
const log = logger('server-oidc-provider');
|
|
7
|
-
export const updateClient = (context, client) => {
|
|
8
|
-
if (client.client_secret == null) {
|
|
9
|
-
if (!context.cfg.debug.all && !context.cfg.debug.oidc) {
|
|
10
|
-
throw new SyntaxError('Client secret is required');
|
|
11
|
-
}
|
|
12
|
-
client.client_secret = hex.encode(randomBytes(32));
|
|
13
|
-
// The secret itself is never written to a log.
|
|
14
|
-
log.warn('Exceptionally insecure: a client secret was generated for an OIDC client (debug only)', {
|
|
15
|
-
clientId: client.client_id,
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
const helper = makeSecurityHelper(context);
|
|
19
|
-
const updateUri = makeUriUpdater(context, helper);
|
|
20
|
-
client.redirect_uris = client.redirect_uris?.map(updateUri) ?? [];
|
|
21
|
-
client.post_logout_redirect_uris = client.post_logout_redirect_uris?.map(updateUri) ?? [];
|
|
22
|
-
return client;
|
|
23
|
-
};
|
|
24
|
-
/** Expands a `{{service-alias}}/path` URI against that registered service; any other URI is kept. */
|
|
25
|
-
export const makeUriUpdater = (context, helper) => (uri) => {
|
|
26
|
-
if (uri.startsWith('{{')) {
|
|
27
|
-
const [host, ...parts] = uri.split(SEP);
|
|
28
|
-
const service = context.cfg.services[host.slice(2, -2)];
|
|
29
|
-
return helper.makeUrl(service, parts.join(SEP));
|
|
30
|
-
}
|
|
31
|
-
return uri;
|
|
32
|
-
};
|
|
33
|
-
//# sourceMappingURL=client.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/utils/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAGjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAErD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEtC,MAAM,GAAG,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAA;AAE1C,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAgB,EAAE,MAAsB,EAAkB,EAAE;IACvF,IAAI,MAAM,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACtD,MAAM,IAAI,WAAW,CAAC,2BAA2B,CAAC,CAAA;QACpD,CAAC;QACD,MAAM,CAAC,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAA;QAClD,+CAA+C;QAC/C,GAAG,CAAC,IAAI,CAAC,uFAAuF,EAAE;YAChG,QAAQ,EAAE,MAAM,CAAC,SAAS;SAC3B,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,kBAAkB,CAAkB,OAAO,CAAC,CAAA;IAC3D,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IACjD,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,EAAE,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAA;IACjE,MAAM,CAAC,yBAAyB,GAAG,MAAM,CAAC,yBAAyB,EAAE,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAA;IAEzF,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,qGAAqG;AACrG,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAgB,EAAE,MAAsB,EAAE,EAAE,CAAC,CAAC,GAAW,EAAU,EAAE;IAClG,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAEvC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QACvD,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IACjD,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA"}
|
package/src/utils/client.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from '@noble/hashes/utils.js'
|
|
2
|
-
import { hex } from '@scure/base'
|
|
3
|
-
import type { ClientMetadata } from 'oidc-provider'
|
|
4
|
-
import type { Config, Context } from '../types.js'
|
|
5
|
-
import { makeSecurityHelper } from '@owlmeans/config'
|
|
6
|
-
import type { SecurityHelper } from '@owlmeans/config'
|
|
7
|
-
import { SEP } from '@owlmeans/route'
|
|
8
|
-
import { logger } from '@owlmeans/log'
|
|
9
|
-
|
|
10
|
-
const log = logger('server-oidc-provider')
|
|
11
|
-
|
|
12
|
-
export const updateClient = (context: Context, client: ClientMetadata): ClientMetadata => {
|
|
13
|
-
if (client.client_secret == null) {
|
|
14
|
-
if (!context.cfg.debug.all && !context.cfg.debug.oidc) {
|
|
15
|
-
throw new SyntaxError('Client secret is required')
|
|
16
|
-
}
|
|
17
|
-
client.client_secret = hex.encode(randomBytes(32))
|
|
18
|
-
// The secret itself is never written to a log.
|
|
19
|
-
log.warn('Exceptionally insecure: a client secret was generated for an OIDC client (debug only)', {
|
|
20
|
-
clientId: client.client_id,
|
|
21
|
-
})
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const helper = makeSecurityHelper<Config, Context>(context)
|
|
25
|
-
const updateUri = makeUriUpdater(context, helper)
|
|
26
|
-
client.redirect_uris = client.redirect_uris?.map(updateUri) ?? []
|
|
27
|
-
client.post_logout_redirect_uris = client.post_logout_redirect_uris?.map(updateUri) ?? []
|
|
28
|
-
|
|
29
|
-
return client
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Expands a `{{service-alias}}/path` URI against that registered service; any other URI is kept. */
|
|
33
|
-
export const makeUriUpdater = (context: Context, helper: SecurityHelper) => (uri: string): string => {
|
|
34
|
-
if (uri.startsWith('{{')) {
|
|
35
|
-
const [host, ...parts] = uri.split(SEP)
|
|
36
|
-
|
|
37
|
-
const service = context.cfg.services[host.slice(2, -2)]
|
|
38
|
-
return helper.makeUrl(service, parts.join(SEP))
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return uri
|
|
42
|
-
}
|