@owlmeans/server-oidc-provider 0.1.18-rc.3 → 0.1.18-rc.31

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 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
17
+ bun add @owlmeans/server-oidc-provider@^0.1.18-rc.31
18
18
  ```
19
19
 
20
20
  ## Usage
@@ -59,7 +59,7 @@ Returns middleware that mounts the OIDC authorize/token/userinfo/jwks endpoints
59
59
 
60
60
  ## Related Packages
61
61
 
62
- - [`@owlmeans/oidc`](../oidc) — shared protocol constants and module declarations
62
+ - [`@owlmeans/oidc`](../oidc) — shared protocol constants and entrypoint declarations
63
63
  - [`@owlmeans/server-oidc-rp`](../server-oidc-rp) — relying-party counterpart for consuming external IdPs
64
64
  - [`@owlmeans/server-api`](../server-api) — the underlying server API the middleware mounts onto
65
65
  - [`@owlmeans/web-oidc-provider`](../web-oidc-provider) — browser UI for the provider's interaction screens
@@ -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
75
+ npx @owlmeans/agent-skills@^0.1.18-rc.27
76
76
  ```
77
77
 
78
78
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/server-oidc-provider",
4
- "version": "0.1.18-rc.0",
5
- "generatedAt": "2026-08-16T22:20:50.512Z",
4
+ "version": "0.1.18-rc.31",
5
+ "generatedAt": "2026-09-15T13:19:14.360Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: server-oidc-provider
3
- description: How to use @owlmeans/server-oidc-provider — embedded OIDC identity provider built on the oidc-provider library. Auto-invoked when serving OIDC endpoints from your own service.
3
+ description: How to use @owlmeans/server-oidc-provider — the embedded OIDC identity provider on top of the oidc-provider library — service wiring, the account and adapter seams, the interaction URL, how scopes are derived from claims, and the response headers an authorization endpoint has to correct. Auto-invoked when serving OIDC endpoints from your own service.
4
4
  user-invocable: false
5
5
  ---
6
6
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
@@ -8,66 +8,123 @@ 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.0"` in `dependencies`
12
- **Runtime deps:** `oidc-provider@9.8.4` (exact), `jose@6.2.3` (exact)
11
+ **Install:** `"@owlmeans/server-oidc-provider": "^0.1.18-rc.31"` in `dependencies`
12
+ **Runtime deps:** `oidc-provider@9.11.1` (exact), `jose@6.2.5` (exact), `@types/oidc-provider@9.5.0`
13
+
14
+ Use this only when your service **is** the identity provider. For consuming someone else's issuer,
15
+ use `@owlmeans/server-oidc-rp`.
13
16
 
14
17
  ## Key Exports
15
18
 
16
19
  | Export | Description |
17
20
  |--------|-------------|
18
- | `createOidcProviderService(alias?)` | Factory for the embedded OIDC provider service |
19
- | `appendOidcProviderService<C,T>(ctx, alias?)` | Register the provider service on a context |
20
- | Constants | `DEFAULT_ALIAS`, `OIDC_ACCOUNT_SERVICE` |
21
- | Types | `OidcProviderService`, `OidcAccountService`, `OidcAdapterService`, `Config`, `Context` |
22
-
23
- ## Usage
24
-
25
- Use this only when your service IS the identity provider (e.g. self-hosted Keycloak alternative). For consuming an external IdP, use `@owlmeans/server-oidc-rp`.
21
+ | `createOidcProviderService(alias?)` | The provider service factory |
22
+ | `appendOidcProviderService<C,T>(ctx, alias?)` | Registers it on a context |
23
+ | `createOidcProviderMiddleware(webAlias?, oidcAlias?)` | Loading-stage middleware that mounts the provider on the API server exactly once. Register it, or nothing is ever mounted |
24
+ | `OidcProviderService` | `instance()`, `update(api)`, `getInteraction(id)` and the live `oidc` provider |
25
+ | `OidcAccountService` | The account seam: `loadById(ctx, id, { clientId? })` — what `findAccount` delegates to |
26
+ | `OidcAdapterService` | The storage seam: `instance(name)` returns an `oidc-provider` `Adapter` |
27
+ | `OIDC_ACCOUNT_SERVICE`, `DEFAULT_ALIAS` | The default account-service alias and the default provider alias |
28
+ | `OidcConfig`, `OidcConfigAppend` | The `cfg.oidc` shape this package reads |
29
+ | `OidcAccountParams` | `{ clientId? }` — lets the account service scope its claims per client |
30
+ | `toClientMetadata(client)` | Maps a stored `OidcRegisteredClient` to `oidc-provider` `ClientMetadata` |
31
+ | `OidcRegisteredClient`, `OidcClientMetadata` | The stored-client shape `toClientMetadata` takes, and the `oidc-provider` metadata shape it returns, carrying `owlEntityId` |
32
+ | `Config`, `Context` | `ServerConfig`/`ServerContext` with `cfg.oidc` and the `debug.oidc` / `debug.oidcServer` / `debug.oidcData` switches |
33
+
34
+ ## Wiring
26
35
 
27
36
  ```typescript
28
- import { appendOidcProviderService } from '@owlmeans/server-oidc-provider'
37
+ import { appendOidcProviderService, createOidcProviderMiddleware } from '@owlmeans/server-oidc-provider'
38
+
29
39
  appendOidcProviderService<C, T>(context)
40
+ context.registerMiddleware(createOidcProviderMiddleware())
30
41
  ```
31
42
 
32
- The service mounts the oidc-provider Koa app onto Fastify via `api.server.use(base, oidc.callback())`. It wires `findAccount`, `interactions.url`, the JWKS, and optional adapter.
43
+ `cfg.oidc` supplies `clients` (`ClientMetadata[]`), `defaultKeys.RS256.pk` (a PKCS#8 PEM), and
44
+ optionally `basePath` (default `oidc`), `authService` (whose registered route the issuer is built
45
+ from — defaults to this service), `behindProxy`, `accountService`, `adapterService` and
46
+ `customConfiguration` (merged over the defaults below). The shape also declares `frontBase`, which
47
+ this package reads nowhere — setting it configures nothing.
33
48
 
34
- ## Building the interaction URL (server context, frontend route)
49
+ A client's `redirect_uris` and `post_logout_redirect_uris` may be written as `{{service-alias}}/path`
50
+ and are expanded against that registered service's host. A client with no `client_secret` is refused
51
+ unless a debug flag is on, in which case one is generated and printed.
52
+
53
+ ## Building the interaction URL
35
54
 
36
55
  `interactions.url` must return the fully-qualified address of the `INTERACTION` screen, which is a
37
- **frontend** route resolved from a **server** context. `call()` does not exist there — it is attached
38
- only by `@owlmeans/client-entrypoint` — so the URL is assembled the way `urlCall` does it in the
39
- browser: resolve the route, substitute the `INTERACTION_UID` path param, then `makeSecurityHelper().makeUrl(route, path)`
40
- so the frontend service's host and base are applied. Pass the entrypoint's own `getPath()` as the
41
- path and let `makeUrl` supply the base — do not prepend it twice.
56
+ **frontend** route resolved from a **server** context. `url()` does not exist there — that helper is
57
+ attached only by `@owlmeans/client-entrypoint` — so the URL is assembled the way the browser's own
58
+ `url()` does it: take the entrypoint's `path()`, substitute the `INTERACTION_UID` path param, then
59
+ `makeSecurityHelper().makeUrl(entry.address(), path)`. `address()` is the address the entrypoint
60
+ answers on — the frontend service's, not this one's — so the base comes from it and must not be
61
+ prepended a second time.
42
62
 
43
63
  ## Scopes are derived from `claims`
44
64
 
45
- `oidc-provider` adds every key of the `claims` configuration to the supported-scope set
46
- (`collectScopes`). Declaring `claims.email` therefore makes `email` a **static** scope, and static
47
- scopes are checked against each client's own `scope` allowlist: a client that omits one fails the
48
- whole authorization request with `invalid_scope`. Whatever provisions clients for this provider must
49
- allow every scope the RP requests (`OIDC_RP_BASE_SCOPES`), and the account service must emit the
50
- matching claims — a granted scope with no claim behind it is silently empty.
51
-
52
- ## oidc-provider v9 notes (important)
53
-
54
- - **Provider is a Koa app instance.** `oidc.use()` callbacks where the work happens *after* `await next()` will **not** fire once a route is matched — Koa's downstream does not continue past matched routes in v9. Move post-response header work (e.g. CSP rewrites) to a **Fastify `onSend`/`preHandler` hook** scoped to the OIDC base path.
55
- - **`enableHttpPostMethods`** defaults `false` — set it in the Provider config if your interaction UI POSTs to the authorization/end-session endpoints.
56
- - **DPoP is enabled by default.** Add `features: { dPoP: { enabled: false } }` if RP clients do not send DPoP proofs.
57
- - **Cookie `sameSite` defaults to `lax`** (was `none`). Adjust `cookies.*.sameSite` if the interaction UI is on a different subdomain.
58
- - **JWKS `kid` must be unique.** Every key in `jwks.keys` needs a distinct `kid`.
59
- - **Node 22+** required.
60
-
61
- ## jose v6 notes
62
-
63
- `importPKCS8` now returns a **non-extractable `CryptoKey`** by default. Pass `{ extractable: true }` so `exportJWK` succeeds:
65
+ `oidc-provider` adds every key of the `claims` configuration to the supported-scope set. Declaring
66
+ `claims.email` therefore makes `email` a **static** scope, and static scopes are checked against each
67
+ client's own `scope` allowlist: a client that omits one fails the whole authorization request with
68
+ `invalid_scope`. Whatever provisions clients for this provider must allow every scope the RP requests
69
+ (`OIDC_RP_BASE_SCOPES`), and the account service must emit the matching claims — a granted scope with
70
+ no claim behind it is silently empty.
71
+
72
+ The defaults this package sets: `claims` covers `email` (`email`, `email_verified`), `profile` (the
73
+ standard set) and `PERMISSIONS_SCOPE` → `PERMISSIONS_CLAIM`, which stays inert unless the account
74
+ service actually emits it; `scopes` is `openid profile offline_access permissions`;
75
+ `features.devInteractions` is off. Anything under `cfg.oidc.customConfiguration` merges over these.
76
+
77
+ ## oidc-provider v9 configuration
78
+
79
+ - **The provider is a Koa app**, and `Provider#use(fn)` splices `fn` **ahead of** the provider's own
80
+ router, so a middleware registered that way runs before routing and resumes after `await next()`.
81
+ The header corrections below are still mounted on the API server ahead of `oidc.callback()`, for
82
+ the reason given there.
83
+ - **`enableHttpPostMethods` is `false`.** Set it only together with `cookies.long.sameSite: 'none'` —
84
+ the configuration check throws `TypeError: HTTP POST Method support requires that
85
+ cookies.long.sameSite is set to none` otherwise, at construction time.
86
+ - **DPoP is enabled.** Pass `features: { dPoP: { enabled: false } }` when the clients send no DPoP
87
+ proofs.
88
+ - **Cookie `sameSite` is `lax`** for both `cookies.long` and `cookies.short`. Revisit it when the
89
+ interaction UI lives on another subdomain.
90
+ - **Every key in `jwks.keys` needs a distinct `kid`.**
91
+ - There is no `provider.Account` getter — accounts come from the `findAccount` callback, which this
92
+ package points at `OidcAccountService`.
93
+ - Outbound HTTP goes through the `fetch` configuration option, which mirrors the fetch API.
94
+
95
+ ## jose v6 key import
96
+
97
+ `importPKCS8` returns a **non-extractable** `CryptoKey` for a private key. Pass `{ extractable: true }`
98
+ so the JWKS export succeeds:
64
99
 
65
100
  ```typescript
66
101
  const key = await jose.importPKCS8(pkcs8Pem, 'RS256', { extractable: true })
67
102
  const jwk = await jose.exportJWK(key)
68
103
  ```
69
104
 
105
+ ## Response headers the hardened defaults get wrong
106
+
107
+ `@fastify/helmet` runs with its defaults on every OwlMeans server, and two of them break an
108
+ authorization endpoint. Both are corrected by middleware this package mounts ahead of the provider.
109
+
110
+ - **`Cross-Origin-Opener-Policy: same-origin`** puts the authorization document in a fresh browsing
111
+ context group, severing `window.opener` **permanently** — navigating back to the relying party
112
+ afterwards does not restore it. That kills popup-based login, which is how an app embedded in an
113
+ iframe must authenticate (see the `web-oidc-rp` skill). The provider sends `unsafe-none`.
114
+ - **`form-action 'self'`** blocks the provider's own interaction form posting across origins, so it
115
+ is rewritten to `form-action *`.
116
+
117
+ **Set these as middleware, never as a Fastify `onSend` hook.** `oidc.callback()` is a Koa handler
118
+ mounted through Middie: it ends the response itself, outside Fastify's reply lifecycle, so `onSend`
119
+ never fires for any route the provider answers and anything set there silently never reaches the
120
+ wire — the header looks configured in code and is absent in production. Middleware registered before
121
+ the provider writes to the raw response, where helmet has already put its defaults, so the override
122
+ is what ships. Verify with `curl -D -` against the provider's
123
+ `.well-known/openid-configuration` rather than by reading the code.
124
+
70
125
  ## Depends On
71
126
 
72
- - `@owlmeans/oidc`, `@owlmeans/server-api`, `@owlmeans/server-context`
73
- - `oidc-provider` v9, `jose` v6 (runtime — see [[oidc-versions]] for pinned versions and upgrade checklist)
127
+ - `@owlmeans/oidc`, `@owlmeans/server-api`, `@owlmeans/server-context`, `@owlmeans/config`,
128
+ `@owlmeans/context`, `@owlmeans/entrypoint`, `@owlmeans/route`, `@noble/hashes`, `@scure/base`
129
+ - `fastify` (peer) — the API server this package mounts the provider onto
130
+ - `oidc-provider` v9, `jose` v6 — see [[oidc-versions]] for the pins and the upgrade checklist
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAA0C,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAS9G,eAAO,MAAM,yBAAyB,WAAW,MAAM,KAAmB,mBAoGzE,CAAA;AAED,eAAO,MAAM,yBAAyB,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,OACzE,CAAC,UAAS,MAAM,KACpB,CAOF,CAAA"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAA0C,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAS9G,eAAO,MAAM,yBAAyB,WAAW,MAAM,KAAmB,mBAoHzE,CAAA;AAED,eAAO,MAAM,yBAAyB,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,OACzE,CAAC,UAAS,MAAM,KACpB,CAOF,CAAA"}
package/build/service.js CHANGED
@@ -29,34 +29,48 @@ export const createOidcProviderService = (alias = DEFAULT_ALIAS) => {
29
29
  interactions: {
30
30
  url: async (_, interaction) => {
31
31
  // The interaction screen is a FRONTEND route, and this is a server context — the
32
- // entrypoint registered here has no `call()` (that helper is attached by
33
- // `@owlmeans/client-entrypoint` only). So the URL is assembled the way `urlCall` does
34
- // it in the browser: resolve the route, substitute the path params, then qualify it
35
- // with the frontend service's host.
32
+ // entrypoint registered here has no `url()` (that helper is attached by
33
+ // `@owlmeans/client-entrypoint` only). So the URL is assembled the way `entrypointUrl`
34
+ // does it in the browser: take the entrypoint's path, substitute the path params, then
35
+ // qualify it with the address the entrypoint answers on — the FRONTEND service's, not
36
+ // this one's.
36
37
  const entry = context.entrypoint(INTERACTION);
37
- const route = await entry.route.resolve(context);
38
- const path = entry.getPath().split(SEP)
38
+ const path = entry.path().split(SEP)
39
39
  .map(part => part === `${PARAM}${INTERACTION_UID}` ? interaction.uid : part)
40
40
  .join(SEP);
41
- return helper.makeUrl(route, path);
41
+ return helper.makeUrl(entry.address(), path);
42
42
  }
43
43
  }
44
44
  });
45
45
  oidc.proxy = cfg.behindProxy ?? unsecure;
46
46
  const base = SEP + (cfg.basePath ?? DEFAULT_PATH);
47
- api.server.use(base, oidc.callback());
48
- // oidc-provider v9: provider.use() middleware no longer runs post-response after a matched
49
- // route. CSP rewrite is handled at the Fastify layer via an onSend hook instead.
50
- api.server.addHook('onSend', async (request, reply, payload) => {
51
- if (!request.url.startsWith(base)) {
52
- return payload;
53
- }
54
- const csp = reply.getHeader('content-security-policy');
47
+ /**
48
+ * Response headers the hardened defaults get wrong for an authorization endpoint.
49
+ *
50
+ * This runs as middleware, ahead of the provider in the same chain, and writes to the raw
51
+ * response — deliberately, not as a Fastify `onSend` hook. `oidc.callback()` is a Koa
52
+ * handler mounted through Middie: it ends the response itself, outside Fastify's reply
53
+ * lifecycle, so `onSend` never fires for any route the provider answers and anything set
54
+ * there silently never reaches the wire. The security defaults are already on the raw
55
+ * response by this point (`@fastify/helmet` applies them in `onRequest`), so overriding
56
+ * them here is what actually takes effect.
57
+ */
58
+ api.server.use(base, (_req, res, next) => {
59
+ // `Cross-Origin-Opener-Policy: same-origin` puts this document in a fresh browsing
60
+ // context group, which severs `window.opener` **permanently** — navigating back to the
61
+ // relying party afterwards does not restore it. Popup-based login is the standard way an
62
+ // embedded application authenticates and the opener is its only channel home, so an
63
+ // authorization endpoint must not be the thing that cuts it.
64
+ res.setHeader('Cross-Origin-Opener-Policy', 'unsafe-none');
65
+ // The provider posts its own interaction forms across origins; `form-action 'self'`
66
+ // would block the submission.
67
+ const csp = res.getHeader('Content-Security-Policy');
55
68
  if (typeof csp === 'string' && csp.includes("form-action 'self'")) {
56
- reply.header('Content-Security-Policy', csp.replace(/form-action 'self'/, 'form-action *'));
69
+ res.setHeader('Content-Security-Policy', csp.replace(/form-action 'self'/, 'form-action *'));
57
70
  }
58
- return payload;
71
+ next();
59
72
  });
73
+ api.server.use(base, oidc.callback());
60
74
  if (context.cfg.debug?.all || context.cfg.debug?.oidc) {
61
75
  oidc.on('grant.error', (_, error) => {
62
76
  console.warn('GRANT ERROR .......: ');
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/server-oidc-provider",
3
- "version": "0.1.18-rc.3",
3
+ "version": "0.1.18-rc.31",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -23,8 +23,8 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@owlmeans/dep-config": "workspace:*",
26
- "@owlmeans/context": "^0.1.18-rc.3",
27
- "@types/bun": "^1.3.14",
26
+ "@owlmeans/context": "^0.1.18-rc.24",
27
+ "@types/bun": "^1.4.0",
28
28
  "@types/node": "^26.1.0",
29
29
  "@types/oidc-provider": "9.5.0",
30
30
  "nodemon": "^3.1.14",
@@ -35,13 +35,13 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@noble/hashes": "^1.5.0",
38
- "@owlmeans/config": "^0.1.18-rc.3",
39
- "@owlmeans/context": "^0.1.18-rc.3",
40
- "@owlmeans/entrypoint": "^0.1.18-rc.3",
41
- "@owlmeans/oidc": "^0.1.18-rc.3",
42
- "@owlmeans/route": "^0.1.18-rc.3",
43
- "@owlmeans/server-api": "^0.1.18-rc.3",
44
- "@owlmeans/server-context": "^0.1.18-rc.3",
38
+ "@owlmeans/config": "^0.1.18-rc.28",
39
+ "@owlmeans/context": "^0.1.18-rc.24",
40
+ "@owlmeans/entrypoint": "^0.1.18-rc.27",
41
+ "@owlmeans/oidc": "^0.1.18-rc.36",
42
+ "@owlmeans/route": "^0.1.18-rc.25",
43
+ "@owlmeans/server-api": "^0.1.18-rc.32",
44
+ "@owlmeans/server-context": "^0.1.18-rc.27",
45
45
  "@scure/base": "^2.3.0",
46
46
  "jose": "6.2.5",
47
47
  "oidc-provider": "9.11.1"
package/src/service.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { assertContext, createService } from '@owlmeans/context'
2
2
  import { DEFAULT_ALIAS, OIDC_ACCOUNT_SERVICE } from './consts.js'
3
3
  import { DEFAULT_PATH, INTERACTION, INTERACTION_UID } from '@owlmeans/oidc'
4
+ import type { ServerResponse } from 'node:http'
4
5
  import type { Config, Context, OidcAccountService, OidcAdapterService, OidcProviderService } from './types.js'
5
6
  import Provider from 'oidc-provider'
6
7
  import type { BasicRoute } from '@owlmeans/route'
@@ -42,17 +43,17 @@ export const createOidcProviderService = (alias: string = DEFAULT_ALIAS): OidcPr
42
43
  interactions: {
43
44
  url: async (_, interaction) => {
44
45
  // The interaction screen is a FRONTEND route, and this is a server context — the
45
- // entrypoint registered here has no `call()` (that helper is attached by
46
- // `@owlmeans/client-entrypoint` only). So the URL is assembled the way `urlCall` does
47
- // it in the browser: resolve the route, substitute the path params, then qualify it
48
- // with the frontend service's host.
46
+ // entrypoint registered here has no `url()` (that helper is attached by
47
+ // `@owlmeans/client-entrypoint` only). So the URL is assembled the way `entrypointUrl`
48
+ // does it in the browser: take the entrypoint's path, substitute the path params, then
49
+ // qualify it with the address the entrypoint answers on — the FRONTEND service's, not
50
+ // this one's.
49
51
  const entry = context.entrypoint<CommonEntrypoint>(INTERACTION)
50
- const route = await entry.route.resolve<Config, Context>(context)
51
- const path = entry.getPath().split(SEP)
52
+ const path = entry.path().split(SEP)
52
53
  .map(part => part === `${PARAM}${INTERACTION_UID}` ? interaction.uid : part)
53
54
  .join(SEP)
54
55
 
55
- return helper.makeUrl(route, path)
56
+ return helper.makeUrl(entry.address(), path)
56
57
  }
57
58
  }
58
59
  })
@@ -60,21 +61,37 @@ export const createOidcProviderService = (alias: string = DEFAULT_ALIAS): OidcPr
60
61
  oidc.proxy = cfg.behindProxy ?? unsecure
61
62
  const base = SEP + (cfg.basePath ?? DEFAULT_PATH)
62
63
 
63
- api.server.use(base, oidc.callback())
64
-
65
- // oidc-provider v9: provider.use() middleware no longer runs post-response after a matched
66
- // route. CSP rewrite is handled at the Fastify layer via an onSend hook instead.
67
- api.server.addHook('onSend', async (request, reply, payload) => {
68
- if (!request.url.startsWith(base)) {
69
- return payload
70
- }
71
- const csp = reply.getHeader('content-security-policy')
64
+ /**
65
+ * Response headers the hardened defaults get wrong for an authorization endpoint.
66
+ *
67
+ * This runs as middleware, ahead of the provider in the same chain, and writes to the raw
68
+ * response — deliberately, not as a Fastify `onSend` hook. `oidc.callback()` is a Koa
69
+ * handler mounted through Middie: it ends the response itself, outside Fastify's reply
70
+ * lifecycle, so `onSend` never fires for any route the provider answers and anything set
71
+ * there silently never reaches the wire. The security defaults are already on the raw
72
+ * response by this point (`@fastify/helmet` applies them in `onRequest`), so overriding
73
+ * them here is what actually takes effect.
74
+ */
75
+ api.server.use(base, (_req: unknown, res: ServerResponse, next: () => void) => {
76
+ // `Cross-Origin-Opener-Policy: same-origin` puts this document in a fresh browsing
77
+ // context group, which severs `window.opener` **permanently** — navigating back to the
78
+ // relying party afterwards does not restore it. Popup-based login is the standard way an
79
+ // embedded application authenticates and the opener is its only channel home, so an
80
+ // authorization endpoint must not be the thing that cuts it.
81
+ res.setHeader('Cross-Origin-Opener-Policy', 'unsafe-none')
82
+
83
+ // The provider posts its own interaction forms across origins; `form-action 'self'`
84
+ // would block the submission.
85
+ const csp = res.getHeader('Content-Security-Policy')
72
86
  if (typeof csp === 'string' && csp.includes("form-action 'self'")) {
73
- reply.header('Content-Security-Policy', csp.replace(/form-action 'self'/, 'form-action *'))
87
+ res.setHeader('Content-Security-Policy', csp.replace(/form-action 'self'/, 'form-action *'))
74
88
  }
75
- return payload
89
+
90
+ next()
76
91
  })
77
92
 
93
+ api.server.use(base, oidc.callback())
94
+
78
95
  if (context.cfg.debug?.all || context.cfg.debug?.oidc) {
79
96
 
80
97
  oidc.on('grant.error', (_, error) => {
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect } from 'bun:test'
2
2
  import { generateKeyPairSync } from 'node:crypto'
3
- import { AppType, Layer, makeBasicContext } from '@owlmeans/context'
3
+ import { AppType, makeBasicContext } from '@owlmeans/context'
4
4
  import type { BasicContext } from '@owlmeans/context'
5
5
  import { combineConfig } from '../src/utils/config.js'
6
6
  import type { Config } from '../src/types.js'
@@ -12,7 +12,6 @@ const makeTestContext = () => {
12
12
  const cfg: Config = {
13
13
  ready: false,
14
14
  service: 'server-oidc-provider-tests',
15
- layer: Layer.Service,
16
15
  type: AppType.Backend,
17
16
  services: {},
18
17
  debug: { all: false },
package/build/.gitkeep DELETED
File without changes