@owlmeans/server-oidc-rp 0.1.6 → 0.1.8
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 +17 -0
- package/agent-meta/instructions/server-oidc-rp.instructions.md +68 -0
- package/agent-meta/manifest.json +23 -0
- package/agent-meta/skills/server-oidc-rp/SKILL.md +85 -0
- package/build/actions/process.d.ts.map +1 -1
- package/build/actions/process.js +5 -0
- package/build/actions/process.js.map +1 -1
- package/build/index.d.ts +2 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/utils/permissions.d.ts +9 -0
- package/build/utils/permissions.d.ts.map +1 -0
- package/build/utils/permissions.js +20 -0
- package/build/utils/permissions.js.map +1 -0
- package/build/wrapper.d.ts.map +1 -1
- package/build/wrapper.js +11 -0
- package/build/wrapper.js.map +1 -1
- package/package.json +17 -17
- package/src/actions/process.ts +6 -0
- package/src/index.ts +2 -0
- package/src/utils/permissions.ts +27 -0
- package/src/wrapper.ts +12 -0
package/README.md
CHANGED
|
@@ -103,3 +103,20 @@ const oidc = context.service<OidcClientService>(OIDC_SERVICE)
|
|
|
103
103
|
- [`@owlmeans/server-auth`](../server-auth) — works alongside the OIDC guard for token verification
|
|
104
104
|
- [`@owlmeans/server-context`](../server-context) — base context where services are registered
|
|
105
105
|
- [`@owlmeans/auth-common`](../auth-common) — `DEFAULT_GUARD` co-attached via `setupOidcGuard`
|
|
106
|
+
|
|
107
|
+
<!-- owlmeans:agent-guidance:start -->
|
|
108
|
+
## Agent guidance
|
|
109
|
+
|
|
110
|
+
This package ships embedded Claude Code skills and GitHub Copilot instructions under
|
|
111
|
+
`agent-meta/`. After installing your `@owlmeans/*` packages, run the OwlMeans
|
|
112
|
+
agent-skills installer to place them into your project's native locations
|
|
113
|
+
(`.claude/skills/` and `.github/instructions/`):
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
npx @owlmeans/agent-skills
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The embedded files are version-matched to this package release. Do not edit them
|
|
120
|
+
directly — they are regenerated on each publish. To contribute guidance edits,
|
|
121
|
+
open a PR against the source monorepo.
|
|
122
|
+
<!-- owlmeans:agent-guidance:end -->
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "How to use @owlmeans/server-oidc-rp — OIDC relying party. appendOidcGuard(), makeOidcWrappingService(), makeOidcGate(), setupOidcGuard() to wire OIDC into a server context."
|
|
3
|
+
applyTo: "**/context.ts, **/modules.ts, **/*.ts, **/*.tsx"
|
|
4
|
+
---
|
|
5
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
6
|
+
|
|
7
|
+
# @owlmeans/server-oidc-rp
|
|
8
|
+
|
|
9
|
+
**Layer:** Server
|
|
10
|
+
**Install:** `"@owlmeans/server-oidc-rp": "^0.1.8"` in `dependencies`
|
|
11
|
+
|
|
12
|
+
## Key Exports
|
|
13
|
+
|
|
14
|
+
| Export | Description |
|
|
15
|
+
|--------|-------------|
|
|
16
|
+
| `appendOidcGuard<C, T>(context)` | Add OIDC auth guard to context |
|
|
17
|
+
| `makeOidcWrappingService()` | OIDC token service factory |
|
|
18
|
+
| `makeOidcGate()` | OIDC gate factory (used by guards) |
|
|
19
|
+
| `setupOidcGuard(modules, options?)` | Wire OIDC guard onto modules |
|
|
20
|
+
| Constants | OIDC service / guard aliases |
|
|
21
|
+
| `OidcRp` types | RP-side config and token shapes |
|
|
22
|
+
|
|
23
|
+
## Subpath Exports
|
|
24
|
+
|
|
25
|
+
- `./auth`, `./auth/plugins`
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// context.ts
|
|
31
|
+
import { appendOidcGuard, makeOidcWrappingService, makeOidcGate } from '@owlmeans/server-oidc-rp'
|
|
32
|
+
context.registerService(makeOidcWrappingService())
|
|
33
|
+
context.registerService(makeOidcGate())
|
|
34
|
+
appendOidcGuard<C, T>(context)
|
|
35
|
+
|
|
36
|
+
// modules.ts
|
|
37
|
+
import { setupOidcGuard } from '@owlmeans/server-oidc-rp'
|
|
38
|
+
setupOidcGuard(appModules)
|
|
39
|
+
|
|
40
|
+
// config.ts
|
|
41
|
+
cfg.oidc.providers.push({
|
|
42
|
+
clientId: OIDC_ADMIN_CLIENT,
|
|
43
|
+
basePath: 'realms/master',
|
|
44
|
+
service: OIDC_PRODUCT,
|
|
45
|
+
secret: '/etc/master-secret/oidc-admin-secret',
|
|
46
|
+
internal: true
|
|
47
|
+
})
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Product-Viable Usage Notes
|
|
51
|
+
|
|
52
|
+
- Viable uses `makeOidcClientService()` to read provider descriptors from `cfg.oidc.providers`, including Google and internal admin providers.
|
|
53
|
+
- `findProvider(predicate)`, `hasProvider(params)`, and `entityToClientId(params)` are the preferred provider lookup helpers; avoid scanning config ad hoc in downstream code.
|
|
54
|
+
- `setupAuthServiceModules(managerModules, AUTH_API)` exposes provider-list and token-update service modules protected by `GUARD_ED25519`.
|
|
55
|
+
- When a downstream app uses OIDC/Google only for login and maps users into `@owlmeans/server-auth-identity`, do not reintroduce `appendOidcGuard()`, `makeOidcGate()`, or `setupOidcGuard()` as product authorization. Use a product-specific `GateService` over local identity data.
|
|
56
|
+
|
|
57
|
+
## Integrated-IAM permissions claim (Phase 3)
|
|
58
|
+
|
|
59
|
+
- `extractPermissionSets(claim)` (exported) shape-validates a `permissions` token claim into
|
|
60
|
+
`PermissionSet[]`; non-conforming claims (e.g. anything Keycloak emits) return `undefined`.
|
|
61
|
+
- `authenticate` (actions/process.ts) maps a conforming id_token `permissions` claim into
|
|
62
|
+
`Auth.permissions` + `permissioned: true`; the wrapping service re-extracts it on token refresh.
|
|
63
|
+
- `createGateModel` is exported for `@owlmeans/server-iam`, whose `makeIamGate` asserts claims first
|
|
64
|
+
and falls back to this UMA2 model — registered under the same `OIDC_GATE` alias by `appendIam()`.
|
|
65
|
+
|
|
66
|
+
## Depends On
|
|
67
|
+
|
|
68
|
+
- `@owlmeans/oidc`, `@owlmeans/server-auth`, `@owlmeans/server-context`, `@owlmeans/server-entrypoint`, `@owlmeans/auth-common`, `@owlmeans/basic-keys`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"package": "@owlmeans/server-oidc-rp",
|
|
4
|
+
"version": "0.1.8",
|
|
5
|
+
"generatedAt": "2026-06-11T16:30:27.172Z",
|
|
6
|
+
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
|
+
"entries": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "skill",
|
|
10
|
+
"name": "server-oidc-rp",
|
|
11
|
+
"category": "package-specific",
|
|
12
|
+
"file": "skills/server-oidc-rp/SKILL.md",
|
|
13
|
+
"canonicalPath": ".claude/skills/server-oidc-rp/SKILL.md"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"kind": "instruction",
|
|
17
|
+
"name": "server-oidc-rp",
|
|
18
|
+
"category": "package-specific",
|
|
19
|
+
"file": "instructions/server-oidc-rp.instructions.md",
|
|
20
|
+
"canonicalPath": ".github/instructions/server-oidc-rp.instructions.md"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: server-oidc-rp
|
|
3
|
+
description: How to use @owlmeans/server-oidc-rp — OIDC relying party. appendOidcGuard(), makeOidcWrappingService(), makeOidcGate() to wire OIDC into a server context; setupOidcGuard() to attach the guard to module declarations. Auto-invoked when importing server-oidc-rp helpers.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
7
|
+
|
|
8
|
+
# @owlmeans/server-oidc-rp
|
|
9
|
+
|
|
10
|
+
**Layer:** Server
|
|
11
|
+
**Install:** `"@owlmeans/server-oidc-rp": "^0.1.8"` in `dependencies`
|
|
12
|
+
|
|
13
|
+
## Key Exports
|
|
14
|
+
|
|
15
|
+
| Export | Description |
|
|
16
|
+
|--------|-------------|
|
|
17
|
+
| `appendOidcGuard<C, T>(context)` | Add OIDC auth guard to context |
|
|
18
|
+
| `makeOidcWrappingService()` | OIDC token service factory |
|
|
19
|
+
| `makeOidcGate()` | OIDC gate factory (used by guards) |
|
|
20
|
+
| `setupOidcGuard(modules, options?)` | Wire OIDC guard onto module declarations |
|
|
21
|
+
| Constants | OIDC service / guard aliases |
|
|
22
|
+
| `OidcRp` types | RP-side config and token shapes |
|
|
23
|
+
|
|
24
|
+
## Subpath Exports
|
|
25
|
+
|
|
26
|
+
- `./auth` — auth integration helpers
|
|
27
|
+
- `./auth/plugins` — pluggable token verifiers
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
### In `context.ts`
|
|
32
|
+
```typescript
|
|
33
|
+
import { appendOidcGuard, makeOidcWrappingService, makeOidcGate } from '@owlmeans/server-oidc-rp'
|
|
34
|
+
|
|
35
|
+
context.registerService(makeOidcWrappingService())
|
|
36
|
+
context.registerService(makeOidcGate())
|
|
37
|
+
appendOidcGuard<C, T>(context)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### In `modules.ts`
|
|
41
|
+
```typescript
|
|
42
|
+
import { setupOidcGuard } from '@owlmeans/server-oidc-rp'
|
|
43
|
+
setupOidcGuard(appModules)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Configure OIDC providers in `config.ts`
|
|
47
|
+
```typescript
|
|
48
|
+
cfg.oidc ??= {}
|
|
49
|
+
cfg.oidc.providers ??= []
|
|
50
|
+
cfg.oidc.providers.push({
|
|
51
|
+
clientId: OIDC_ADMIN_CLIENT,
|
|
52
|
+
basePath: 'realms/master',
|
|
53
|
+
service: OIDC_PRODUCT,
|
|
54
|
+
secret: '/etc/master-secret/oidc-admin-secret',
|
|
55
|
+
internal: true
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Product-Viable Usage Notes
|
|
60
|
+
|
|
61
|
+
- Viable uses `makeOidcClientService()` to read provider descriptors from `cfg.oidc.providers`, including Google and internal admin providers.
|
|
62
|
+
- `findProvider(predicate)`, `hasProvider(params)`, and `entityToClientId(params)` are the preferred provider lookup helpers; avoid scanning config ad hoc in downstream code.
|
|
63
|
+
- `setupAuthServiceModules(managerModules, AUTH_API)` exposes provider-list and token-update service modules protected by `GUARD_ED25519`.
|
|
64
|
+
- When a downstream app uses OIDC/Google only for login and maps users into `@owlmeans/server-auth-identity`, do not reintroduce `appendOidcGuard()`, `makeOidcGate()`, or `setupOidcGuard()` as product authorization. Use a product-specific `GateService` over local identity data.
|
|
65
|
+
|
|
66
|
+
## Public type contract (isolation principle)
|
|
67
|
+
|
|
68
|
+
`openid-client` types **never appear in this package's public exports**. All public types are OwlMeans-owned:
|
|
69
|
+
|
|
70
|
+
| Owned type | Replaces upstream | Description |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `OidcTokenSet` | `TokenEndpointResponse & TokenEndpointResponseHelpers` | `access_token`, `refresh_token`, `id_token`, `token_type`, `expires_in`, `scope` |
|
|
73
|
+
| `OidcTokenSetParameters` | `TokenEndpointResponse` | Subset without helper methods |
|
|
74
|
+
| `OidcGrantChecks` | `AuthorizationCodeGrantChecks` | `{ pkceCodeVerifier?: string; idTokenExpected?: boolean }` |
|
|
75
|
+
| `OidcServerMetadata` | `ServerMetadata` | Issuer and endpoint metadata |
|
|
76
|
+
| `OidcIntrospectionResponse` | `IntrospectionResponse` | Active, scope, sub, client_id |
|
|
77
|
+
| `OidcClientDescriptor` | `Configuration` (opaque) | Pass-through; consumers must never read its internals |
|
|
78
|
+
|
|
79
|
+
Upstream `openid-client` types are imported **only** in `src/service.ts`; mappings happen at the method boundaries. This keeps future library swaps confined to that one file.
|
|
80
|
+
|
|
81
|
+
## Depends On
|
|
82
|
+
|
|
83
|
+
- `@owlmeans/oidc`, `@owlmeans/server-auth`, `@owlmeans/server-context`, `@owlmeans/server-entrypoint`
|
|
84
|
+
- `@owlmeans/auth-common`, `@owlmeans/basic-keys`
|
|
85
|
+
- `openid-client@6.8.4` (exact), `jose@6.2.3` (exact) — see [[oidc-versions]]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/actions/process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/actions/process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AAoBzE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,EAAE,sBAoFzB,CAAA"}
|
package/build/actions/process.js
CHANGED
|
@@ -11,6 +11,8 @@ import { TRUSTED } from '@owlmeans/config';
|
|
|
11
11
|
import { EnvelopeKind, makeEnvelopeModel } from '@owlmeans/basic-envelope';
|
|
12
12
|
import { OIDC_AUTH_LIFTETIME } from '../consts.js';
|
|
13
13
|
import { wrapper } from '../utils/wrapped.js';
|
|
14
|
+
import { extractPermissionSets } from '../utils/permissions.js';
|
|
15
|
+
import { PERMISSIONS_CLAIM } from '@owlmeans/oidc';
|
|
14
16
|
/**
|
|
15
17
|
* Authentication method links together OIDC and OwlMeans auth.
|
|
16
18
|
* 1. We authenticate OIDC redirect back params with the classic OIDC client.
|
|
@@ -44,6 +46,8 @@ export const authenticate = handleBody(async ({ authUrl, ...params }, ctx) => {
|
|
|
44
46
|
console.log('List provided user permisssions', decodeJwt(tokenSet.access_token));
|
|
45
47
|
const id = decodeJwt(tokenSet.id_token);
|
|
46
48
|
console.log('token set', tokenSet, tokenSet.claims(), id);
|
|
49
|
+
// Integrated IAM mode: the provider mints the subject's PermissionSet[] into the id_token
|
|
50
|
+
const permissions = extractPermissionSets(id[PERMISSIONS_CLAIM]);
|
|
47
51
|
let user = {
|
|
48
52
|
type: OIDC_WRAPPED_TOKEN,
|
|
49
53
|
token,
|
|
@@ -65,6 +69,7 @@ export const authenticate = handleBody(async ({ authUrl, ...params }, ctx) => {
|
|
|
65
69
|
// from the OwlMeans Auth intead
|
|
66
70
|
// profileId: user?.userId,
|
|
67
71
|
entityId: cfg.entityId,
|
|
72
|
+
...(permissions != null ? { permissions, permissioned: true } : {}),
|
|
68
73
|
isUser: true,
|
|
69
74
|
createdAt: new Date(),
|
|
70
75
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/actions/process.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,GAAG,MAAM,KAAK,CAAA;AACrB,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAEzD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAA;AAChC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/actions/process.ts"],"names":[],"mappings":"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"}
|
package/build/index.d.ts
CHANGED
|
@@ -5,4 +5,6 @@ export * from './guard.js';
|
|
|
5
5
|
export * from './gate.js';
|
|
6
6
|
export * from './modules.js';
|
|
7
7
|
export * from './wrapper.js';
|
|
8
|
+
export { createGateModel } from './model/gate.js';
|
|
9
|
+
export { extractPermissionSets } from './utils/permissions.js';
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,oBAAoB,EACpB,YAAY,EACZ,sBAAsB,EACtB,eAAe,EACf,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,MAAM,EACN,OAAO,EACP,qBAAqB,EACrB,WAAW,EACX,kBAAkB,GACnB,MAAM,YAAY,CAAA;AACnB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,oBAAoB,EACpB,YAAY,EACZ,sBAAsB,EACtB,eAAe,EACf,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,MAAM,EACN,OAAO,EACP,qBAAqB,EACrB,WAAW,EACX,kBAAkB,GACnB,MAAM,YAAY,CAAA;AACnB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA"}
|
package/build/index.js
CHANGED
|
@@ -4,4 +4,6 @@ export * from './guard.js';
|
|
|
4
4
|
export * from './gate.js';
|
|
5
5
|
export * from './modules.js';
|
|
6
6
|
export * from './wrapper.js';
|
|
7
|
+
export { createGateModel } from './model/gate.js';
|
|
8
|
+
export { extractPermissionSets } from './utils/permissions.js';
|
|
7
9
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PermissionSet } from '@owlmeans/auth';
|
|
2
|
+
/**
|
|
3
|
+
* Shape-validates a `permissions` token claim into PermissionSet[].
|
|
4
|
+
* Returns undefined unless the claim is an array of conforming sets — Keycloak
|
|
5
|
+
* tokens (or any foreign claim) never produce a conforming value, which keeps
|
|
6
|
+
* the claims-based gate path inert outside the integrated IAM mode.
|
|
7
|
+
*/
|
|
8
|
+
export declare const extractPermissionSets: (claim: unknown) => PermissionSet[] | undefined;
|
|
9
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/utils/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,OAAO,KAAG,aAAa,EAAE,GAAG,SAkBxE,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shape-validates a `permissions` token claim into PermissionSet[].
|
|
3
|
+
* Returns undefined unless the claim is an array of conforming sets — Keycloak
|
|
4
|
+
* tokens (or any foreign claim) never produce a conforming value, which keeps
|
|
5
|
+
* the claims-based gate path inert outside the integrated IAM mode.
|
|
6
|
+
*/
|
|
7
|
+
export const extractPermissionSets = (claim) => {
|
|
8
|
+
if (!Array.isArray(claim) || claim.length < 1) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
const sets = claim.filter((set) => set != null && typeof set === 'object'
|
|
12
|
+
&& typeof set.scope === 'string'
|
|
13
|
+
&& set.permissions != null
|
|
14
|
+
&& typeof set.permissions === 'object'
|
|
15
|
+
&& !Array.isArray(set.permissions)
|
|
16
|
+
&& (set.resources == null || (Array.isArray(set.resources)
|
|
17
|
+
&& set.resources.every(res => typeof res === 'string'))));
|
|
18
|
+
return sets.length > 0 ? sets : undefined;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/utils/permissions.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAc,EAA+B,EAAE;IACnF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAwB,EAAE,CACtD,GAAG,IAAI,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;WACnC,OAAQ,GAAqB,CAAC,KAAK,KAAK,QAAQ;WAC/C,GAAqB,CAAC,WAAW,IAAI,IAAI;WAC1C,OAAQ,GAAqB,CAAC,WAAW,KAAK,QAAQ;WACtD,CAAC,KAAK,CAAC,OAAO,CAAE,GAAqB,CAAC,WAAW,CAAC;WAClD,CAAE,GAAqB,CAAC,SAAS,IAAI,IAAI,IAAI,CAC9C,KAAK,CAAC,OAAO,CAAE,GAAqB,CAAC,SAAS,CAAC;eAC3C,GAAqB,CAAC,SAAU,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAC3E,CAAC,CACH,CAAA;IAED,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;AAC3C,CAAC,CAAA"}
|
package/build/wrapper.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAyC,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAyC,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAc/F,eAAO,MAAM,uBAAuB,QAAO,kBAqH1C,CAAA"}
|
package/build/wrapper.js
CHANGED
|
@@ -5,6 +5,9 @@ import { OIDC_WRAPPED_TOKEN, WRAPPED_OIDC } from '@owlmeans/oidc';
|
|
|
5
5
|
import { cache, managedId } from './utils/cache.js';
|
|
6
6
|
import { authService, DEFAULT_ALIAS, OIDC_AUTH_LIFTETIME, OIDC_WRAP_FRESHNESS } from './consts.js';
|
|
7
7
|
import days from 'dayjs';
|
|
8
|
+
import { decodeJwt } from 'jose';
|
|
9
|
+
import { PERMISSIONS_CLAIM } from '@owlmeans/oidc';
|
|
10
|
+
import { extractPermissionSets } from './utils/permissions.js';
|
|
8
11
|
import { TRUSTED } from '@owlmeans/config';
|
|
9
12
|
import { AUTH_SRV_KEY } from '@owlmeans/server-auth';
|
|
10
13
|
import { trust } from '@owlmeans/auth-common/utils';
|
|
@@ -77,6 +80,14 @@ export const makeOidcWrappingService = () => {
|
|
|
77
80
|
...user,
|
|
78
81
|
createdAt: new Date()
|
|
79
82
|
};
|
|
83
|
+
// Keep integrated-IAM permission grants fresh across token refreshes
|
|
84
|
+
if (tokenSet.id_token != null) {
|
|
85
|
+
const permissions = extractPermissionSets(decodeJwt(tokenSet.id_token)[PERMISSIONS_CLAIM]);
|
|
86
|
+
if (permissions != null) {
|
|
87
|
+
updatedUser.permissions = permissions;
|
|
88
|
+
updatedUser.permissioned = true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
80
91
|
const trusted = await trust(ctx, TRUSTED, ctx.cfg.alias ?? ctx.cfg.service);
|
|
81
92
|
const authorization = await makeEnvelopeModel(OIDC_WRAPPED_TOKEN)
|
|
82
93
|
.send(updatedUser, null).sign(trusted.key, EnvelopeKind.Token);
|
package/build/wrapper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE3E,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACjE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEnD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAClG,OAAO,IAAI,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../src/wrapper.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/server-oidc-rp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@owlmeans/dep-config": "workspace:*",
|
|
40
|
-
"@owlmeans/test-auth": "^0.1.
|
|
40
|
+
"@owlmeans/test-auth": "^0.1.8",
|
|
41
41
|
"@types/bun": "^1.3.0",
|
|
42
42
|
"@types/node": "^24.10.1",
|
|
43
43
|
"nodemon": "^3.1.11",
|
|
@@ -46,21 +46,21 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@noble/hashes": "^1.5.0",
|
|
49
|
-
"@owlmeans/auth": "^0.1.
|
|
50
|
-
"@owlmeans/auth-common": "^0.1.
|
|
51
|
-
"@owlmeans/basic-envelope": "^0.1.
|
|
52
|
-
"@owlmeans/client-entrypoint": "^0.1.
|
|
53
|
-
"@owlmeans/config": "^0.1.
|
|
54
|
-
"@owlmeans/context": "^0.1.
|
|
55
|
-
"@owlmeans/did": "^0.1.
|
|
56
|
-
"@owlmeans/entrypoint": "^0.1.
|
|
57
|
-
"@owlmeans/oidc": "^0.1.
|
|
58
|
-
"@owlmeans/resource": "^0.1.
|
|
59
|
-
"@owlmeans/route": "^0.1.
|
|
60
|
-
"@owlmeans/server-api": "^0.1.
|
|
61
|
-
"@owlmeans/server-auth": "^0.1.
|
|
62
|
-
"@owlmeans/server-context": "^0.1.
|
|
63
|
-
"@owlmeans/server-entrypoint": "^0.1.
|
|
49
|
+
"@owlmeans/auth": "^0.1.8",
|
|
50
|
+
"@owlmeans/auth-common": "^0.1.8",
|
|
51
|
+
"@owlmeans/basic-envelope": "^0.1.8",
|
|
52
|
+
"@owlmeans/client-entrypoint": "^0.1.8",
|
|
53
|
+
"@owlmeans/config": "^0.1.8",
|
|
54
|
+
"@owlmeans/context": "^0.1.8",
|
|
55
|
+
"@owlmeans/did": "^0.1.8",
|
|
56
|
+
"@owlmeans/entrypoint": "^0.1.8",
|
|
57
|
+
"@owlmeans/oidc": "^0.1.8",
|
|
58
|
+
"@owlmeans/resource": "^0.1.8",
|
|
59
|
+
"@owlmeans/route": "^0.1.8",
|
|
60
|
+
"@owlmeans/server-api": "^0.1.8",
|
|
61
|
+
"@owlmeans/server-auth": "^0.1.8",
|
|
62
|
+
"@owlmeans/server-context": "^0.1.8",
|
|
63
|
+
"@owlmeans/server-entrypoint": "^0.1.8",
|
|
64
64
|
"@scure/base": "^1.1.9",
|
|
65
65
|
"dayjs": "^1.11.13",
|
|
66
66
|
"jose": "6.2.3",
|
package/src/actions/process.ts
CHANGED
|
@@ -15,6 +15,8 @@ import { TRUSTED } from '@owlmeans/config'
|
|
|
15
15
|
import { EnvelopeKind, makeEnvelopeModel } from '@owlmeans/basic-envelope'
|
|
16
16
|
import { OIDC_AUTH_LIFTETIME } from '../consts.js'
|
|
17
17
|
import { wrapper } from '../utils/wrapped.js'
|
|
18
|
+
import { extractPermissionSets } from '../utils/permissions.js'
|
|
19
|
+
import { PERMISSIONS_CLAIM } from '@owlmeans/oidc'
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Authentication method links together OIDC and OwlMeans auth.
|
|
@@ -70,6 +72,9 @@ export const authenticate: RefedEntrypointHandler = handleBody(async (
|
|
|
70
72
|
id
|
|
71
73
|
)
|
|
72
74
|
|
|
75
|
+
// Integrated IAM mode: the provider mints the subject's PermissionSet[] into the id_token
|
|
76
|
+
const permissions = extractPermissionSets(id[PERMISSIONS_CLAIM])
|
|
77
|
+
|
|
73
78
|
let user: Auth = {
|
|
74
79
|
type: OIDC_WRAPPED_TOKEN,
|
|
75
80
|
token,
|
|
@@ -91,6 +96,7 @@ export const authenticate: RefedEntrypointHandler = handleBody(async (
|
|
|
91
96
|
// from the OwlMeans Auth intead
|
|
92
97
|
// profileId: user?.userId,
|
|
93
98
|
entityId: cfg.entityId,
|
|
99
|
+
...(permissions != null ? { permissions, permissioned: true } : {}),
|
|
94
100
|
isUser: true,
|
|
95
101
|
createdAt: new Date(),
|
|
96
102
|
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PermissionSet } from '@owlmeans/auth'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shape-validates a `permissions` token claim into PermissionSet[].
|
|
5
|
+
* Returns undefined unless the claim is an array of conforming sets — Keycloak
|
|
6
|
+
* tokens (or any foreign claim) never produce a conforming value, which keeps
|
|
7
|
+
* the claims-based gate path inert outside the integrated IAM mode.
|
|
8
|
+
*/
|
|
9
|
+
export const extractPermissionSets = (claim: unknown): PermissionSet[] | undefined => {
|
|
10
|
+
if (!Array.isArray(claim) || claim.length < 1) {
|
|
11
|
+
return undefined
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const sets = claim.filter((set): set is PermissionSet =>
|
|
15
|
+
set != null && typeof set === 'object'
|
|
16
|
+
&& typeof (set as PermissionSet).scope === 'string'
|
|
17
|
+
&& (set as PermissionSet).permissions != null
|
|
18
|
+
&& typeof (set as PermissionSet).permissions === 'object'
|
|
19
|
+
&& !Array.isArray((set as PermissionSet).permissions)
|
|
20
|
+
&& ((set as PermissionSet).resources == null || (
|
|
21
|
+
Array.isArray((set as PermissionSet).resources)
|
|
22
|
+
&& (set as PermissionSet).resources!.every(res => typeof res === 'string')
|
|
23
|
+
))
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
return sets.length > 0 ? sets : undefined
|
|
27
|
+
}
|
package/src/wrapper.ts
CHANGED
|
@@ -8,6 +8,9 @@ import { cache, managedId } from './utils/cache.js'
|
|
|
8
8
|
import type { Config, Context, OidcClientService, OidcTokenSetParameters } from './types.js'
|
|
9
9
|
import { authService, DEFAULT_ALIAS, OIDC_AUTH_LIFTETIME, OIDC_WRAP_FRESHNESS } from './consts.js'
|
|
10
10
|
import days from 'dayjs'
|
|
11
|
+
import { decodeJwt } from 'jose'
|
|
12
|
+
import { PERMISSIONS_CLAIM } from '@owlmeans/oidc'
|
|
13
|
+
import { extractPermissionSets } from './utils/permissions.js'
|
|
11
14
|
import type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
|
|
12
15
|
import { TRUSTED } from '@owlmeans/config'
|
|
13
16
|
import { AUTH_SRV_KEY } from '@owlmeans/server-auth'
|
|
@@ -95,6 +98,15 @@ export const makeOidcWrappingService = (): WrappedOIDCService => {
|
|
|
95
98
|
createdAt: new Date()
|
|
96
99
|
}
|
|
97
100
|
|
|
101
|
+
// Keep integrated-IAM permission grants fresh across token refreshes
|
|
102
|
+
if (tokenSet.id_token != null) {
|
|
103
|
+
const permissions = extractPermissionSets(decodeJwt(tokenSet.id_token)[PERMISSIONS_CLAIM])
|
|
104
|
+
if (permissions != null) {
|
|
105
|
+
updatedUser.permissions = permissions
|
|
106
|
+
updatedUser.permissioned = true
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
98
110
|
const trusted = await trust<Config, Context>(ctx, TRUSTED, ctx.cfg.alias ?? ctx.cfg.service)
|
|
99
111
|
const authorization = await makeEnvelopeModel<Auth>(OIDC_WRAPPED_TOKEN)
|
|
100
112
|
.send(updatedUser, null).sign(trusted.key, EnvelopeKind.Token)
|