@owlmeans/server-auth 0.1.18-rc.2 → 0.1.18-rc.20
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 +5 -5
- package/agent-meta/manifest.json +9 -2
- package/agent-meta/skills/server-auth/SKILL.md +93 -22
- package/agent-meta/skills/supervisor-auth/SKILL.md +128 -0
- package/build/entrypoints.d.ts +3 -0
- package/build/entrypoints.d.ts.map +1 -0
- package/build/{modules.js → entrypoints.js} +4 -4
- package/build/entrypoints.js.map +1 -0
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/manager/context.d.ts.map +1 -1
- package/build/manager/context.js +0 -1
- package/build/manager/context.js.map +1 -1
- package/build/manager/entrypoints.d.ts +2 -0
- package/build/manager/entrypoints.d.ts.map +1 -0
- package/build/manager/{modules.js → entrypoints.js} +5 -5
- package/build/manager/entrypoints.js.map +1 -0
- package/build/manager/index.d.ts +1 -1
- package/build/manager/index.d.ts.map +1 -1
- package/build/manager/index.js +1 -1
- package/build/manager/index.js.map +1 -1
- package/build/manager/main.js +2 -2
- package/build/manager/main.js.map +1 -1
- package/build/manager/model.d.ts.map +1 -1
- package/build/manager/model.js +14 -1
- package/build/manager/model.js.map +1 -1
- package/build/manager/plugins/basic-ed25519.js.map +1 -1
- package/build/manager/plugins/basic-rely.d.ts.map +1 -1
- package/build/manager/plugins/basic-rely.js +5 -5
- package/build/manager/plugins/basic-rely.js.map +1 -1
- package/build/manager/plugins/re-captcha.js +1 -1
- package/build/manager/plugins/re-captcha.js.map +1 -1
- package/build/manager/plugins/supervisor.js +3 -3
- package/build/manager/plugins/supervisor.js.map +1 -1
- package/build/manager/rely/flow.js +1 -1
- package/build/manager/rely/flow.js.map +1 -1
- package/build/manager/supervisor.d.ts +5 -5
- package/build/manager/supervisor.d.ts.map +1 -1
- package/build/manager/supervisor.js +4 -4
- package/build/manager/supervisor.js.map +1 -1
- package/build/service.js +1 -1
- package/build/service.js.map +1 -1
- package/package.json +26 -26
- package/src/{modules.ts → entrypoints.ts} +3 -3
- package/src/index.ts +1 -1
- package/src/manager/README.md +1 -1
- package/src/manager/context.ts +0 -2
- package/src/manager/{modules.ts → entrypoints.ts} +4 -4
- package/src/manager/index.ts +1 -1
- package/src/manager/main.ts +2 -2
- package/src/manager/model.ts +16 -1
- package/src/manager/plugins/basic-ed25519.ts +2 -2
- package/src/manager/plugins/basic-rely.ts +7 -6
- package/src/manager/plugins/re-captcha.ts +3 -3
- package/src/manager/plugins/supervisor.ts +4 -4
- package/src/manager/rely/flow.ts +1 -1
- package/src/manager/supervisor.ts +6 -6
- package/src/service.ts +1 -1
- package/tests/context.ts +1 -2
- package/tests/supervisor.spec.ts +6 -4
- package/build/.gitkeep +0 -0
- package/build/manager/modules.d.ts +0 -2
- package/build/manager/modules.d.ts.map +0 -1
- package/build/manager/modules.js.map +0 -1
- package/build/modules.d.ts +0 -3
- package/build/modules.d.ts.map +0 -1
- package/build/modules.js.map +0 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Server-side Ed25519 authentication service for OwlMeans backends.
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
bun add @owlmeans/server-auth
|
|
15
|
+
bun add @owlmeans/server-auth@^0.1.18-rc.17
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
## Usage
|
|
@@ -35,7 +35,7 @@ Reference the guard by alias when protecting routes:
|
|
|
35
35
|
import { DAUTH_GUARD } from '@owlmeans/server-app'
|
|
36
36
|
// same as DEFAULT_ALIAS from @owlmeans/server-auth
|
|
37
37
|
|
|
38
|
-
const
|
|
38
|
+
const adminEntrypoint = entrypoint(route('admin', '/admin'), guard(DAUTH_GUARD))
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
## API
|
|
@@ -60,12 +60,12 @@ Resource alias for the nonce replay-prevention cache.
|
|
|
60
60
|
|
|
61
61
|
- Register `appendAuthService(context)` before `appendAuthIdentityResources(context)` and product-specific gate services.
|
|
62
62
|
- Register `AUTH_CACHE` explicitly as a Redis resource when customizing the backend context.
|
|
63
|
-
- This package verifies bearer tokens and populates `request.auth`; authorization remains the job of
|
|
63
|
+
- This package verifies bearer tokens and populates `request.auth`; authorization remains the job of entrypoint gates and handler-level organization entity checks.
|
|
64
64
|
- Pair it with `@owlmeans/server-auth-identity` when external provider login should produce durable local account/profile/credentials records.
|
|
65
65
|
|
|
66
66
|
## Related Packages
|
|
67
67
|
|
|
68
|
-
- [`@owlmeans/auth-common`](../auth-common) — `GUARD_ED25519` constant and auth
|
|
68
|
+
- [`@owlmeans/auth-common`](../auth-common) — `GUARD_ED25519` constant and auth entrypoints
|
|
69
69
|
- [`@owlmeans/server-app`](../server-app) — `makeContext` calls `appendAuthService` by default
|
|
70
70
|
|
|
71
71
|
<!-- owlmeans:agent-guidance:start -->
|
|
@@ -76,7 +76,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
76
76
|
your project's skill store (`.agents/skills/`):
|
|
77
77
|
|
|
78
78
|
```sh
|
|
79
|
-
npx @owlmeans/agent-skills
|
|
79
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.14
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/server-auth",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-
|
|
4
|
+
"version": "0.1.18-rc.20",
|
|
5
|
+
"generatedAt": "2026-09-10T23:12:07.508Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -11,6 +11,13 @@
|
|
|
11
11
|
"category": "package-specific",
|
|
12
12
|
"file": "skills/server-auth/SKILL.md",
|
|
13
13
|
"canonicalPath": ".agents/skills/server-auth/SKILL.md"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"kind": "skill",
|
|
17
|
+
"name": "supervisor-auth",
|
|
18
|
+
"category": "multi-package",
|
|
19
|
+
"file": "skills/supervisor-auth/SKILL.md",
|
|
20
|
+
"canonicalPath": ".agents/skills/supervisor-auth/SKILL.md"
|
|
14
21
|
}
|
|
15
22
|
]
|
|
16
23
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: server-auth
|
|
3
|
-
description: How to use @owlmeans/server-auth — server
|
|
3
|
+
description: How to use @owlmeans/server-auth — the server side of OwlMeans authentication. Two halves in one package - appendAuthService/makeAuthService, which verify Ed25519 bearer tokens on an ordinary API server, and the ./manager subpath, which IS the auth manager service (challenge, plugin registry, credential envelope, rely). Auto-invoked when importing the server auth guard, registering an auth plugin, or building the auth manager.
|
|
4
4
|
user-invocable: false
|
|
5
5
|
---
|
|
6
6
|
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
@@ -8,41 +8,112 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/server-auth
|
|
9
9
|
|
|
10
10
|
**Layer:** Server
|
|
11
|
-
**Install:** `"@owlmeans/server-auth": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/server-auth": "^0.1.18-rc.20"` in `dependencies`
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Two halves, deliberately split by subpath:
|
|
14
|
+
|
|
15
|
+
- the **root** export is what every protected API server needs — the guard that verifies an
|
|
16
|
+
`Ed25519BasicToken` bearer and resolves an `Auth`;
|
|
17
|
+
- **`./manager`** is the auth manager application itself — it serves `/authentication/init` and
|
|
18
|
+
`/authentication/authenticate`, owns the plugin registry, and signs the credential envelope.
|
|
19
|
+
|
|
20
|
+
An ordinary service imports the root. Only the auth manager imports `./manager`.
|
|
21
|
+
|
|
22
|
+
## Key Exports — root
|
|
23
|
+
|
|
24
|
+
| Export | Description |
|
|
25
|
+
|--------|-------------|
|
|
26
|
+
| `appendAuthService(ctx, alias?)` | Register the guard on a server context and expose it as `context.auth()`. Registers a static `AUTH_CACHE` resource when the context has none |
|
|
27
|
+
| `makeAuthService(alias?)` | The guard service itself: `match`, `handle`, `unpack(token)`, `authenticate(token)` |
|
|
28
|
+
| `entrypoints` | `DISPATCHER` and `DISPATCHER_AUTHEN`, elevated — spread these into a service that accepts a manager-issued credential and exchanges it for a bearer |
|
|
29
|
+
| `DEFAULT_ALIAS` | `'auth'` — the guard's service alias, matching `DEFAULT_GUARD` |
|
|
30
|
+
| `AUTH_CACHE` | `'auth-cache'` — the single-use challenge store |
|
|
31
|
+
| `AUTH_SRV_KEY` | `'auth-service'` — the TRUSTED record whose key signs credential envelopes |
|
|
32
|
+
| `AUTHEN_TIMEFRAME` | `15 * 60 * 1000` — challenge lifetime and anti-replay window, in ms |
|
|
33
|
+
| `AuthService`, `AuthServiceAppend`, `AuthSpent` | Types |
|
|
34
|
+
| `makeRelyModel`, `makeProviderRely`, `makeConsumerRely`, `RelyOptions` | The rely (wallet handshake) models |
|
|
35
|
+
|
|
36
|
+
## Key Exports — `./manager`
|
|
14
37
|
|
|
15
38
|
| Export | Description |
|
|
16
39
|
|--------|-------------|
|
|
17
|
-
| `
|
|
18
|
-
| `
|
|
19
|
-
|
|
|
20
|
-
|
|
|
40
|
+
| `makeContext(cfg, customize?)` | A server context preconfigured with the API server, API client, socket service and static `AUTH_CACHE` |
|
|
41
|
+
| `main(ctx)` | Register the manager entrypoints, configure, init and listen |
|
|
42
|
+
| `entrypoints` | `AUTHEN`, `AUTHEN_INIT`, `AUTHEN_AUTHEN`, `AUTHEN_RELY`, the api-config entrypoints and the reCAPTCHA siteverify entrypoint |
|
|
43
|
+
| `authenticationInit`, `authenticate`, `rely` | The handlers those entrypoints elevate to: `init(request)` → challenge, `authenticate(credential)` → signed credential envelope, and the rely socket |
|
|
44
|
+
| `plugins`, `registerPlugin(type, factory)` | The plugin registry (also on `./manager/plugins`) |
|
|
45
|
+
| `appendSupervisorAuth(ctx, opts?)`, `setupInternalTokenCoguard(entrypoints, guard?)` | PK supervisor login — see the `supervisor-auth` skill |
|
|
46
|
+
| `createRelyService(alias?)`, `DEFAULT_RELY`, `RELY_TUNNEL` | The rely guard service |
|
|
47
|
+
| `AppConfig`, `AppContext`, `AuthModel`, `RelyService`, `RelyAllowanceRequest`, `RelyLinker`, `RelyCarrier` | Types |
|
|
48
|
+
|
|
49
|
+
`./manager` also re-exports the handful of symbols a manager application needs from elsewhere
|
|
50
|
+
(`config`, `service`, `TRUSTED`, `elevate`, `handleBody` / `handleRequest`, `backend`,
|
|
51
|
+
`GUARD_ED25519`, `AUTHEN*` aliases, `TrustedRecord`), so a manager app can be written against this
|
|
52
|
+
one import.
|
|
21
53
|
|
|
22
|
-
##
|
|
54
|
+
## Key Exports — `./manager/plugins`
|
|
23
55
|
|
|
24
|
-
|
|
25
|
-
|
|
56
|
+
| Export | Description |
|
|
57
|
+
|--------|-------------|
|
|
58
|
+
| `AuthPlugin` | `{ type, init(request), authenticate(credential) }` — `AuthModel` minus `rely` |
|
|
59
|
+
| `registerPlugin(type, factory)` | Add a plugin under a type string. The registry is a module-level singleton |
|
|
60
|
+
| `plugins` | The registry map |
|
|
61
|
+
| `getPlugin(type, context)`, `assertType(type, plugin)` | Resolution; `getPlugin` throws `AuthUnknown(type)` for an unregistered type |
|
|
62
|
+
| `basicEd25519`, `reCaptcha`, `basicRely` | The plugins registered out of the box, for `AuthenticationType.BasicEd25519`, `ReCaptcha` and `RelyHandshake` |
|
|
63
|
+
| `makeSupervisorPlugin(context, opts)` | The PK supervisor plugin factory |
|
|
64
|
+
| `RecpatchaResponse`, `RecaptchaRequest`, `RelyRecord`, `AuthRedisResource` | Types |
|
|
26
65
|
|
|
27
66
|
## Usage
|
|
28
67
|
|
|
68
|
+
Protect an ordinary API server:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { appendAuthService } from '@owlmeans/server-auth'
|
|
72
|
+
import { appendAuthIdentityResources } from '@owlmeans/server-auth-identity'
|
|
73
|
+
|
|
74
|
+
// in makeContext, after the db/cache services are appended:
|
|
75
|
+
appendAuthService(context)
|
|
76
|
+
appendAuthIdentityResources(context)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Add an authentication method to the manager:
|
|
80
|
+
|
|
29
81
|
```typescript
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
82
|
+
import { registerPlugin } from '@owlmeans/server-auth/manager/plugins'
|
|
83
|
+
import type { AuthPlugin } from '@owlmeans/server-auth/manager/plugins'
|
|
32
84
|
|
|
33
|
-
|
|
85
|
+
registerPlugin('my-method', context => ({
|
|
86
|
+
type: 'my-method',
|
|
87
|
+
init: async request => ({ challenge: /* unique per request */ '' }),
|
|
88
|
+
authenticate: async credential => {
|
|
89
|
+
// verify credential.credential, then set userId / profileId / entitySlug / role / scopes
|
|
90
|
+
return { token: '' } // '' keeps the manager's own challenge as the credential token
|
|
91
|
+
},
|
|
92
|
+
}) as AuthPlugin)
|
|
34
93
|
```
|
|
35
94
|
|
|
36
|
-
##
|
|
95
|
+
## Rules
|
|
37
96
|
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
97
|
+
- The guard verifies a bearer token and populates `req.auth`. It decides nothing about ownership or
|
|
98
|
+
permissions — pair it with `@owlmeans/entrypoint` gates, and keep a handler-level organization
|
|
99
|
+
check as a second line of defence.
|
|
100
|
+
- `AUTH_CACHE` is the anti-replay store: the manager burns each decoded challenge into it as a
|
|
101
|
+
create-once record with `AUTHEN_TIMEFRAME` TTL. `appendAuthService` registers a **static**
|
|
102
|
+
(in-process) resource when the context has none, which is correct for a single replica only —
|
|
103
|
+
register a Redis resource under the same alias before calling it in any scaled deployment.
|
|
104
|
+
- A plugin's `init` must return a challenge that is unique per request. A challenge that repeats
|
|
105
|
+
across independent attempts collides in `AUTH_CACHE` and surfaces as `AuthenFailed('challenge')`.
|
|
106
|
+
- The manager canonicalizes the organization entity: whatever slug (current, retired, or the frozen
|
|
107
|
+
key) a plugin leaves on `credential.entitySlug` is resolved through `ENTITY_RESOLVER` and replaced
|
|
108
|
+
with the current slug before the envelope is signed. An unresolvable value throws
|
|
109
|
+
`AuthenFailed('entity')`. Where no resolver is registered the value is passed through untouched.
|
|
110
|
+
- Pair this package with `@owlmeans/server-auth-identity` when an external provider (Google, OIDC,
|
|
111
|
+
email OTP) must map onto local account/profile/credential records.
|
|
43
112
|
|
|
44
113
|
## Depends On
|
|
45
114
|
|
|
46
|
-
- `@owlmeans/auth`, `@owlmeans/auth-common`
|
|
47
|
-
- `@owlmeans/
|
|
48
|
-
- `@owlmeans/
|
|
115
|
+
- `@owlmeans/auth`, `@owlmeans/auth-common` — types, aliases, `trust()`, `extractAuthToken`
|
|
116
|
+
- `@owlmeans/basic-envelope`, `@owlmeans/basic-keys` — envelope signing and Ed25519 verification
|
|
117
|
+
- `@owlmeans/server-context`, `@owlmeans/server-entrypoint`, `@owlmeans/server-api`
|
|
118
|
+
- `@owlmeans/config` — the `TRUSTED` config resource
|
|
119
|
+
- `@owlmeans/static-resource` — the default `AUTH_CACHE` backing
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: supervisor-auth
|
|
3
|
+
description: PK-based supervisor authentication — a development-only login where a holder of one of the project's trusted private keys mints a token for any user id/email (registering them on first use), bypassing external IdPs. Primary use is end-to-end tests. Covers appendSupervisorAuth (server + web), the supervisor plugin, and the @owlmeans/test-ui helpers. Use when wiring or testing supervisor auth.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
7
|
+
|
|
8
|
+
# PK-Based Supervisor Authentication
|
|
9
|
+
|
|
10
|
+
**Layer:** Server (`@owlmeans/server-auth`) + Web (`@owlmeans/web-auth`) + Tests (`@owlmeans/test-ui`)
|
|
11
|
+
|
|
12
|
+
A privileged, **development-only** auth path: a holder of one of the project's trusted private keys
|
|
13
|
+
(the allowlisted "supervisors") signs a server challenge to mint a valid owlmeans token for an
|
|
14
|
+
arbitrary user id / email — **without** Google/OIDC. Unknown users are **registered** on first use.
|
|
15
|
+
The primary purpose is deterministic **end-to-end tests** that authenticate against real environments.
|
|
16
|
+
|
|
17
|
+
It reuses the existing flow end-to-end: the plugin only **verifies the supervisor signature and
|
|
18
|
+
resolves/registers the user**, then hands the mutated credential back to the auth manager's own
|
|
19
|
+
model (which signs the credential envelope) and to the project's auth service (which exchanges it
|
|
20
|
+
for the final `Ed25519BasicToken` bearer). No new token-minting code.
|
|
21
|
+
|
|
22
|
+
## Type & payload
|
|
23
|
+
|
|
24
|
+
- `AuthenticationType.Supervisor = 'pk-supervisor'` (in `@owlmeans/auth`).
|
|
25
|
+
- Shared signed payload: `buildSupervisorPayload(challenge, userId, salt)` (in `@owlmeans/auth`) —
|
|
26
|
+
binds the signature to the **single-use server challenge** (replay protection), the target
|
|
27
|
+
`userId`, and a fresh client `salt`. The front-end packs `{ salt, signature }` (JSON) into
|
|
28
|
+
`AuthCredentials.credential`.
|
|
29
|
+
|
|
30
|
+
## Server: `appendSupervisorAuth` (from `@owlmeans/server-auth/manager`)
|
|
31
|
+
|
|
32
|
+
Call once on the **auth-manager** context (the one that serves `AUTHEN_INIT`/`AUTHEN_AUTHEN` and holds
|
|
33
|
+
`AUTH_SRV_KEY`), beside other plugin appends (e.g. `appendOtpPlugin`).
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { appendSupervisorAuth } from '@owlmeans/server-auth/manager'
|
|
37
|
+
|
|
38
|
+
appendSupervisorAuth(context, {
|
|
39
|
+
supervisors: ['master-key', 'super-user', 'shared-key'], // TRUSTED record `name`s allowed to sign
|
|
40
|
+
resolveUser: async (userId, ctx, { register }) => { // find-or-create the target identity
|
|
41
|
+
// wire to your identity store; return { userId, profileId?, entitySlug?, role?, scopes? }
|
|
42
|
+
},
|
|
43
|
+
allowRegistration: true, // default true
|
|
44
|
+
enabled: undefined, // default: development only (cfg.debug.all || cfg.debug.supervisor)
|
|
45
|
+
acceptInternalTokens: true, // default true — see below
|
|
46
|
+
})
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Options:
|
|
50
|
+
- `supervisors` — TRUSTED-record `name`s authorized to sign. Default `['master','superuser']`. The
|
|
51
|
+
matching **public** key must be in the project's TRUSTED config; the **private** key is what the
|
|
52
|
+
front-end signs with. Pick aliases whose private keys you actually have (e.g. in `.env.dev.secrets`).
|
|
53
|
+
- `resolveUser` — `(userId, context, { register }) => Promise<SupervisorUserResolution>`. Default:
|
|
54
|
+
trust the id as-is (`{ userId }`). Wire it to `@owlmeans/server-auth-identity`'s
|
|
55
|
+
`IdentityLinkingService` (`getLinkedProfile` / `linkProfile`) to find-or-create a real profile and
|
|
56
|
+
organization entity. `SupervisorUserResolution` is `{ userId }` plus optional `profileId`,
|
|
57
|
+
`entitySlug`, `role` and `scopes` — the organization value is a SLUG, the renameable public name
|
|
58
|
+
that a token carries, never the stable `entityId`. `profileId` defaults to `userId`, `scopes` to
|
|
59
|
+
the credential's own or `[ALL_SCOPES]`, and `role` to `AuthRole.User`.
|
|
60
|
+
- `enabled` — force on/off. Default is development only. **Never enable in real production.**
|
|
61
|
+
- `acceptInternalTokens` — when `true`, appends the internal `Ed25519BasicToken` guard
|
|
62
|
+
(`DEFAULT_GUARD`) as a coguard on every already-guarded backend entrypoint, so internal OwlMeans
|
|
63
|
+
tokens keep working where another guard (OIDC, say) is the primary one. The primary guard stays
|
|
64
|
+
first; the internal guard only matches an `Ed25519BasicToken` authorization header. Also exposed
|
|
65
|
+
standalone as `setupInternalTokenCoguard(entrypoints, guard?)`. Set `false` when the entrypoints
|
|
66
|
+
already use `DEFAULT_GUARD` as their primary guard.
|
|
67
|
+
- `guard` — which guard alias `acceptInternalTokens` appends. Default `DEFAULT_GUARD` (`'auth'`).
|
|
68
|
+
|
|
69
|
+
## Web: `appendSupervisorAuth` (from `@owlmeans/web-auth`)
|
|
70
|
+
|
|
71
|
+
Call once on the web client context. Registers the self-contained login form plugin; the form renders
|
|
72
|
+
at the standard typed route `SUPERVISOR_LOGIN_PATH` = `/authentication/login/pk-supervisor`.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { appendSupervisorAuth } from '@owlmeans/web-auth'
|
|
76
|
+
|
|
77
|
+
appendSupervisorAuth(context) // dev-only by default; or appendSupervisorAuth(context, { enabled })
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The form (`data-testid="supervisor-auth-form"`, inputs `supervisor-user-id`, `supervisor-pk`, button
|
|
81
|
+
`supervisor-submit`, error `supervisor-error`) fetches a challenge, signs it, exchanges it for a
|
|
82
|
+
bearer, stores it, and redirects HOME — mirroring the Google plugin. (Alternatively, the side-effect
|
|
83
|
+
import `@owlmeans/web-auth/auth/plugins` always-registers it.)
|
|
84
|
+
|
|
85
|
+
The web append reads `cfg.debug.supervisor` alone; the server append accepts either
|
|
86
|
+
`cfg.debug.all` or `cfg.debug.supervisor`. A deployment that wants the operator login therefore sets
|
|
87
|
+
`debug.supervisor` — it is the flag both halves honour, and the only one that does not arrive by
|
|
88
|
+
accident. The plugin is `restricted`, so `appendSupervisorAuth` also writes
|
|
89
|
+
`cfg.security.auth.login.overrides` to make it offerable; `{ offer: false }` registers it without
|
|
90
|
+
advertising it.
|
|
91
|
+
|
|
92
|
+
## Tests: `@owlmeans/test-ui` helpers
|
|
93
|
+
|
|
94
|
+
- `authenticateViaSupervisorApi({ apiBaseUrl, userId, pk })` — drives the live API
|
|
95
|
+
(`/authentication/init` → sign → `/authentication/authenticate` → `/authenticate`) and returns the
|
|
96
|
+
final bearer. **No browser**; registers the user on first use. The "set a token directly via API" path.
|
|
97
|
+
- `loginViaSupervisorForm(page, { baseUrl, userId, pk })` — Playwright: drives the real login form
|
|
98
|
+
end-to-end (faithful path that exercises the plugin + registration).
|
|
99
|
+
- `loginViaDispatcher(page, baseUrl, token)` — inject a pregenerated bearer via the standard
|
|
100
|
+
`/dispatcher?token=` route (apps that override DISPATCHER, e.g. for a forced IdP, can't use this —
|
|
101
|
+
use the form).
|
|
102
|
+
- `pregenerateAuthToken({ userId, pk, scopes?, role?, profileId?, source?, ... })` — offline mint via
|
|
103
|
+
`@owlmeans/test-auth`'s `makeBearer`, using the project's **own** trusted signing key (lowest-level
|
|
104
|
+
primitive). No plugin, no registration.
|
|
105
|
+
|
|
106
|
+
`loginViaSupervisorForm` answers a cookie-consent dialog by default (`consent: 'accept'`): an
|
|
107
|
+
OwlMeans app refuses to start an authentication flow until consent is answered, and the modal
|
|
108
|
+
intercepts every click at the form underneath. Both browser helpers navigate with
|
|
109
|
+
`waitUntil: 'domcontentloaded'` rather than Playwright's `load`, because `load` waits for every
|
|
110
|
+
subresource and a tag manager or analytics beacon that never settles holds it open until timeout.
|
|
111
|
+
|
|
112
|
+
## Security
|
|
113
|
+
|
|
114
|
+
- Development/stage only. Gate on `cfg.debug`; never ship enabled to real production.
|
|
115
|
+
- Anyone with a supervisor **private** key can impersonate/register any user — treat those keys as
|
|
116
|
+
highly sensitive.
|
|
117
|
+
|
|
118
|
+
## Depends On
|
|
119
|
+
- `@owlmeans/auth` (type + `buildSupervisorPayload` + `SupervisorCredentialPayload`),
|
|
120
|
+
`@owlmeans/basic-keys` (sign/verify), `@owlmeans/basic-ids` (the salt),
|
|
121
|
+
`@owlmeans/auth-common` (`DEFAULT_GUARD`, `TrustedRecord`), `@owlmeans/config` (`TRUSTED`).
|
|
122
|
+
- Tests: `@owlmeans/test-ui` (the helpers above) over `@owlmeans/test-auth` (`makeBearer`).
|
|
123
|
+
|
|
124
|
+
## Related
|
|
125
|
+
|
|
126
|
+
`server-auth` (the plugin registry and the manager) · `web-auth` (the form package) ·
|
|
127
|
+
`server-auth-identity` (what `resolveUser` should be wired to) · `login-methods` (why a
|
|
128
|
+
`restricted` method has to be named in the configuration)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAOnE,eAAO,MAAM,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAKlD,CAAA"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { elevate } from '@owlmeans/server-entrypoint';
|
|
2
|
-
import {
|
|
2
|
+
import { entrypoints as list } from '@owlmeans/auth-common';
|
|
3
3
|
import { DISPATCHER, DISPATCHER_AUTHEN } from '@owlmeans/auth';
|
|
4
4
|
import { authenticate } from './actions/service.js';
|
|
5
5
|
import { stab, elevate as celevate } from '@owlmeans/client-entrypoint';
|
|
6
6
|
elevate(list, DISPATCHER_AUTHEN, authenticate);
|
|
7
7
|
celevate(list, DISPATCHER, stab);
|
|
8
|
-
export const
|
|
9
|
-
...list.filter((module) => [DISPATCHER, DISPATCHER_AUTHEN].includes(module.
|
|
8
|
+
export const entrypoints = [
|
|
9
|
+
...list.filter((module) => [DISPATCHER, DISPATCHER_AUTHEN].includes(module.alias))
|
|
10
10
|
];
|
|
11
|
-
//# sourceMappingURL=
|
|
11
|
+
//# sourceMappingURL=entrypoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoints.js","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,WAAW,IAAI,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAE9D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,IAAI,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAEvE,OAAO,CAAC,IAAI,EAAE,iBAAiB,EAAE,YAAY,CAAC,CAAA;AAC9C,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,CAAA;AAEhC,MAAM,CAAC,MAAM,WAAW,GAAgC;IACtD,GAAG,IAAI,CAAC,MAAM,CACZ,CAAC,MAAM,EAAuC,EAAE,CAC9C,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CACzD;CACF,CAAA"}
|
package/build/index.d.ts
CHANGED
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,mBAAmB,YAAY,CAAA;AAC/B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,mBAAmB,YAAY,CAAA;AAC/B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,cAAc,CAAA"}
|
package/build/index.js
CHANGED
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,cAAc,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/manager/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AASvD,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,cAAa,OAAO,KAAW,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/manager/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AASvD,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,cAAa,OAAO,KAAW,CAoB9G,CAAA"}
|
package/build/manager/context.js
CHANGED
|
@@ -20,7 +20,6 @@ export const makeContext = (cfg, customize = false) => {
|
|
|
20
20
|
if (!customize && !context.hasResource(AUTH_CACHE)) {
|
|
21
21
|
appendStaticResource(context, AUTH_CACHE);
|
|
22
22
|
}
|
|
23
|
-
context.makeContext = (cfg => makeContext(cfg, customize));
|
|
24
23
|
return context;
|
|
25
24
|
};
|
|
26
25
|
//# sourceMappingURL=context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/manager/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAE5D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAEhE,MAAM,CAAC,MAAM,WAAW,GAAG,CAA+C,GAAM,EAAE,SAAS,GAAY,KAAK,EAAK,EAAE;IACjH,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAM,CAAA;IAE3C,eAAe,CAAO,OAAO,CAAC,CAAA;IAC9B,eAAe,CAAO,OAAO,CAAC,CAAA;IAC9B,mBAAmB,CAAO,OAAO,CAAC,CAAA;IAElC,OAAO,CAAC,kBAAkB,CAAC,sBAAsB,EAAE,CAAC,CAAA;IAEpD,4CAA4C;IAC5C,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACpD,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAA;IAC1D,CAAC;IAED,oBAAoB,CAAO,OAAO,CAAC,CAAA;IACnC,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QACnD,oBAAoB,CAAO,OAAO,EAAE,UAAU,CAAC,CAAA;IACjD,CAAC;IAED,OAAO,
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/manager/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAE5D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAEhE,MAAM,CAAC,MAAM,WAAW,GAAG,CAA+C,GAAM,EAAE,SAAS,GAAY,KAAK,EAAK,EAAE;IACjH,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAM,CAAA;IAE3C,eAAe,CAAO,OAAO,CAAC,CAAA;IAC9B,eAAe,CAAO,OAAO,CAAC,CAAA;IAC9B,mBAAmB,CAAO,OAAO,CAAC,CAAA;IAElC,OAAO,CAAC,kBAAkB,CAAC,sBAAsB,EAAE,CAAC,CAAA;IAEpD,4CAA4C;IAC5C,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACpD,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAA;IAC1D,CAAC;IAED,oBAAoB,CAAO,OAAO,CAAC,CAAA;IACnC,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QACnD,oBAAoB,CAAO,OAAO,EAAE,UAAU,CAAC,CAAA;IACjD,CAAC;IAED,OAAO,OAAY,CAAA;AACrB,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../../src/manager/entrypoints.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,WAAW,mDAAO,CAAA"}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { AUTHEN, AUTHEN_AUTHEN, AUTHEN_INIT, AUTHEN_RELY, MOD_RECAPTCHA } from '@owlmeans/auth';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { entrypoints as list } from '@owlmeans/auth-common';
|
|
3
|
+
import { entrypoints as apiConfig } from '@owlmeans/api-config-server';
|
|
4
4
|
import { elevate, guard } from '@owlmeans/server-entrypoint';
|
|
5
5
|
import * as actions from './actions/index.js';
|
|
6
6
|
import { entrypoint } from '@owlmeans/client-entrypoint';
|
|
7
7
|
import { backend, route, RouteMethod } from '@owlmeans/route';
|
|
8
8
|
import { handleIntermediate } from '@owlmeans/server-api';
|
|
9
9
|
import { DEFAULT_RELY } from './consts.js';
|
|
10
|
-
elevate(list, AUTHEN, handleIntermediate(async (_, context) =>
|
|
10
|
+
elevate(list, AUTHEN, handleIntermediate(async (_, context) => context), { intermediate: true });
|
|
11
11
|
elevate(list, AUTHEN_INIT, actions.authenticationInit);
|
|
12
12
|
elevate(list, AUTHEN_AUTHEN, actions.authenticate);
|
|
13
13
|
elevate(list, AUTHEN_RELY, actions.rely, guard(DEFAULT_RELY));
|
|
14
|
-
export const
|
|
14
|
+
export const entrypoints = list;
|
|
15
15
|
list.push(...apiConfig);
|
|
16
16
|
list.push(entrypoint(route(MOD_RECAPTCHA, '/api/siteverify', backend({
|
|
17
17
|
host: 'https://www.google.com',
|
|
18
18
|
base: 'recaptcha',
|
|
19
19
|
secure: true,
|
|
20
20
|
}, RouteMethod.POST))));
|
|
21
|
-
//# sourceMappingURL=
|
|
21
|
+
//# sourceMappingURL=entrypoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoints.js","sourceRoot":"","sources":["../../src/manager/entrypoints.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC/F,OAAO,EAAE,WAAW,IAAI,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAAE,WAAW,IAAI,SAAS,EAAE,MAAM,6BAA6B,CAAA;AACtE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,kBAAkB,CACtC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAC9B,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;AAC1B,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAA;AACtD,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;AAClD,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAA;AAE7D,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAA;AAC/B,IAAI,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAA;AACvB,IAAI,CAAC,IAAI,CACP,UAAU,CACR,KAAK,CAAC,aAAa,EAAE,iBAAiB,EAAE,OAAO,CAAC;IAC9C,IAAI,EAAE,wBAAwB;IAC9B,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,IAAI;CACb,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CACtB,CACF,CAAA"}
|
package/build/manager/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/manager/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,YAAY,CAAA;AAE/B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/manager/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,YAAY,CAAA;AAE/B,cAAc,kBAAkB,CAAA;AAChC,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA"}
|
package/build/manager/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/manager/index.ts"],"names":[],"mappings":"AAEA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/manager/index.ts"],"names":[],"mappings":"AAEA,cAAc,kBAAkB,CAAA;AAChC,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA"}
|
package/build/manager/main.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { entrypoints } from './entrypoints.js';
|
|
2
2
|
export const main = async (ctx) => {
|
|
3
|
-
ctx.registerEntrypoints(
|
|
3
|
+
ctx.registerEntrypoints(entrypoints);
|
|
4
4
|
await ctx.configure().init();
|
|
5
5
|
await ctx.getApiServer().listen();
|
|
6
6
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/manager/main.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/manager/main.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAG9C,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,EAAgD,GAAM,EAAE,EAAE;IACjF,GAAG,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAA;IACpC,MAAM,GAAG,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAA;IAC5B,MAAM,GAAG,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,CAAA;AACnC,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/manager/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/manager/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAkBlE,eAAO,MAAM,aAAa,YAAa,UAAU,CAAC,SAAS,CAAC,KAAG,SAyF9D,CAAA"}
|
package/build/manager/model.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AuthenFailed, AuthenPayloadError } from '@owlmeans/auth';
|
|
1
|
+
import { AuthenFailed, AuthenPayloadError, entitySlugOf } from '@owlmeans/auth';
|
|
2
|
+
import { ENTITY_RESOLVER } from '@owlmeans/auth-common';
|
|
2
3
|
import { getPlugin } from './plugins/utils.js';
|
|
3
4
|
import { AUTH_CACHE, AUTHEN_TIMEFRAME } from '../consts.js';
|
|
4
5
|
import { EnvelopeKind, makeEnvelopeModel } from '@owlmeans/basic-envelope';
|
|
@@ -52,6 +53,18 @@ export const makeAuthModel = (context) => {
|
|
|
52
53
|
const challenge = credential.challenge;
|
|
53
54
|
const { token } = await plugin.authenticate(Object.assign(credential, { challenge: msg }));
|
|
54
55
|
credential.challenge = token === '' ? challenge : token;
|
|
56
|
+
// Plugins accept whatever the caller typed — a current slug, a slug the organization has
|
|
57
|
+
// since retired, or (for a token minted before slugs existed) its stable key. The token is
|
|
58
|
+
// signed once and read for as long as it lives, so the value is canonicalized here rather
|
|
59
|
+
// than at every place that later reads it back.
|
|
60
|
+
const entitySlug = entitySlugOf(credential);
|
|
61
|
+
if (entitySlug != null && context.hasService(ENTITY_RESOLVER)) {
|
|
62
|
+
const entity = await context.service(ENTITY_RESOLVER).resolve(entitySlug);
|
|
63
|
+
if (entity == null) {
|
|
64
|
+
throw new AuthenFailed('entity');
|
|
65
|
+
}
|
|
66
|
+
credential.entitySlug = entity.slug;
|
|
67
|
+
}
|
|
55
68
|
credential.credential = trustedUser.id;
|
|
56
69
|
return {
|
|
57
70
|
token: await makeEnvelopeModel(credential.type)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/manager/model.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/manager/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"basic-ed25519.js","sourceRoot":"","sources":["../../../src/manager/plugins/basic-ed25519.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEvF,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEjD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAG1C,MAAM,CAAC,MAAM,YAAY,GAAG,CAA+C,OAAU,EAAc,EAAE;IACnG,MAAM,MAAM,GAAe;QACzB,IAAI,EAAE,kBAAkB,CAAC,YAAY;QACrC,IAAI,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE;YACpB,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YAEhC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAA;YAEhD,OAAO,EAAE,SAAS,EAAE,CAAA;QACtB,CAAC;QAED,YAAY,EAAE,KAAK,EAAC,UAAU,EAAC,EAAE;YAC/B;;eAEG;YACH,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"basic-ed25519.js","sourceRoot":"","sources":["../../../src/manager/plugins/basic-ed25519.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEvF,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEjD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAG1C,MAAM,CAAC,MAAM,YAAY,GAAG,CAA+C,OAAU,EAAc,EAAE;IACnG,MAAM,MAAM,GAAe;QACzB,IAAI,EAAE,kBAAkB,CAAC,YAAY;QACrC,IAAI,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE;YACpB,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YAEhC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAA;YAEhD,OAAO,EAAE,SAAS,EAAE,CAAA;QACtB,CAAC;QAED,YAAY,EAAE,KAAK,EAAC,UAAU,EAAC,EAAE;YAC/B;;eAEG;YACH,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,iBAAiB,CAAgB,OAAO,CAAC;iBACvE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;YAE1B,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,IAAI,YAAY,EAAE,CAAA;YAC1B,CAAC;YAED,IAAI,UAAU,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;gBAClC,MAAM,IAAI,WAAW,CAAC,4BAA4B,CAAC,CAAA;YACrD,CAAC;YAED,MAAM,GAAG,GAAG,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,CAAA;YAE7C,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnE,MAAM,IAAI,YAAY,CAAC,aAAa,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;YACpD,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAA;YAE5C,8DAA8D;YAC9D,UAAU,CAAC,MAAM,GAAG,CAAC,UAAU,CAAC,CAAA;YAChC,UAAU,CAAC,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAA;YACpC,UAAU,CAAC,SAAS,GAAG,KAAK,CAAA;YAC5B,UAAU,CAAC,IAAI,GAAG,kBAAkB,CAAC,YAAY,CAAA;YAEjD,OAAO,EAAE,KAAK,EAAE,CAAA;QAClB,CAAC;KACF,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"basic-rely.d.ts","sourceRoot":"","sources":["../../../src/manager/plugins/basic-rely.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,aAAa,CAAA;AAChF,OAAO,KAAK,EAAE,UAAU,EAAiC,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"basic-rely.d.ts","sourceRoot":"","sources":["../../../src/manager/plugins/basic-rely.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,aAAa,CAAA;AAChF,OAAO,KAAK,EAAE,UAAU,EAAiC,MAAM,YAAY,CAAA;AAU3E,eAAO,MAAM,SAAS,YAAa,UAAU,SAAS,MAAM,KAAG,UA0J9D,CAAA"}
|
|
@@ -11,8 +11,8 @@ export const basicRely = (context, type) => {
|
|
|
11
11
|
type: type ?? AuthenticationType.RelyHandshake,
|
|
12
12
|
// This method is used by consumer and by provider (wallet)
|
|
13
13
|
// to initialize shared authentication process.
|
|
14
|
-
// The idea is that both
|
|
15
|
-
//
|
|
14
|
+
// The idea is that both watch the record holding their own pin/token and wake
|
|
15
|
+
// up when the peer writes its handshake value into it.
|
|
16
16
|
init: async (request) => {
|
|
17
17
|
const [, keyPair] = await trusted(context);
|
|
18
18
|
const tunnel = context.resource(AUTH_CACHE);
|
|
@@ -32,8 +32,8 @@ export const basicRely = (context, type) => {
|
|
|
32
32
|
}
|
|
33
33
|
if (request.provideRely != null) {
|
|
34
34
|
await Promise.all([pin, token].filter(key => key != null).map(async (key) => {
|
|
35
|
-
_subscriptions[key] = await tunnel.
|
|
36
|
-
if (value
|
|
35
|
+
_subscriptions[key] = await tunnel.watch(key, async (value) => {
|
|
36
|
+
if (value?.challenge != null) {
|
|
37
37
|
const rely = makeEnvelopeModel(value.challenge, EnvelopeKind.Wrap);
|
|
38
38
|
if (await rely.verify(keyPair)) {
|
|
39
39
|
[pin, token].filter(key => key != null).forEach(key => {
|
|
@@ -45,7 +45,7 @@ export const basicRely = (context, type) => {
|
|
|
45
45
|
await request.provideRely?.(rely.message(), relyMsg, true);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
}, {
|
|
48
|
+
}, { once: true });
|
|
49
49
|
// @TODO they need to be killed on close - but actually live a little bit longer
|
|
50
50
|
// then timeout for them is ok
|
|
51
51
|
setTimeout(() => {
|