@seamless-auth/oidc-provider 0.3.0 → 0.4.0
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/CHANGELOG.md +37 -0
- package/README.md +80 -10
- package/dist/accessTokenClaims.d.ts +11 -0
- package/dist/accessTokenClaims.js +30 -0
- package/dist/accessTokenClaims.js.map +1 -1
- package/dist/accountClaims.d.ts +51 -0
- package/dist/accountClaims.js +102 -0
- package/dist/accountClaims.js.map +1 -0
- package/dist/adapter.js +16 -3
- package/dist/adapter.js.map +1 -1
- package/dist/apiClient.d.ts +3 -2
- package/dist/apiClient.js +3 -2
- package/dist/apiClient.js.map +1 -1
- package/dist/brandingContrast.d.ts +4 -0
- package/dist/brandingContrast.js +59 -0
- package/dist/brandingContrast.js.map +1 -0
- package/dist/claimsMismatch.d.ts +15 -0
- package/dist/claimsMismatch.js +90 -0
- package/dist/claimsMismatch.js.map +1 -0
- package/dist/createOidcEdge.d.ts +5 -0
- package/dist/createOidcEdge.js +43 -7
- package/dist/createOidcEdge.js.map +1 -1
- package/dist/deviceFlow.d.ts +2 -6
- package/dist/deviceFlow.js +2 -10
- package/dist/deviceFlow.js.map +1 -1
- package/dist/env.d.ts +1 -4
- package/dist/env.js +46 -4
- package/dist/env.js.map +1 -1
- package/dist/errorPage.d.ts +10 -0
- package/dist/errorPage.js +24 -0
- package/dist/errorPage.js.map +1 -0
- package/dist/hostedPages.d.ts +1 -0
- package/dist/hostedPages.js +24 -1
- package/dist/hostedPages.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interactions.js +83 -30
- package/dist/interactions.js.map +1 -1
- package/dist/jwtAccessTokens.d.ts +1 -1
- package/dist/jwtAccessTokens.js +2 -1
- package/dist/jwtAccessTokens.js.map +1 -1
- package/dist/logout.d.ts +4 -0
- package/dist/logout.js +8 -1
- package/dist/logout.js.map +1 -1
- package/dist/providerConfig.d.ts +3 -3
- package/dist/providerConfig.js +22 -8
- package/dist/providerConfig.js.map +1 -1
- package/dist/requestContext.d.ts +1 -2
- package/dist/requestContext.js.map +1 -1
- package/dist/requestObjectErrors.d.ts +12 -0
- package/dist/requestObjectErrors.js +47 -0
- package/dist/requestObjectErrors.js.map +1 -0
- package/dist/resumeCookie.js +3 -1
- package/dist/resumeCookie.js.map +1 -1
- package/dist/server.js +2 -2
- package/dist/server.js.map +1 -1
- package/dist/signingKey.d.ts +31 -3
- package/dist/signingKey.js +104 -4
- package/dist/signingKey.js.map +1 -1
- package/dist/ui/assets/index-BLikvo1E.js +18 -0
- package/dist/ui/assets/index-DKah8G4b.css +1 -0
- package/dist/ui/index.html +2 -2
- package/package.json +11 -8
- package/dist/ui/assets/index-CydLXRvo.js +0 -18
- package/dist/ui/assets/index-y3LME-Gv.css +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# @seamless-auth/oidc-provider
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 307f05d: Carry roles, permissions and custom claims in provider tokens (#47).
|
|
8
|
+
|
|
9
|
+
- New scopes `permissions` (`roles`, `permissions`, `org_id`, `org_roles`, `org_permissions`, or `permissions_omitted`) and `custom_claims` (every custom claim the API resolves for the user and the application). They appear in ID tokens, `/userinfo`, and a user's RFC 9068 access token for a resource when the grant holds the scope. The consent page describes both.
|
|
10
|
+
- The values come from the API's `/oidc/accounts/:id` and the API signs only what it computes again, so the edge cannot add or change one. Reserved claim names are never released, and the permission claims are released whole or not at all.
|
|
11
|
+
- When the API refuses a sign with `claims_mismatch` (a role or membership changed between the account read and the sign), the edge reads the account again and signs once more, so the token request succeeds with the new values. A second mismatch answers `server_error` (500) with a description. Other refusals are not retried.
|
|
12
|
+
- `org_id` now names the session's active organization rather than the user's oldest membership. This changes `org_id` under the `seamless` scope too.
|
|
13
|
+
- Needs a seamless-auth-api release that returns these claims and signs them. Against an older API none are released.
|
|
14
|
+
- Depend on `@seamless-auth/types` `^0.40.0` for the shared reserved claim list, the account claims schema and the `claims_mismatch` refusal code.
|
|
15
|
+
- 18b472c: The edge now follows the API's provider key rotation without a restart. It used to load the signing keys once at startup, so after the API rotated its active key every token request failed with `unknown_key` until the edge restarted, and `/jwks` and JWT access token introspection kept the startup keys. It now re-reads the keys every five minutes and at once when the API refuses a key as unknown (at most the request that meets the rotation fails), and `/jwks` serves the current set. Embedders can set the interval with the new `signingKeyRefreshMs` option (`0` turns the timer off). A rotation to a key with a different algorithm is refused with a logged error and still needs a restart. `SigningKeyRing` is exported for custom setups.
|
|
16
|
+
- 18b472c: `TRUST_PROXY` now takes a hop count (`2` for a CDN in front of a load balancer) or a comma-separated list of proxy addresses and subnets (`10.0.0.0/8, 172.16.0.5`, or Express's `loopback`, `linklocal` and `uniquelocal`), and is passed to Express's `trust proxy` as is. Behind more than one proxy the edge used to forward the last proxy's address as the client IP, so users shared the API's per-IP rate limits and lockouts. `true` still means one hop and `false` none, so existing deployments are unchanged; a value that is neither a hop count nor valid addresses now stops the service at startup. Keep the container port reachable only through the proxy.
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- bfff063: Depend on `@seamless-auth/core` and `@seamless-auth/express` `^0.26.0`. On 0.x, `^0.23.0` stopped at 0.23, so the edge ran on 0.23 and an application installing the provider got a second, older copy of both. The edge now has the adapter fixes from 0.25: the CSRF origin check on form posts to the auth routes (seamless-auth-server#256), no replay of a completed bearer refresh rotation (#258), no client-chosen client IP under a `trust proxy` that trusts every address (#257), and a bundled adapter manifest with the v0.23 routes.
|
|
21
|
+
|
|
22
|
+
The hosted pages build against `@seamless-auth/react` 0.20 and `@seamless-auth/client` 0.9. Client 0.8.2 sent body-less requests such as the passkey step-up start without a JSON content type or the transport header, and adapters from 0.25 refuse those with 415, so step-up needs the newer client.
|
|
23
|
+
- 216b785: The confirmation for a native client now names the account as well as the client. `GET /interaction/:uid/details` returns `account: { identifier }` (the account's email, or its phone number if it has none), or `account: null` unless the browser is signed in as the interaction's account and the API can describe it. The hosted "Continue to <app>?" card shows the identifier, and with no account to name it offers only Cancel. If you serve your own pages through `uiDir`, show `account.identifier` beside the client name, send `{ "confirmed": true }` only from a real click, and do not offer to continue when `account` is `null`.
|
|
24
|
+
- 7858f18: A device client polling an expired device code faster than its interval now gets `expired_token`, so it stops, rather than `slow_down` on every poll. The poll throttle only tracks codes that have not expired. With an API that keeps expired device codes readable for a while (seamless-auth-api#542), the token endpoint answers `expired_token` for them; a code the API does not know still gets `invalid_grant`.
|
|
25
|
+
- 7858f18: Errors the provider cannot send back to the app now render on the hosted pages, with your branding, instead of the library's default "oops! something went wrong" page. That covers an unknown `client_id`, an unregistered `redirect_uri` at `/authorize`, and a refused `/session/end` (an unregistered `post_logout_redirect_uri`, or an `id_token_hint` that cannot be read). The page shows the error code, the provider's description and a plain explanation, and answers with the hosted pages' CSP and `no-store`. A server error shows a generic description.
|
|
26
|
+
- 7858f18: The hosted pages meet WCAG 2.2 AA with the default palette and a sound custom one (see `docs/accessibility-audit.md`).
|
|
27
|
+
|
|
28
|
+
- The sign-in screens' mode toggle, error text and hovered button now take this service's palette, and follow `hosted_ui` branding, instead of fallback colors that fell below 4.5:1.
|
|
29
|
+
- Text field edges are darker (`#7a828e` light, `#8a93a0` dark) so they meet 3:1, which also darkens card borders.
|
|
30
|
+
- Sign-out, device and error pages are titled for what they do rather than "Sign in to <app>".
|
|
31
|
+
- The device code error is tied to the code field.
|
|
32
|
+
- When the hosted pages render with a `hosted_ui` palette whose pairs fall below AA contrast, the service logs one warning naming each pair. Nothing is refused.
|
|
33
|
+
- 18b472c: A failure while finishing a login no longer leaves a grant behind, and unexpected errors are answered as JSON. `POST /interaction/:uid/login` saves the grant before it reads the auth context; when that read failed (the API unreachable, say), the grant stayed and bound the first-party session to the client without a finished sign-in. The edge router also had no error handler, so such failures reached Express's default handler, which answers HTML with a stack trace whenever `NODE_ENV` is not `production`. They now answer `500 {"error":"server_error"}` (logged by name and message), and a malformed request body answers its 4xx status with `{"error":"invalid_request"}`.
|
|
34
|
+
- 18b472c: `/session/end` no longer signs a browser out of the hosted pages when it has no provider sign-in. The library ends an empty provider session without a confirmation page, and the edge used to clear the first-party adapter cookies on that automatic post, so any site that sent a browser to `/session/end` signed it out. The first-party session and its cookies are now ended only when the provider session had an account and the user confirmed on the hosted page.
|
|
35
|
+
- 18b472c: A first-party native client (`application_type: native`) no longer gets a code without a click. Any program on the device can listen on a loopback port or claim a private-use scheme, so a signed-in user's browser could otherwise hand a code to it with no interaction (RFC 8252 section 8.6). The hosted pages now show a "Continue to <app>" confirmation for every native client request, after sign-in and on later requests that ride the provider session, and `POST /interaction/:uid/consent` answers `403 confirmation_required` for a native client's prompt unless the body is `{ "confirmed": true }`. A custom hosted UI must send that body from the user's click. Web clients and device-flow approvals are unchanged.
|
|
36
|
+
- 7858f18: A request object that asks for `response_mode=form_post` now gets its `request_not_supported` refusal by form post rather than in the query string. Request objects are still not supported. Only `response_mode` is read from the refused object, without verifying it, and only the value `form_post` changes anything: the error still goes only to the request's own `redirect_uri` once it is checked against the client's registered URIs, and no other value from the object is used or shown. This lets the Form Post OP conformance profile pass `oidcc-unsigned-request-object-supported-correctly-or-rejected-as-unsupported`.
|
|
37
|
+
- 18b472c: The device poll throttle and the resume cookie check now match paths the way the provider's router does. A device client polling `/token/` was never told `slow_down`, because the throttle only recognised the exact path `/token`; it now follows the provider's own routing, so every spelling the provider accepts is throttled. The check that a resumed authorization is the one the resume cookie names now also covers `/authorize/<uid>/` and a differently cased `/AUTHORIZE/<uid>`.
|
|
38
|
+
- abb4834: Depend on `@seamless-auth/types` `^0.36.0`, which adds the session exchange contract.
|
|
39
|
+
|
|
3
40
|
## 0.3.0
|
|
4
41
|
|
|
5
42
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -16,6 +16,10 @@ any OIDC app ──► seamless-auth-oidc-provider (public: OIDC endpoints, host
|
|
|
16
16
|
- Built on [`oidc-provider`](https://github.com/panva/node-oidc-provider) 9.x.
|
|
17
17
|
- Holds no private keys and no database. The API signs every token after checking its claims,
|
|
18
18
|
and stores all provider state.
|
|
19
|
+
- Follows the API's key rotation without a restart. It re-reads the API's keys every five
|
|
20
|
+
minutes (`signingKeyRefreshMs` when embedded), and at once when the API refuses a key as
|
|
21
|
+
unknown, so at most the request that meets a rotation fails. `/jwks` serves the current set.
|
|
22
|
+
Rotating to a key with another algorithm still needs a restart.
|
|
19
23
|
- Code flow with PKCE (a confidential client can be opted out, and then sends `nonce` unless that is waived too), refresh rotation always on, `private_key_jwt` for confidential
|
|
20
24
|
clients, and shared secrets only for clients opted in on the API.
|
|
21
25
|
|
|
@@ -35,6 +39,13 @@ The design is in
|
|
|
35
39
|
hosted pages.
|
|
36
40
|
- HTTPS. Provider cookies are `__Host-` cookies, which browsers only accept over TLS.
|
|
37
41
|
|
|
42
|
+
## Run it on your laptop
|
|
43
|
+
|
|
44
|
+
[`local/README.md`](local/README.md) goes from nothing to a passkey sign-in on the hosted page and a
|
|
45
|
+
JWT access token for your own API on one page: a compose file with the API, Postgres and this
|
|
46
|
+
service behind local TLS, generated keys, and a seed for the clients and the resource. The
|
|
47
|
+
production checks stay on.
|
|
48
|
+
|
|
38
49
|
## Run the image
|
|
39
50
|
|
|
40
51
|
```bash
|
|
@@ -43,16 +54,28 @@ docker run -p 5314:5314 --env-file .env ghcr.io/fells-code/seamless-auth-oidc-pr
|
|
|
43
54
|
|
|
44
55
|
## Configuration
|
|
45
56
|
|
|
46
|
-
| Variable | Required | Description
|
|
47
|
-
| ----------------------------- | -------- |
|
|
48
|
-
| `SEAMLESS_API_URL` | yes | The private API, as this service reaches it.
|
|
49
|
-
| `SEAMLESS_API_ISSUER` | no | The API's `ISSUER`, when it differs from `SEAMLESS_API_URL`.
|
|
50
|
-
| `SEAMLESS_OIDC_SERVICE_TOKEN` | yes | This service's own service token secret, `SEAMLESS_OIDC_SERVICE_TOKEN` on the API. It must differ from the adapters' `SEAMLESS_SERVICE_TOKEN`, which this service never holds. At least 32 characters.
|
|
51
|
-
| `SEAMLESS_JWKS_KID` | no | The `kid` on the service tokens this service signs.
|
|
52
|
-
| `SEAMLESS_COOKIE_SECRET` | yes | Signs the first-party session cookies. At least 32 characters.
|
|
53
|
-
| `OIDC_COOKIE_KEYS` | yes | Comma-separated provider cookie keys. The first signs, the rest verify.
|
|
54
|
-
| `TRUST_PROXY` | no | `
|
|
55
|
-
| `PORT` | no | Defaults to `5314`.
|
|
57
|
+
| Variable | Required | Description |
|
|
58
|
+
| ----------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
59
|
+
| `SEAMLESS_API_URL` | yes | The private API, as this service reaches it. |
|
|
60
|
+
| `SEAMLESS_API_ISSUER` | no | The API's `ISSUER`, when it differs from `SEAMLESS_API_URL`. |
|
|
61
|
+
| `SEAMLESS_OIDC_SERVICE_TOKEN` | yes | This service's own service token secret, `SEAMLESS_OIDC_SERVICE_TOKEN` on the API. It must differ from the adapters' `SEAMLESS_SERVICE_TOKEN`, which this service never holds. At least 32 characters. |
|
|
62
|
+
| `SEAMLESS_JWKS_KID` | no | The `kid` on the service tokens this service signs. |
|
|
63
|
+
| `SEAMLESS_COOKIE_SECRET` | yes | Signs the first-party session cookies. At least 32 characters. |
|
|
64
|
+
| `OIDC_COOKIE_KEYS` | yes | Comma-separated provider cookie keys. The first signs, the rest verify. |
|
|
65
|
+
| `TRUST_PROXY` | no | The proxies in front of this service, as Express's `trust proxy`: the number of hops (`2` for a CDN in front of a load balancer), or a comma-separated list of proxy addresses and subnets (`10.0.0.0/8, 172.16.0.5`). `true` means one hop. Defaults to `false`. See [Behind a proxy](#behind-a-proxy). |
|
|
66
|
+
| `PORT` | no | Defaults to `5314`. |
|
|
67
|
+
|
|
68
|
+
### Behind a proxy
|
|
69
|
+
|
|
70
|
+
The client IP this service forwards to the API decides who shares its per-IP rate limits and
|
|
71
|
+
lockouts, and Express reads it from `X-Forwarded-For` through `TRUST_PROXY`. Set it to the
|
|
72
|
+
proxies actually in front of this service: with too few hops every user arrives as the CDN
|
|
73
|
+
node, and with too many the client picks its own address. A list of addresses and subnets
|
|
74
|
+
holds even when the number of hops varies.
|
|
75
|
+
|
|
76
|
+
Make the container port reachable only through the proxy. A client that can reach it directly
|
|
77
|
+
writes the last `X-Forwarded-For` entry and `X-Forwarded-Proto` and `X-Forwarded-Host`
|
|
78
|
+
itself, and that address goes to the API under this service's token.
|
|
56
79
|
|
|
57
80
|
The issuer comes from the API (`oidc_issuer`), not from this service's environment. The service
|
|
58
81
|
answers only requests for the issuer's own scheme and host, and refuses to start when the API
|
|
@@ -121,6 +144,35 @@ carry none of the three, and an opaque `/userinfo` token gains nothing.
|
|
|
121
144
|
- First-party apps have the scopes granted with the sign-in. Third-party apps list them on the
|
|
122
145
|
consent page.
|
|
123
146
|
|
|
147
|
+
## Roles, permissions and custom claims
|
|
148
|
+
|
|
149
|
+
Two scopes release the authorization claims a first-party Seamless token carries (API ADR 0004
|
|
150
|
+
and ADR 0005), under the same names:
|
|
151
|
+
|
|
152
|
+
| Scope | Claims |
|
|
153
|
+
| --------------- | ------------------------------------------------------------------------------------------- |
|
|
154
|
+
| `permissions` | `roles`, `permissions`, `org_id`, `org_roles`, `org_permissions` (or `permissions_omitted`) |
|
|
155
|
+
| `custom_claims` | every custom claim the API resolves for the user and this application |
|
|
156
|
+
|
|
157
|
+
They appear in the ID token and `/userinfo`, and in a user's access token for a resource when the
|
|
158
|
+
grant holds the scope (the access token's own `scope` lists only the resource's scopes). The older
|
|
159
|
+
`seamless` scope still releases `roles` and `org_id` alone.
|
|
160
|
+
|
|
161
|
+
- `org_id` and the `org_*` claims name the session's active organization, while the user is still
|
|
162
|
+
a member of it.
|
|
163
|
+
- Custom claims come from the user's instance roles, then their roles in the active organization,
|
|
164
|
+
then the application's own set (`/admin/custom-claims/oidc_client/:clientId`), then the
|
|
165
|
+
`pre_token` login hook, a later source winning per name. Reserved names are never released.
|
|
166
|
+
- Permission and custom claims share one 1 KiB budget. Over it, the permission claims become
|
|
167
|
+
`"permissions_omitted": true` first (read `GET /users/me/permissions` then), and custom claims
|
|
168
|
+
are dropped whole only when they do not fit beside that marker. Nothing is trimmed in part.
|
|
169
|
+
- The API computes every value and signs only what matches its own computation for the session
|
|
170
|
+
and application, so this service cannot add, raise or forge one. A role change shows on the
|
|
171
|
+
next token or refresh. If it lands between this service's read and the API's sign, the API
|
|
172
|
+
refuses with `claims_mismatch` and this service reads the account again and signs once more; a
|
|
173
|
+
second mismatch answers `server_error`.
|
|
174
|
+
- Client credentials tokens carry none of them.
|
|
175
|
+
|
|
124
176
|
## Token lifetimes
|
|
125
177
|
|
|
126
178
|
An application's own `accessTokenTtlSeconds`, `idTokenTtlSeconds` and `refreshTokenTtlSeconds`
|
|
@@ -179,6 +231,11 @@ ends:
|
|
|
179
231
|
adapter cookies. Every other app the user signed in to with it is signed out too.
|
|
180
232
|
- **Only sign out of** the asking app ends that app's grant and keeps the session.
|
|
181
233
|
|
|
234
|
+
When the browser has no provider sign-in there is nothing to confirm, and the library ends its
|
|
235
|
+
empty provider session without a page. The first-party session and the adapter cookies are
|
|
236
|
+
left alone then, so a site that sends a browser to `/session/end` cannot sign it out of the
|
|
237
|
+
hosted pages.
|
|
238
|
+
|
|
182
239
|
Back-channel logout (OpenID Back-Channel Logout 1.0) is sent by the API, not by this service.
|
|
183
240
|
The API holds the keys and sees every way a session ends (this logout, admin revoke, sign-out
|
|
184
241
|
everywhere, eviction), so a client with a `backchannelLogoutUri` gets a `logout+jwt` token
|
|
@@ -237,6 +294,19 @@ same way any Seamless app does, then finish the OIDC interaction.
|
|
|
237
294
|
screens. A recovery session goes to enrollment before it can finish a sign-in.
|
|
238
295
|
- **Consent.** First-party clients have consent implied. Third-party clients see the client
|
|
239
296
|
name, the host they are sent back to and the requested scopes, on every authorization.
|
|
297
|
+
- **Native apps.** Any program on a device can listen on a loopback port or claim a private-use
|
|
298
|
+
scheme, so every request from a native client (`application_type: native`), first-party
|
|
299
|
+
included, waits for the user to click "Continue to <app>" (RFC 8252 section 8.6). The card names
|
|
300
|
+
the client and the account, as `account.identifier` (an email or phone number) from
|
|
301
|
+
`GET /interaction/:uid/details`, and that field is `null` unless this browser is signed in as the
|
|
302
|
+
interaction's account and the API can describe it. With no account to name, the page offers only
|
|
303
|
+
Cancel. The consent route refuses a native prompt with `403 confirmation_required` unless the
|
|
304
|
+
page sends `{ "confirmed": true }` from that click. Device-flow approvals are confirmed on the
|
|
305
|
+
device pages instead, before sign-in, so those name the client and the user code only.
|
|
306
|
+
- **Custom pages.** `hosted_ui` only brands these pages. If you replace them with your own (the
|
|
307
|
+
`uiDir` option), your confirmation must do the same: show `account.identifier` beside the client
|
|
308
|
+
name as text, send `{ "confirmed": true }` only from a real click, and not offer to continue when
|
|
309
|
+
`account` is `null`. The edge cannot check any of this for you.
|
|
240
310
|
- **Branding.** The app name comes from the API's config each time a page is served, so a
|
|
241
311
|
config change needs no build and no restart.
|
|
242
312
|
- **Headers.** A strict CSP (`script-src 'self'`, styles from this origin or with the
|
|
@@ -2,6 +2,7 @@ import type { KoaContextWithOIDC } from 'oidc-provider';
|
|
|
2
2
|
interface IssuedToken {
|
|
3
3
|
kind?: unknown;
|
|
4
4
|
gty?: unknown;
|
|
5
|
+
scope?: unknown;
|
|
5
6
|
resourceServer?: unknown;
|
|
6
7
|
}
|
|
7
8
|
/**
|
|
@@ -15,4 +16,14 @@ interface IssuedToken {
|
|
|
15
16
|
* an opaque token for userinfo gains nothing.
|
|
16
17
|
*/
|
|
17
18
|
export declare function accessTokenAuthContext(ctx: KoaContextWithOIDC | undefined, token: IssuedToken): Record<string, unknown> | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* seamless-auth-oidc-provider#47: a user's access token for a resource carries the roles,
|
|
21
|
+
* permissions and custom claims a first-party token does, when the client was granted
|
|
22
|
+
* `permissions` or `custom_claims`. The token's own `scope` lists only the resource's scopes, so
|
|
23
|
+
* the grant is read from the code or refresh token it redeems. The values are the ones the
|
|
24
|
+
* library loaded for this request, which `/oidc/sign` computes again before it signs. A device
|
|
25
|
+
* flow token carries them too: they describe the user, not how the sign-in was made.
|
|
26
|
+
*/
|
|
27
|
+
export declare function accessTokenAuthorization(ctx: KoaContextWithOIDC | undefined, token: IssuedToken): Record<string, unknown> | undefined;
|
|
28
|
+
export declare function accessTokenClaims(ctx: KoaContextWithOIDC | undefined, token: IssuedToken): Record<string, unknown> | undefined;
|
|
18
29
|
export {};
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Licensed under the Apache License, Version 2.0
|
|
4
4
|
* See LICENSE file in the project root for full license information
|
|
5
5
|
*/
|
|
6
|
+
import { SESSION_EXCHANGE_SCOPE } from '@seamless-auth/types';
|
|
7
|
+
import { authorizationClaimsFor, providerAccountOf } from './accountClaims.js';
|
|
6
8
|
import { isDeviceGrant } from './deviceFlow.js';
|
|
7
9
|
import { currentRequestContext } from './requestContext.js';
|
|
8
10
|
/**
|
|
@@ -34,4 +36,32 @@ export function accessTokenAuthContext(ctx, token) {
|
|
|
34
36
|
...(typeof source.authTime === 'number' ? { auth_time: source.authTime } : {}),
|
|
35
37
|
};
|
|
36
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* seamless-auth-oidc-provider#47: a user's access token for a resource carries the roles,
|
|
41
|
+
* permissions and custom claims a first-party token does, when the client was granted
|
|
42
|
+
* `permissions` or `custom_claims`. The token's own `scope` lists only the resource's scopes, so
|
|
43
|
+
* the grant is read from the code or refresh token it redeems. The values are the ones the
|
|
44
|
+
* library loaded for this request, which `/oidc/sign` computes again before it signs. A device
|
|
45
|
+
* flow token carries them too: they describe the user, not how the sign-in was made.
|
|
46
|
+
*/
|
|
47
|
+
export function accessTokenAuthorization(ctx, token) {
|
|
48
|
+
if (!ctx?.oidc || token.kind !== 'AccessToken' || !token.resourceServer) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
if (typeof token.scope === 'string' && token.scope.split(' ').includes(SESSION_EXCHANGE_SCOPE)) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
const account = providerAccountOf(ctx.oidc.account);
|
|
55
|
+
const entities = ctx.oidc.entities;
|
|
56
|
+
const grant = entities.RefreshToken ?? entities.AuthorizationCode ?? entities.DeviceCode;
|
|
57
|
+
if (!account || !grant) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return authorizationClaimsFor(account, grant.scope);
|
|
61
|
+
}
|
|
62
|
+
export function accessTokenClaims(ctx, token) {
|
|
63
|
+
const authorization = accessTokenAuthorization(ctx, token);
|
|
64
|
+
const context = accessTokenAuthContext(ctx, token);
|
|
65
|
+
return authorization || context ? { ...authorization, ...context } : undefined;
|
|
66
|
+
}
|
|
37
67
|
//# sourceMappingURL=accessTokenClaims.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessTokenClaims.js","sourceRoot":"","sources":["../src/accessTokenClaims.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"accessTokenClaims.js","sourceRoot":"","sources":["../src/accessTokenClaims.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type OidcAccountClaims } from '@seamless-auth/types';
|
|
2
|
+
import type { Account, Provider } from 'oidc-provider';
|
|
3
|
+
/**
|
|
4
|
+
* What `/oidc/accounts/:id` returns since seamless-auth-oidc-provider#47: the ADR 0004
|
|
5
|
+
* permission claims under their token names, and the merged custom claims, all computed by the
|
|
6
|
+
* API for this session and client and already held to the shared budget.
|
|
7
|
+
*/
|
|
8
|
+
export declare const OidcProviderAccountSchema: import("zod").ZodObject<{
|
|
9
|
+
sub: import("zod").ZodString;
|
|
10
|
+
email: import("zod").ZodOptional<import("zod").ZodString>;
|
|
11
|
+
email_verified: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
12
|
+
phone_number: import("zod").ZodOptional<import("zod").ZodString>;
|
|
13
|
+
phone_number_verified: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
14
|
+
roles: import("zod").ZodArray<import("zod").ZodString>;
|
|
15
|
+
org_id: import("zod").ZodNullable<import("zod").ZodString>;
|
|
16
|
+
permissions: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
17
|
+
permissions_omitted: import("zod").ZodOptional<import("zod").ZodLiteral<true>>;
|
|
18
|
+
org_roles: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
19
|
+
org_permissions: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
20
|
+
customClaims: import("zod").ZodDefault<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnion<readonly [import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>, import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>, import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>, import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>>, import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>>]>>, import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnion<readonly [import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>, import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>>, import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>>]>>]>>, import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnion<readonly [import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>, import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>, import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>>, import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>>]>>, import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnion<readonly [import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>, import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>>, import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodNumber, import("zod").ZodBoolean, import("zod").ZodNull]>>]>>]>>]>>>;
|
|
21
|
+
}, import("zod/v4/core").$strip>;
|
|
22
|
+
export type OidcProviderAccount = OidcAccountClaims;
|
|
23
|
+
/** Roles, permissions and the active organization's roles, as a first-party token has them. */
|
|
24
|
+
export declare const PERMISSIONS_SCOPE = "permissions";
|
|
25
|
+
/** Every custom claim the API resolved for the user and this client. */
|
|
26
|
+
export declare const CUSTOM_CLAIMS_SCOPE = "custom_claims";
|
|
27
|
+
/** `/oidc/sign` signs these together or not at all, since a partial list looks complete. */
|
|
28
|
+
export declare const PERMISSION_CLAIMS: readonly ["permissions", "permissions_omitted", "org_roles", "org_permissions"];
|
|
29
|
+
export declare const PERMISSIONS_SCOPE_CLAIMS: string[];
|
|
30
|
+
declare const CUSTOM_CLAIMS: unique symbol;
|
|
31
|
+
/** Reserved names are dropped here too, whatever the API sent, so none can replace a claim. */
|
|
32
|
+
export declare function customClaimsOf(account: OidcProviderAccount): Record<string, unknown>;
|
|
33
|
+
/** The claims the library filters by scope, with the custom claims kept aside for after it. */
|
|
34
|
+
export declare function accountClaimsOf(account: OidcProviderAccount): {
|
|
35
|
+
sub: string;
|
|
36
|
+
[CUSTOM_CLAIMS]: Record<string, unknown>;
|
|
37
|
+
};
|
|
38
|
+
export declare function withAccount(account: Account, claims: OidcProviderAccount): Account;
|
|
39
|
+
export declare function providerAccountOf(account: unknown): OidcProviderAccount | undefined;
|
|
40
|
+
/** The authorization claims a scope set releases, by the names `/oidc/sign` expects. */
|
|
41
|
+
export declare function authorizationClaimsFor(account: OidcProviderAccount, scope: unknown): Record<string, unknown>;
|
|
42
|
+
/**
|
|
43
|
+
* The library releases only claims named in its static `claims` map, and custom claim names are
|
|
44
|
+
* the adopter's. ID tokens and userinfo both build their payload through `provider.Claims`, so
|
|
45
|
+
* this adds the account's custom claims there when `custom_claims` was granted, under every
|
|
46
|
+
* claim the library already chose. It also keeps the permission claims whole: a `claims`
|
|
47
|
+
* request or a rejection that asks for part of them gets none, rather than a token the API
|
|
48
|
+
* refuses to sign.
|
|
49
|
+
*/
|
|
50
|
+
export declare function releaseAuthorizationClaims(provider: Provider): void;
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2026 Fells Code, LLC
|
|
3
|
+
* Licensed under the Apache License, Version 2.0
|
|
4
|
+
* See LICENSE file in the project root for full license information
|
|
5
|
+
*/
|
|
6
|
+
import { isReservedClaimName, OidcAccountClaimsSchema, } from '@seamless-auth/types';
|
|
7
|
+
/**
|
|
8
|
+
* What `/oidc/accounts/:id` returns since seamless-auth-oidc-provider#47: the ADR 0004
|
|
9
|
+
* permission claims under their token names, and the merged custom claims, all computed by the
|
|
10
|
+
* API for this session and client and already held to the shared budget.
|
|
11
|
+
*/
|
|
12
|
+
export const OidcProviderAccountSchema = OidcAccountClaimsSchema;
|
|
13
|
+
/** Roles, permissions and the active organization's roles, as a first-party token has them. */
|
|
14
|
+
export const PERMISSIONS_SCOPE = 'permissions';
|
|
15
|
+
/** Every custom claim the API resolved for the user and this client. */
|
|
16
|
+
export const CUSTOM_CLAIMS_SCOPE = 'custom_claims';
|
|
17
|
+
/** `/oidc/sign` signs these together or not at all, since a partial list looks complete. */
|
|
18
|
+
export const PERMISSION_CLAIMS = [
|
|
19
|
+
'permissions',
|
|
20
|
+
'permissions_omitted',
|
|
21
|
+
'org_roles',
|
|
22
|
+
'org_permissions',
|
|
23
|
+
];
|
|
24
|
+
export const PERMISSIONS_SCOPE_CLAIMS = ['roles', 'org_id', ...PERMISSION_CLAIMS];
|
|
25
|
+
// A symbol, so the library's own copies of the claims carry it while no claim filter can
|
|
26
|
+
// release it under a name.
|
|
27
|
+
const CUSTOM_CLAIMS = Symbol('seamless.customClaims');
|
|
28
|
+
const ACCOUNT_PROPERTY = 'seamlessAccount';
|
|
29
|
+
/** Reserved names are dropped here too, whatever the API sent, so none can replace a claim. */
|
|
30
|
+
export function customClaimsOf(account) {
|
|
31
|
+
return Object.fromEntries(Object.entries(account.customClaims).filter(([name]) => !isReservedClaimName(name)));
|
|
32
|
+
}
|
|
33
|
+
function standardClaimsOf(account) {
|
|
34
|
+
const { org_id, ...rest } = account;
|
|
35
|
+
delete rest.customClaims;
|
|
36
|
+
return { ...rest, ...(org_id ? { org_id } : {}) };
|
|
37
|
+
}
|
|
38
|
+
/** The claims the library filters by scope, with the custom claims kept aside for after it. */
|
|
39
|
+
export function accountClaimsOf(account) {
|
|
40
|
+
return {
|
|
41
|
+
...standardClaimsOf(account),
|
|
42
|
+
sub: account.sub,
|
|
43
|
+
[CUSTOM_CLAIMS]: customClaimsOf(account),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function withAccount(account, claims) {
|
|
47
|
+
return Object.assign(account, { [ACCOUNT_PROPERTY]: claims });
|
|
48
|
+
}
|
|
49
|
+
export function providerAccountOf(account) {
|
|
50
|
+
const value = account?.[ACCOUNT_PROPERTY];
|
|
51
|
+
return value ? value : undefined;
|
|
52
|
+
}
|
|
53
|
+
function scopesOf(scope) {
|
|
54
|
+
return new Set(typeof scope === 'string' ? scope.split(' ') : []);
|
|
55
|
+
}
|
|
56
|
+
/** The authorization claims a scope set releases, by the names `/oidc/sign` expects. */
|
|
57
|
+
export function authorizationClaimsFor(account, scope) {
|
|
58
|
+
const scopes = scopesOf(scope);
|
|
59
|
+
const standard = standardClaimsOf(account);
|
|
60
|
+
return {
|
|
61
|
+
...(scopes.has(CUSTOM_CLAIMS_SCOPE) ? customClaimsOf(account) : {}),
|
|
62
|
+
...(scopes.has(PERMISSIONS_SCOPE)
|
|
63
|
+
? Object.fromEntries(PERMISSIONS_SCOPE_CLAIMS.filter((name) => name in standard).map((name) => [
|
|
64
|
+
name,
|
|
65
|
+
standard[name],
|
|
66
|
+
]))
|
|
67
|
+
: {}),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const maskScopes = new WeakMap();
|
|
71
|
+
/**
|
|
72
|
+
* The library releases only claims named in its static `claims` map, and custom claim names are
|
|
73
|
+
* the adopter's. ID tokens and userinfo both build their payload through `provider.Claims`, so
|
|
74
|
+
* this adds the account's custom claims there when `custom_claims` was granted, under every
|
|
75
|
+
* claim the library already chose. It also keeps the permission claims whole: a `claims`
|
|
76
|
+
* request or a rejection that asks for part of them gets none, rather than a token the API
|
|
77
|
+
* refuses to sign.
|
|
78
|
+
*/
|
|
79
|
+
export function releaseAuthorizationClaims(provider) {
|
|
80
|
+
const prototype = provider.Claims.prototype;
|
|
81
|
+
const scope = prototype.scope;
|
|
82
|
+
const result = prototype.result;
|
|
83
|
+
prototype.scope = function (value) {
|
|
84
|
+
maskScopes.set(this, value ?? '');
|
|
85
|
+
return scope.call(this, value);
|
|
86
|
+
};
|
|
87
|
+
prototype.result = async function () {
|
|
88
|
+
const claims = await result.call(this);
|
|
89
|
+
const present = PERMISSION_CLAIMS.filter((name) => name in this.available);
|
|
90
|
+
if (present.some((name) => !(name in claims))) {
|
|
91
|
+
for (const name of present) {
|
|
92
|
+
delete claims[name];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const custom = this.available[CUSTOM_CLAIMS];
|
|
96
|
+
if (!custom || !scopesOf(maskScopes.get(this)).has(CUSTOM_CLAIMS_SCOPE)) {
|
|
97
|
+
return claims;
|
|
98
|
+
}
|
|
99
|
+
return { ...custom, ...claims };
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=accountClaims.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accountClaims.js","sourceRoot":"","sources":["../src/accountClaims.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { randomBytes } from 'node:crypto';
|
|
7
7
|
import { OidcPayloadModelSchema, } from '@seamless-auth/types';
|
|
8
|
-
import { errors } from 'oidc-provider';
|
|
8
|
+
import Provider, { errors } from 'oidc-provider';
|
|
9
9
|
import { checkDeviceRequest, DEVICE_CODE_GRANT, DevicePollThrottle, isDeviceGrant, withLoginPrompt, } from './deviceFlow.js';
|
|
10
10
|
import { adoptSession, currentRequestContext, markDeviceFlow, } from './requestContext.js';
|
|
11
11
|
/** A client assertion or proof presented twice. Answered as `invalid_client`, not a 500. */
|
|
@@ -31,6 +31,11 @@ export class UnsupportedModelError extends Error {
|
|
|
31
31
|
// made under, so they only fill an empty context. Every other record is the thing the request
|
|
32
32
|
// is acting on.
|
|
33
33
|
const CONTEXTUAL_MODELS = new Set(['Session', 'Grant']);
|
|
34
|
+
/** The library's own test (`BaseToken#isExpired`): `exp` at or before now, in seconds. */
|
|
35
|
+
function isExpired(record) {
|
|
36
|
+
const { exp } = record.payload;
|
|
37
|
+
return typeof exp === 'number' && exp <= Math.floor(Date.now() / 1000);
|
|
38
|
+
}
|
|
34
39
|
function toAdapterPayload(model, record) {
|
|
35
40
|
if (!record) {
|
|
36
41
|
return undefined;
|
|
@@ -101,8 +106,16 @@ export class ApiPayloadAdapter {
|
|
|
101
106
|
const context = currentRequestContext();
|
|
102
107
|
const record = await this.#client.findPayload(model, id);
|
|
103
108
|
// The grant loads the code more than once per request, and only the first is the poll.
|
|
104
|
-
// Only a code that exists is tracked, so made-up ones cannot fill the throttle
|
|
105
|
-
|
|
109
|
+
// Only a live code that exists is tracked, so made-up ones cannot fill the throttle, and
|
|
110
|
+
// an expired one the API still returns gets the library's expired_token, not slow_down.
|
|
111
|
+
// The library's own routing says whether this is the token endpoint, for every spelling
|
|
112
|
+
// of the path it accepts.
|
|
113
|
+
if (model === 'DeviceCode' &&
|
|
114
|
+
record &&
|
|
115
|
+
!isExpired(record) &&
|
|
116
|
+
context &&
|
|
117
|
+
!context.devicePolled &&
|
|
118
|
+
Provider.ctx?.oidc?.route === 'token') {
|
|
106
119
|
context.devicePolled = true;
|
|
107
120
|
this.#polls.check(id);
|
|
108
121
|
}
|
package/dist/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAEL,sBAAsB,GAEvB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAEL,sBAAsB,GAEvB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAIjD,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,cAAc,GAEf,MAAM,qBAAqB,CAAC;AAE7B,4FAA4F;AAC5F,MAAM,OAAO,mBAAoB,SAAQ,MAAM,CAAC,iBAAiB;IAC/D;QACE,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACrE,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,qBAAqB,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAErF,MAAM,UAAU,GAAG;IACjB,YAAY,EAAE,eAAe;IAC7B,iBAAiB,EAAE,oBAAoB;IACvC,UAAU,EAAE,aAAa;CACjB,CAAC;AAEX,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,IAAY,EAAE,SAAiB;QACzC,KAAK,CAAC,GAAG,SAAS,6CAA6C,IAAI,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,6FAA6F;AAC7F,8FAA8F;AAC9F,gBAAgB;AAChB,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;AAE1E,0FAA0F;AAC1F,SAAS,SAAS,CAAC,MAAyB;IAC1C,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,gBAAgB,CACvB,KAAuB,EACvB,MAAqC;IAErC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,YAAY,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,EAAoB,CAAC;IACxD,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5D,cAAc,EAAE,CAAC;IACnB,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,4EAA4E;AAC5E,MAAM,OAAO,iBAAiB;IACnB,KAAK,CAAS;IACd,MAAM,CAA+B;IACrC,OAAO,CAAgB;IACvB,MAAM,CAAqB;IAEpC,YAAY,IAAY,EAAE,MAAqB,EAAE,KAAK,GAAG,IAAI,kBAAkB,EAAE;QAC/E,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACzD,CAAC;IAED,aAAa,CAAC,SAAiB;QAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,OAAuB,EAAE,SAAkB;QAClE,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,SAAS,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE,0BAA0B,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,SAAS,GAAG,qBAAqB,EAAE,EAAE,SAAS,CAAC;QACrD,MAAM,MAAM,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;QAC9B,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,MAA6C,CAAC;YACpE,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC3B,oFAAoF;YACpF,mFAAmF;YACnF,4EAA4E;YAC5E,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;gBAChC,MAAM,CAAC,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACxE,CAAC;YACD,iFAAiF;YACjF,OAAO,MAAM,CAAC,GAAG,CAAC;YAClB,OAAO,MAAM,CAAC,GAAG,CAAC;YAClB,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE;YAC9D,OAAO,EAAE,MAAM;YACf,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;YAC/B,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpC,CAAC,CAAC;QACH,8EAA8E;QAC9E,2EAA2E;QAC3E,IAAI,KAAK,KAAK,iBAAiB,IAAI,CAAC,OAAO,EAAE,CAAC;YAC5C,MAAM,IAAI,mBAAmB,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAU;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzD,uFAAuF;QACvF,yFAAyF;QACzF,wFAAwF;QACxF,wFAAwF;QACxF,0BAA0B;QAC1B,IACE,KAAK,KAAK,YAAY;YACtB,MAAM;YACN,CAAC,SAAS,CAAC,MAAM,CAAC;YAClB,OAAO;YACP,CAAC,OAAO,CAAC,YAAY;YACrB,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,KAAK,OAAO,EACrC,CAAC;YACD,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC;QACD,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAChD,IAAI,OAAO,IAAI,KAAK,IAAI,UAAU,IAAI,OAAO,OAAO,EAAE,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC3E,OAAO,CAAC,eAAe,KAAK,IAAI,GAAG,EAAE,CAAC;YACtC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QACjE,CAAC;QACD,sFAAsF;QACtF,wEAAwE;QACxE,IACE,OAAO,EAAE,MAAM,KAAK,KAAK;YACzB,CAAC,KAAK,KAAK,aAAa,IAAI,KAAK,KAAK,mBAAmB,CAAC;YAC1D,qBAAqB,EAAE,EAAE,kBAAkB,KAAK,EAAE,EAClD,CAAC;YACD,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,CAAC;QACD,IAAI,KAAK,KAAK,cAAc,IAAI,OAAO,IAAI,MAAM,EAAE,SAAS,EAAE,CAAC;YAC7D,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,wBAAwB,CAAC,OAAuB,EAAE,SAAiB;QACvE,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,OAAO,OAAO,CAAC,GAAG,CAAC;YACnB,OAAO,OAAO,CAAC,GAAG,CAAC;YACnB,OAAO,OAAO,CAAC,QAAQ,CAAC;YACxB,OAAO;QACT,CAAC;QACD,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;QACxC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACpE,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACpF,OAAO;QACT,CAAC;QACD,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACpC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,OAAO,OAAO,CAAC,GAAG,CAAC;QACrB,CAAC;QACD,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,OAAO,OAAO,CAAC,GAAG,CAAC;QACrB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;QACnD,OAAO,gBAAgB,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC5F,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAW;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QAC9C,OAAO,gBAAgB,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAClF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,UAAU,CAAC,KAAgC,CAAC,CAAC;QAC3D,yFAAyF;QACzF,kFAAkF;QAClF,IAAI,CAAC,QAAQ,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;YACxC,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,OAAO,GAAG,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,GAAG,KAAK,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC/D,OAAO,CAAC,WAAW,GAAG;oBACpB,KAAK,EAAE,KAAuB;oBAC9B,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAChC,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,GAAG,KAAK,eAAe,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,OAAe;QACnC,MAAM,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3F,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,gBAAgB;IAClB,OAAO,CAAgB;IACvB,OAAO,CAAkB;IAElC,YAAY,MAAqB,EAAE,MAAuB;QACxD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAU;QACnB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,CAAC;YAC1C,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YAC9D,IAAI,CAAC,wBAAwB,EAAE,CAAC;gBAC9B,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;QACD,yEAAyE;QACzE,MAAM,MAAM,GAAG,QAAQ,CAAC,0BAA0B,CAAC;YACjD,CAAC,CAAC,QAAQ,CAAC,WAAW;YACtB,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,iBAAiB,CAAC,CAAC;QACxE,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,CAAC;YACpE,OAAO,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAoB,CAAC;QAChE,CAAC;QACD,MAAM,QAAQ,GAAG,qBAAqB,EAAE,EAAE,oBAAoB,CAAC;QAC/D,MAAM,MAAM,GACV,QAAQ,EAAE,QAAQ,KAAK,QAAQ,CAAC,SAAS;YACvC,CAAC,CAAC,QAAQ,CAAC,KAAK;YAChB,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC5C,OAAO,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAoB,CAAC;IACvF,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,IAAI,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,IAAI,qBAAqB,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,IAAI,qBAAqB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAC/D,CAAC;CACF;AAED,MAAM,UAAU,uBAAuB,CACrC,MAAqB,EACrB,MAAuB;IAEvB,MAAM,KAAK,GAAG,IAAI,kBAAkB,EAAE,CAAC;IACvC,OAAO,CAAC,IAAI,EAAE,EAAE,CACd,IAAI,KAAK,QAAQ;QACf,CAAC,CAAC,IAAI,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC;QACtC,CAAC,CAAC,IAAI,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC"}
|
package/dist/apiClient.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type OidcAccountQuery, type OidcAuthContext, type OidcClientMetadata, type OidcClientResource, type OidcEdgeConfigResponse, type OidcEdgeEvent, type OidcJwksResponse, type OidcPayloadModel, type OidcPayloadRecord, type OidcPayloadUpsertRequest, type OidcPayloadUpsertResponse, type OidcSessionBindRequest, type OidcSessionRevokeRequest, type OidcSignRequest, type OidcSignResponse } from '@seamless-auth/types';
|
|
2
|
+
import { type OidcProviderAccount } from './accountClaims.js';
|
|
2
3
|
export declare const SERVICE_TOKEN_SUBJECT = "seamless-oidc-provider";
|
|
3
4
|
export interface OidcApiClientOptions {
|
|
4
5
|
apiUrl: string;
|
|
@@ -27,7 +28,7 @@ export declare class OidcApiClient {
|
|
|
27
28
|
clientResources(id: string): Promise<OidcClientResource[]>;
|
|
28
29
|
verifySecret(id: string, secret: string): Promise<boolean>;
|
|
29
30
|
/** Answers only for the user behind a session holding a grant for `clientId`. */
|
|
30
|
-
account(id: string, binding: OidcAccountQuery): Promise<
|
|
31
|
+
account(id: string, binding: OidcAccountQuery): Promise<OidcProviderAccount | undefined>;
|
|
31
32
|
/**
|
|
32
33
|
* Binds the session to `clientId` with the user's own access token for that session. The
|
|
33
34
|
* API answers nothing about a session, and signs nothing for it, until it is bound.
|
package/dist/apiClient.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* See LICENSE file in the project root for full license information
|
|
5
5
|
*/
|
|
6
6
|
import { createServiceToken, DEV_JWKS_KID, SERVICE_TOKEN_AUDIENCE, SERVICE_TOKEN_ISSUER, } from '@seamless-auth/core';
|
|
7
|
-
import {
|
|
7
|
+
import { OidcAuthContextSchema, OidcClientMetadataSchema, OidcClientResourcesResponseSchema, OidcEdgeConfigResponseSchema, OidcEdgeRoutes, OidcJwksResponseSchema, OidcPayloadConsumeResponseSchema, OidcPayloadRecordSchema, OidcPayloadUpsertResponseSchema, OidcSignRefusalSchema, OidcSignResponseSchema, OidcVerifySecretResponseSchema, } from '@seamless-auth/types';
|
|
8
|
+
import { OidcProviderAccountSchema } from './accountClaims.js';
|
|
8
9
|
import { OidcApiError, OidcSignRefusedError } from './errors.js';
|
|
9
10
|
import { currentRequestContext } from './requestContext.js';
|
|
10
11
|
export const SERVICE_TOKEN_SUBJECT = 'seamless-oidc-provider';
|
|
@@ -115,7 +116,7 @@ export class OidcApiClient {
|
|
|
115
116
|
account(id, binding) {
|
|
116
117
|
const query = new URLSearchParams(binding).toString();
|
|
117
118
|
return this.#request('GET', `${routePath(OidcEdgeRoutes.account, { id })}?${query}`, {
|
|
118
|
-
schema:
|
|
119
|
+
schema: OidcProviderAccountSchema,
|
|
119
120
|
allowNotFound: true,
|
|
120
121
|
});
|
|
121
122
|
}
|
package/dist/apiClient.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiClient.js","sourceRoot":"","sources":["../src/apiClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,
|
|
1
|
+
{"version":3,"file":"apiClient.js","sourceRoot":"","sources":["../src/apiClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { HostedUi } from '@seamless-auth/types';
|
|
2
|
+
export declare function contrastRatio(a: string, b: string): number;
|
|
3
|
+
/** The color pairs a branded palette leaves below WCAG 2.2 AA, as readable lines. */
|
|
4
|
+
export declare function brandingContrastProblems(hostedUi: HostedUi | undefined): string[];
|