@jskit-ai/agent-docs 0.1.251 → 0.1.252
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/guide/agent/app-extras/realtime.md +11 -3
- package/guide/agent/app-setup/authentication.md +58 -0
- package/package.json +1 -1
- package/patterns/minimal-foundation/example/package.json +1 -1
- package/patterns/shell-foundation/example/package.json +1 -1
- package/reference/autogen/PATTERN_INDEX.md +16 -16
- package/reference/autogen/packages/auth-provider-local-core.md +30 -1
- package/reference/autogen/packages/auth-provider-local-db-core.md +6 -0
- package/reference/autogen/packages/realtime.md +4 -2
- package/reference/autogen/packages/users-web.md +4 -0
- package/skills/jskit/references/pattern-index.md +16 -16
- package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +1 -1
- package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +1 -1
- package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +1 -1
- package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +1 -1
- package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +1 -1
- package/skills/jskit/references/patterns/users/account-settings/PATTERN.md +12 -3
- package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsSignInMethodsSection.vue +67 -0
- package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +1 -1
|
@@ -46,9 +46,17 @@ rejects unauthenticated handshakes before a socket joins any broadcast room.
|
|
|
46
46
|
Clients must disconnect and reconnect after their login identity changes so a
|
|
47
47
|
new handshake establishes the current actor.
|
|
48
48
|
|
|
49
|
-
When `auth.service.authenticateRequest()` is present,
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
When `auth.service.authenticateRequest()` is present, each publish reauthenticates
|
|
50
|
+
every socket that could receive it before sending, and every socket is rechecked
|
|
51
|
+
every 30 seconds. A socket could receive a publish when the audience is
|
|
52
|
+
`all_clients` or `broadcast`, when it is already in a target room, or, when an
|
|
53
|
+
audience contributor is registered, when a target room is a user or workspace
|
|
54
|
+
room it could join on revalidation. Other sockets are not checked for that
|
|
55
|
+
publish. Sockets whose authentication requests are identical, such as tabs of
|
|
56
|
+
one browser, share one `authenticateRequest()` call within a publish or a
|
|
57
|
+
30-second pass; nothing is reused from one publish or pass to the next. Revoked,
|
|
58
|
+
expired, or changed actors are disconnected by the first publish that could
|
|
59
|
+
reach them or the next 30-second check. Authentication lookup errors fail
|
|
52
60
|
closed.
|
|
53
61
|
|
|
54
62
|
Packages that know which scopes an actor belongs to contribute them through
|
|
@@ -131,6 +131,64 @@ or compatibility adapter.
|
|
|
131
131
|
the completed password-reset flow before releasing the updated application.
|
|
132
132
|
This change does not alter identity, session or recovery-token storage.
|
|
133
133
|
|
|
134
|
+
## Google, Microsoft and GitHub sign-in with local auth
|
|
135
|
+
|
|
136
|
+
Local auth signs people in through Google, Microsoft and GitHub when the
|
|
137
|
+
application sets each provider's client id and secret in private Env:
|
|
138
|
+
|
|
139
|
+
| Provider | Env pair | Protocol and scopes |
|
|
140
|
+
| --- | --- | --- |
|
|
141
|
+
| Google | `AUTH_GOOGLE_CLIENT_ID`, `AUTH_GOOGLE_CLIENT_SECRET` | OpenID Connect discovery, `openid email profile` |
|
|
142
|
+
| Microsoft | `AUTH_MICROSOFT_CLIENT_ID`, `AUTH_MICROSOFT_CLIENT_SECRET` | OpenID Connect discovery through the `common` endpoint, `openid email profile` |
|
|
143
|
+
| GitHub | `AUTH_GITHUB_CLIENT_ID`, `AUTH_GITHUB_CLIENT_SECRET` | OAuth 2.0, `read:user user:email`, email from `GET /user/emails` |
|
|
144
|
+
|
|
145
|
+
A provider appears in `oauthLogin.providers` only when both values of its pair
|
|
146
|
+
are set; setting one without the other stops startup. `APP_PUBLIC_URL` is then
|
|
147
|
+
required, and every provider's app registration must allow exactly
|
|
148
|
+
`${APP_PUBLIC_URL}/auth/login` as its redirect address. The login page posts the
|
|
149
|
+
callback to `/api/oauth/complete`, which completes the provider the attempt
|
|
150
|
+
started with.
|
|
151
|
+
|
|
152
|
+
Register the Microsoft app for accounts in any organizational directory and
|
|
153
|
+
personal Microsoft accounts, and add the optional ID token claim `xms_edov`.
|
|
154
|
+
|
|
155
|
+
Security behavior:
|
|
156
|
+
|
|
157
|
+
- The authorization-code flow uses PKCE (`S256`) and `state`, plus `nonce` for
|
|
158
|
+
OpenID Connect. The attempt is stored server-side, in the file store or the
|
|
159
|
+
`auth_local_oauth_attempts` table, under the hash of a random httpOnly
|
|
160
|
+
`jskit_local_oauth_attempt` cookie (`__Host-` in production), so it completes
|
|
161
|
+
only in the starting browser and works across several servers. It is deleted
|
|
162
|
+
when used and expires after ten minutes.
|
|
163
|
+
- ID tokens are verified against the provider's JWKS: signature, issuer,
|
|
164
|
+
audience, expiry and nonce.
|
|
165
|
+
- Only a verified email signs in: Google's `email_verified`, GitHub's primary
|
|
166
|
+
verified address, and for Microsoft a personal account or a work or school
|
|
167
|
+
account whose token carries `xms_edov: true`. A Microsoft token without an
|
|
168
|
+
email claim is refused.
|
|
169
|
+
- `returnTo` must be on the application's own origin; anything else returns to
|
|
170
|
+
`/`.
|
|
171
|
+
|
|
172
|
+
A sign-in matches the provider subject first. Otherwise a verified email that
|
|
173
|
+
matches an existing user signs that user in and links the provider identity,
|
|
174
|
+
and a new email creates the user the way `register` does: the
|
|
175
|
+
`auth.local.user.registered` hook runs and profile synchronization provisions
|
|
176
|
+
the personal workspace. An account created this way has no password until
|
|
177
|
+
password recovery sets one. Sessions are ordinary local sessions; provider
|
|
178
|
+
tokens are discarded after sign-in.
|
|
179
|
+
|
|
180
|
+
With providers configured, the `providerLinking` capability is on. The security
|
|
181
|
+
status lists each provider as an `oauth:<provider>` method, where `canEnable`
|
|
182
|
+
means it can be linked and `canDisable` that it can be unlinked.
|
|
183
|
+
`GET /api/settings/security/oauth/:provider/start` links a provider to the
|
|
184
|
+
signed-in account and `DELETE /api/settings/security/oauth/:provider` unlinks
|
|
185
|
+
it. Unlinking the last sign-in method is refused, and so is linking an identity
|
|
186
|
+
that already belongs to another account. The `users/account-settings` pattern's
|
|
187
|
+
sign-in methods section offers both.
|
|
188
|
+
|
|
189
|
+
With `@jskit-ai/auth-provider-local-db-core`, run `npm run db:migrate` to create
|
|
190
|
+
the `auth_local_identities` and `auth_local_oauth_attempts` tables.
|
|
191
|
+
|
|
134
192
|
## Browser boundary
|
|
135
193
|
|
|
136
194
|
`@jskit-ai/auth-web` owns the normal auth views, guard runtime, sign-out flow,
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@ A concrete Fastify, Vue, and JSKIT application foundation for products that do n
|
|
|
15
15
|
|
|
16
16
|
- Id: `app/minimal-foundation`
|
|
17
17
|
- Keywords: `app`, `fastify`, `foundation`, `minimal`, `server`, `vite`, `vue`
|
|
18
|
-
- Owner: `@jskit-ai/agent-docs@0.1.
|
|
18
|
+
- Owner: `@jskit-ai/agent-docs@0.1.252`
|
|
19
19
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/app/minimal-foundation/PATTERN.md)
|
|
20
20
|
- Examples: [example/](../../skills/jskit/references/patterns/app/minimal-foundation/example/)
|
|
21
21
|
- Requires: `@jskit-ai/http-runtime`, `@jskit-ai/kernel`
|
|
@@ -26,7 +26,7 @@ A concrete JSKIT web application foundation with responsive shell navigation, se
|
|
|
26
26
|
|
|
27
27
|
- Id: `app/shell-foundation`
|
|
28
28
|
- Keywords: `app`, `foundation`, `material`, `navigation`, `placements`, `shell`, `vite`, `vue`
|
|
29
|
-
- Owner: `@jskit-ai/agent-docs@0.1.
|
|
29
|
+
- Owner: `@jskit-ai/agent-docs@0.1.252`
|
|
30
30
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/app/shell-foundation/PATTERN.md)
|
|
31
31
|
- Examples: [example/](../../skills/jskit/references/patterns/app/shell-foundation/example/)
|
|
32
32
|
- Requires: `@jskit-ai/http-runtime`, `@jskit-ai/kernel`, `@jskit-ai/shell-web`
|
|
@@ -37,7 +37,7 @@ Configure an assistant runtime for one application surface and expose its chat a
|
|
|
37
37
|
|
|
38
38
|
- Id: `assistant/assistant-surface`
|
|
39
39
|
- Keywords: `ai`, `assistant`, `chat`, `config`, `environment`, `page`, `placement`, `settings`, `surface`
|
|
40
|
-
- Owner: `@jskit-ai/assistant-runtime@0.2.
|
|
40
|
+
- Owner: `@jskit-ai/assistant-runtime@0.2.4`
|
|
41
41
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/assistant/assistant-surface/PATTERN.md)
|
|
42
42
|
- Examples: [example/](../../skills/jskit/references/patterns/assistant/assistant-surface/example/)
|
|
43
43
|
- Requires: `@jskit-ai/assistant-runtime`, `@jskit-ai/connectors-catalog`, `@jskit-ai/connectors-core`, `@jskit-ai/shell-web`
|
|
@@ -48,7 +48,7 @@ Run one OpenID Connect sign-in for all of an owner's apps as its own JSKIT proje
|
|
|
48
48
|
|
|
49
49
|
- Id: `auth/accounts-hub`
|
|
50
50
|
- Keywords: `accounts hub`, `auth`, `authentication`, `issuer`, `master login`, `oidc`, `openid connect`, `single sign-on`, `sso`
|
|
51
|
-
- Owner: `@jskit-ai/oidc-issuer-core@0.1.
|
|
51
|
+
- Owner: `@jskit-ai/oidc-issuer-core@0.1.7`
|
|
52
52
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/auth/accounts-hub/PATTERN.md)
|
|
53
53
|
- Examples: [example/](../../skills/jskit/references/patterns/auth/accounts-hub/example/)
|
|
54
54
|
- Requires: `@jskit-ai/oidc-issuer-core`
|
|
@@ -70,7 +70,7 @@ Let people sign in with the accounts they already have in an accounts hub or ano
|
|
|
70
70
|
|
|
71
71
|
- Id: `auth/oidc-sign-in`
|
|
72
72
|
- Keywords: `accounts hub`, `auth`, `authentication`, `back-channel logout`, `dynamic client registration`, `issuer`, `master login`, `oidc`, `openid connect`, `single sign-on`, `sso`
|
|
73
|
-
- Owner: `@jskit-ai/auth-provider-oidc-core@0.2.
|
|
73
|
+
- Owner: `@jskit-ai/auth-provider-oidc-core@0.2.2`
|
|
74
74
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/auth/oidc-sign-in/PATTERN.md)
|
|
75
75
|
- Examples: [example/](../../skills/jskit/references/patterns/auth/oidc-sign-in/example/)
|
|
76
76
|
- Requires: `@jskit-ai/auth-provider-oidc-core`, `@jskit-ai/auth-web`
|
|
@@ -246,7 +246,7 @@ Add a protected administration surface, settings shell, and semantic navigation
|
|
|
246
246
|
|
|
247
247
|
- Id: `console/console-surface`
|
|
248
248
|
- Keywords: `admin`, `console`, `navigation`, `owner`, `placement`, `settings`, `surface`
|
|
249
|
-
- Owner: `@jskit-ai/console-web@0.1.
|
|
249
|
+
- Owner: `@jskit-ai/console-web@0.1.222`
|
|
250
250
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/console/console-surface/PATTERN.md)
|
|
251
251
|
- Examples: [example/](../../skills/jskit/references/patterns/console/console-surface/example/)
|
|
252
252
|
- Requires: `@jskit-ai/console-core`, `@jskit-ai/console-web`, `@jskit-ai/shell-web`
|
|
@@ -257,7 +257,7 @@ Build a routed CRUD user interface as thin application pages over JSKIT's shared
|
|
|
257
257
|
|
|
258
258
|
- Id: `crud/crud-screen-set`
|
|
259
259
|
- Keywords: `actions`, `add`, `crud`, `delete`, `edit`, `filters`, `list`, `material`, `routes`, `view`, `vue`
|
|
260
|
-
- Owner: `@jskit-ai/http-web@0.2.
|
|
260
|
+
- Owner: `@jskit-ai/http-web@0.2.3`
|
|
261
261
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/crud/crud-screen-set/PATTERN.md)
|
|
262
262
|
- Examples: [example/](../../skills/jskit/references/patterns/crud/crud-screen-set/example/)
|
|
263
263
|
- Requires: `@jskit-ai/http-web`, `@jskit-ai/resource-crud-core`
|
|
@@ -323,7 +323,7 @@ Add JSKIT realtime events with an optional Redis backplane and an explicit shell
|
|
|
323
323
|
|
|
324
324
|
- Id: `realtime/realtime-application`
|
|
325
325
|
- Keywords: `realtime`, `redis`, `socket.io`, `sockets`, `status`, `websocket`
|
|
326
|
-
- Owner: `@jskit-ai/realtime@0.2.
|
|
326
|
+
- Owner: `@jskit-ai/realtime@0.2.2`
|
|
327
327
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/realtime/realtime-application/PATTERN.md)
|
|
328
328
|
- Examples: [example/](../../skills/jskit/references/patterns/realtime/realtime-application/example/)
|
|
329
329
|
- Requires: `@jskit-ai/realtime`, `@jskit-ai/shell-web`
|
|
@@ -334,7 +334,7 @@ Compose application-owned Google Publisher Tag delivery with the generic rewarde
|
|
|
334
334
|
|
|
335
335
|
- Id: `rewards/google-rewarded`
|
|
336
336
|
- Keywords: `ads`, `google`, `publisher tag`, `rewarded`, `unlock`
|
|
337
|
-
- Owner: `@jskit-ai/rewarded-web@0.2.
|
|
337
|
+
- Owner: `@jskit-ai/rewarded-web@0.2.2`
|
|
338
338
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/rewards/google-rewarded/PATTERN.md)
|
|
339
339
|
- Examples: [example/](../../skills/jskit/references/patterns/rewards/google-rewarded/example/)
|
|
340
340
|
- Requires: `@jskit-ai/rewarded-web`
|
|
@@ -345,7 +345,7 @@ Define a server feature through explicit capabilities and first-class actions, a
|
|
|
345
345
|
|
|
346
346
|
- Id: `server/feature-package`
|
|
347
347
|
- Keywords: `actions`, `feature`, `json-rest`, `knex`, `orchestration`, `package`, `provider`, `repository`, `routes`, `server`
|
|
348
|
-
- Owner: `@jskit-ai/agent-docs@0.1.
|
|
348
|
+
- Owner: `@jskit-ai/agent-docs@0.1.252`
|
|
349
349
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/server/feature-package/PATTERN.md)
|
|
350
350
|
- Examples: [example/](../../skills/jskit/references/patterns/server/feature-package/example/)
|
|
351
351
|
- Requires: `@jskit-ai/kernel`
|
|
@@ -374,11 +374,11 @@ Add product routes and shell extensions through file routing, semantic placement
|
|
|
374
374
|
|
|
375
375
|
## Account settings surface
|
|
376
376
|
|
|
377
|
-
Compose an account settings route and profile, preference, and
|
|
377
|
+
Compose an account settings route and profile, preference, notification, and sign-in method sections from JSKIT user web components.
|
|
378
378
|
|
|
379
379
|
- Id: `users/account-settings`
|
|
380
|
-
- Keywords: `account`, `notifications`, `preferences`, `profile`, `settings`, `user`, `vue`
|
|
381
|
-
- Owner: `@jskit-ai/users-web@0.2.
|
|
380
|
+
- Keywords: `account`, `link provider`, `notifications`, `oauth`, `preferences`, `profile`, `settings`, `sign-in methods`, `user`, `vue`
|
|
381
|
+
- Owner: `@jskit-ai/users-web@0.2.3`
|
|
382
382
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/users/account-settings/PATTERN.md)
|
|
383
383
|
- Examples: [example/](../../skills/jskit/references/patterns/users/account-settings/example/)
|
|
384
384
|
- Requires: `@jskit-ai/shell-web`, `@jskit-ai/users-core`, `@jskit-ai/users-web`
|
|
@@ -389,7 +389,7 @@ Expose user administration and workspace-scoped member operations through app-ow
|
|
|
389
389
|
|
|
390
390
|
- Id: `users/user-administration-server`
|
|
391
391
|
- Keywords: `account`, `admin`, `member`, `repository`, `resource`, `routes`, `service`, `user`, `workspace`
|
|
392
|
-
- Owner: `@jskit-ai/users-core@0.2.
|
|
392
|
+
- Owner: `@jskit-ai/users-core@0.2.2`
|
|
393
393
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/users/user-administration-server/PATTERN.md)
|
|
394
394
|
- Examples: [example/](../../skills/jskit/references/patterns/users/user-administration-server/example/)
|
|
395
395
|
- Requires: `@jskit-ai/crud-core`, `@jskit-ai/users-core`
|
|
@@ -400,7 +400,7 @@ Configure roles, workspace access policy, invitations, and app-owned invitation
|
|
|
400
400
|
|
|
401
401
|
- Id: `workspaces/workspace-server`
|
|
402
402
|
- Keywords: `access`, `invite`, `membership`, `multitenancy`, `policy`, `role`, `tenancy`, `workspace`
|
|
403
|
-
- Owner: `@jskit-ai/workspaces-core@0.2.
|
|
403
|
+
- Owner: `@jskit-ai/workspaces-core@0.2.2`
|
|
404
404
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/workspaces/workspace-server/PATTERN.md)
|
|
405
405
|
- Examples: [example/](../../skills/jskit/references/patterns/workspaces/workspace-server/example/)
|
|
406
406
|
- Requires: `@jskit-ai/users-core`, `@jskit-ai/workspaces-core`
|
|
@@ -411,7 +411,7 @@ Compose workspace selection, invitation, member administration, settings, and re
|
|
|
411
411
|
|
|
412
412
|
- Id: `workspaces/workspace-surfaces`
|
|
413
413
|
- Keywords: `admin`, `invite`, `member`, `navigation`, `settings`, `surface`, `switcher`, `workspace`
|
|
414
|
-
- Owner: `@jskit-ai/workspaces-web@0.2.
|
|
414
|
+
- Owner: `@jskit-ai/workspaces-web@0.2.3`
|
|
415
415
|
- Read: [PATTERN.md](../../skills/jskit/references/patterns/workspaces/workspace-surfaces/PATTERN.md)
|
|
416
416
|
- Examples: [example/](../../skills/jskit/references/patterns/workspaces/workspace-surfaces/example/)
|
|
417
417
|
- Requires: `@jskit-ai/shell-web`, `@jskit-ai/workspaces-core`, `@jskit-ai/workspaces-web`
|
|
@@ -28,6 +28,10 @@ Local functions
|
|
|
28
28
|
- `serializeSessions(sessions)`
|
|
29
29
|
- `parseRecovery(content)`
|
|
30
30
|
- `serializeRecovery(records)`
|
|
31
|
+
- `parseIdentities(content)`
|
|
32
|
+
- `serializeIdentities(identities)`
|
|
33
|
+
- `parseOAuthAttempts(content)`
|
|
34
|
+
- `serializeOAuthAttempts(attempts)`
|
|
31
35
|
- `readText(filePath)`
|
|
32
36
|
- `writeAtomic(filePath, content)`
|
|
33
37
|
- `encodeJournalContent(content)`
|
|
@@ -53,6 +57,15 @@ Exports
|
|
|
53
57
|
- `normalizePasswordStrategy`
|
|
54
58
|
- `verifyPassword`
|
|
55
59
|
|
|
60
|
+
### `src/server/lib/oauth.js`
|
|
61
|
+
Exports
|
|
62
|
+
- `createOAuthClients({ logger = null } = {})`
|
|
63
|
+
- `resolveOAuthProviders(env = {})`
|
|
64
|
+
Local functions
|
|
65
|
+
- `signInError(statusCode, message, { code, provider = null })`
|
|
66
|
+
- `unverifiedSignIn()`
|
|
67
|
+
- `displayNameFrom(source = {})`
|
|
68
|
+
|
|
56
69
|
### `src/server/lib/passwords.js`
|
|
57
70
|
Exports
|
|
58
71
|
- `hashPassword(password)`
|
|
@@ -83,6 +96,7 @@ Local functions
|
|
|
83
96
|
- `isDevAuthSession(session)`
|
|
84
97
|
- `isAuthenticatingSession(session)`
|
|
85
98
|
- `normalizeDisplayName(value, email)`
|
|
99
|
+
- `hasPassword(user)`
|
|
86
100
|
- `createId(prefix)`
|
|
87
101
|
- `safeRequestCookies(request)`
|
|
88
102
|
- `unauthenticatedAuthResult(clearSession = false)`
|
|
@@ -120,4 +134,19 @@ Exports
|
|
|
120
134
|
Local functions
|
|
121
135
|
- `resolveStoreDir(env, appRoot)`
|
|
122
136
|
- `resolveSessionSecret(env, { storeDir, isProduction })`
|
|
123
|
-
- `resolveAppPublicUrl(env, { recoverySender })`
|
|
137
|
+
- `resolveAppPublicUrl(env, { recoverySender, oauthProviders })`
|
|
138
|
+
|
|
139
|
+
### test-support
|
|
140
|
+
|
|
141
|
+
### `test-support/oauthHarness.js`
|
|
142
|
+
Exports
|
|
143
|
+
- `APP_URL`
|
|
144
|
+
- `ATTEMPT_COOKIE`
|
|
145
|
+
- `approveAtProvider(service, { provider = "google", returnTo = "/home", cookies = {}, link = false } = {})`
|
|
146
|
+
- `createService({ backend, oauthProviders, profileProjector = null })`
|
|
147
|
+
- `oidcProviderEntry(issuer, { id = "google", label = "Google" } = {})`
|
|
148
|
+
- `sessionCookies(session)`
|
|
149
|
+
- `startFakeGitHub({ user = { id: 4242, login: "ada", name: "Ada Lovelace" }, emails } = {})`
|
|
150
|
+
- `startOidcProvider({ account } = {})`
|
|
151
|
+
Local functions
|
|
152
|
+
- `readBody(req)`
|
|
@@ -29,6 +29,8 @@ Local functions
|
|
|
29
29
|
- `mapUser(row)`
|
|
30
30
|
- `mapSession(row)`
|
|
31
31
|
- `mapRecovery(row)`
|
|
32
|
+
- `mapIdentity(row)`
|
|
33
|
+
- `mapOAuthAttempt(row)`
|
|
32
34
|
- `userInsert(input = {})`
|
|
33
35
|
- `sessionInsert(input = {})`
|
|
34
36
|
- `recoveryInsert(input = {})`
|
|
@@ -48,3 +50,7 @@ Exports
|
|
|
48
50
|
### `migrations/auth_local_db_initial.cjs`
|
|
49
51
|
Exports
|
|
50
52
|
- None
|
|
53
|
+
|
|
54
|
+
### `migrations/auth_local_db_oauth.cjs`
|
|
55
|
+
Exports
|
|
56
|
+
- None
|
|
@@ -57,7 +57,7 @@ Exports
|
|
|
57
57
|
- `createAudienceContributors()`
|
|
58
58
|
- `createSocketRequest(socket)`
|
|
59
59
|
- `realtimeAuthenticationRequired(authService = null)`
|
|
60
|
-
- `revalidateSocket({ socket, authService, audiences = null, request })`
|
|
60
|
+
- `revalidateSocket({ socket, authService, audiences = null, request, authenticateRequest })`
|
|
61
61
|
- `registerSocketAudienceBootstrap({ io, logger, authService = null, audiences = null })`
|
|
62
62
|
- `resolveAudienceTargets(audience, event, { database = null, logger })`
|
|
63
63
|
Local functions
|
|
@@ -68,11 +68,12 @@ Local functions
|
|
|
68
68
|
- `resolveScopeWorkspaceId(scope = {})`
|
|
69
69
|
- `resolveScopeUserId(scope = {})`
|
|
70
70
|
- `roomForScope(scope = {})`
|
|
71
|
+
- `isScopeRoom(room)`
|
|
71
72
|
- `applyAudiencePreset(preset, { event, rooms, flags, logger })`
|
|
72
73
|
- `addAudienceRooms(selection, state)`
|
|
73
74
|
- `collectUserIds(rows)`
|
|
74
75
|
- `parseCookieHeader(value = "")`
|
|
75
|
-
- `resolveSocketActor(authService, socket, request = createSocketRequest(socket))`
|
|
76
|
+
- `resolveSocketActor(authService, socket, request = createSocketRequest(socket), authenticateRequest = (value) => authService.authenticateRequest(value))`
|
|
76
77
|
- `authenticationRequiredError()`
|
|
77
78
|
- `rememberSocketActorId(socket, actorId)`
|
|
78
79
|
- `registerRequiredSocketAuthentication({ io, logger, authService })`
|
|
@@ -83,6 +84,7 @@ Exports
|
|
|
83
84
|
- `createRealtimeDelivery({ io, database = null, logger, authService = null, audiences = null })`
|
|
84
85
|
Local functions
|
|
85
86
|
- `publicRealtimePayload(event)`
|
|
87
|
+
- `createSharedAuthentication(authService)`
|
|
86
88
|
|
|
87
89
|
### `src/server/RealtimeProvider.js`
|
|
88
90
|
Exports
|
|
@@ -143,6 +143,10 @@ Exports
|
|
|
143
143
|
Exports
|
|
144
144
|
- None
|
|
145
145
|
|
|
146
|
+
### `patterns/account-settings/example/src/components/account/settings/AccountSettingsSignInMethodsSection.vue`
|
|
147
|
+
Exports
|
|
148
|
+
- None
|
|
149
|
+
|
|
146
150
|
### `patterns/account-settings/example/src/pages/account/index.vue`
|
|
147
151
|
Exports
|
|
148
152
|
- None
|
|
@@ -15,7 +15,7 @@ A concrete Fastify, Vue, and JSKIT application foundation for products that do n
|
|
|
15
15
|
|
|
16
16
|
- Id: `app/minimal-foundation`
|
|
17
17
|
- Keywords: `app`, `fastify`, `foundation`, `minimal`, `server`, `vite`, `vue`
|
|
18
|
-
- Owner: `@jskit-ai/agent-docs@0.1.
|
|
18
|
+
- Owner: `@jskit-ai/agent-docs@0.1.252`
|
|
19
19
|
- Read: [PATTERN.md](patterns/app/minimal-foundation/PATTERN.md)
|
|
20
20
|
- Examples: [example/](patterns/app/minimal-foundation/example/)
|
|
21
21
|
- Requires: `@jskit-ai/http-runtime`, `@jskit-ai/kernel`
|
|
@@ -26,7 +26,7 @@ A concrete JSKIT web application foundation with responsive shell navigation, se
|
|
|
26
26
|
|
|
27
27
|
- Id: `app/shell-foundation`
|
|
28
28
|
- Keywords: `app`, `foundation`, `material`, `navigation`, `placements`, `shell`, `vite`, `vue`
|
|
29
|
-
- Owner: `@jskit-ai/agent-docs@0.1.
|
|
29
|
+
- Owner: `@jskit-ai/agent-docs@0.1.252`
|
|
30
30
|
- Read: [PATTERN.md](patterns/app/shell-foundation/PATTERN.md)
|
|
31
31
|
- Examples: [example/](patterns/app/shell-foundation/example/)
|
|
32
32
|
- Requires: `@jskit-ai/http-runtime`, `@jskit-ai/kernel`, `@jskit-ai/shell-web`
|
|
@@ -37,7 +37,7 @@ Configure an assistant runtime for one application surface and expose its chat a
|
|
|
37
37
|
|
|
38
38
|
- Id: `assistant/assistant-surface`
|
|
39
39
|
- Keywords: `ai`, `assistant`, `chat`, `config`, `environment`, `page`, `placement`, `settings`, `surface`
|
|
40
|
-
- Owner: `@jskit-ai/assistant-runtime@0.2.
|
|
40
|
+
- Owner: `@jskit-ai/assistant-runtime@0.2.4`
|
|
41
41
|
- Read: [PATTERN.md](patterns/assistant/assistant-surface/PATTERN.md)
|
|
42
42
|
- Examples: [example/](patterns/assistant/assistant-surface/example/)
|
|
43
43
|
- Requires: `@jskit-ai/assistant-runtime`, `@jskit-ai/connectors-catalog`, `@jskit-ai/connectors-core`, `@jskit-ai/shell-web`
|
|
@@ -48,7 +48,7 @@ Run one OpenID Connect sign-in for all of an owner's apps as its own JSKIT proje
|
|
|
48
48
|
|
|
49
49
|
- Id: `auth/accounts-hub`
|
|
50
50
|
- Keywords: `accounts hub`, `auth`, `authentication`, `issuer`, `master login`, `oidc`, `openid connect`, `single sign-on`, `sso`
|
|
51
|
-
- Owner: `@jskit-ai/oidc-issuer-core@0.1.
|
|
51
|
+
- Owner: `@jskit-ai/oidc-issuer-core@0.1.7`
|
|
52
52
|
- Read: [PATTERN.md](patterns/auth/accounts-hub/PATTERN.md)
|
|
53
53
|
- Examples: [example/](patterns/auth/accounts-hub/example/)
|
|
54
54
|
- Requires: `@jskit-ai/oidc-issuer-core`
|
|
@@ -70,7 +70,7 @@ Let people sign in with the accounts they already have in an accounts hub or ano
|
|
|
70
70
|
|
|
71
71
|
- Id: `auth/oidc-sign-in`
|
|
72
72
|
- Keywords: `accounts hub`, `auth`, `authentication`, `back-channel logout`, `dynamic client registration`, `issuer`, `master login`, `oidc`, `openid connect`, `single sign-on`, `sso`
|
|
73
|
-
- Owner: `@jskit-ai/auth-provider-oidc-core@0.2.
|
|
73
|
+
- Owner: `@jskit-ai/auth-provider-oidc-core@0.2.2`
|
|
74
74
|
- Read: [PATTERN.md](patterns/auth/oidc-sign-in/PATTERN.md)
|
|
75
75
|
- Examples: [example/](patterns/auth/oidc-sign-in/example/)
|
|
76
76
|
- Requires: `@jskit-ai/auth-provider-oidc-core`, `@jskit-ai/auth-web`
|
|
@@ -246,7 +246,7 @@ Add a protected administration surface, settings shell, and semantic navigation
|
|
|
246
246
|
|
|
247
247
|
- Id: `console/console-surface`
|
|
248
248
|
- Keywords: `admin`, `console`, `navigation`, `owner`, `placement`, `settings`, `surface`
|
|
249
|
-
- Owner: `@jskit-ai/console-web@0.1.
|
|
249
|
+
- Owner: `@jskit-ai/console-web@0.1.222`
|
|
250
250
|
- Read: [PATTERN.md](patterns/console/console-surface/PATTERN.md)
|
|
251
251
|
- Examples: [example/](patterns/console/console-surface/example/)
|
|
252
252
|
- Requires: `@jskit-ai/console-core`, `@jskit-ai/console-web`, `@jskit-ai/shell-web`
|
|
@@ -257,7 +257,7 @@ Build a routed CRUD user interface as thin application pages over JSKIT's shared
|
|
|
257
257
|
|
|
258
258
|
- Id: `crud/crud-screen-set`
|
|
259
259
|
- Keywords: `actions`, `add`, `crud`, `delete`, `edit`, `filters`, `list`, `material`, `routes`, `view`, `vue`
|
|
260
|
-
- Owner: `@jskit-ai/http-web@0.2.
|
|
260
|
+
- Owner: `@jskit-ai/http-web@0.2.3`
|
|
261
261
|
- Read: [PATTERN.md](patterns/crud/crud-screen-set/PATTERN.md)
|
|
262
262
|
- Examples: [example/](patterns/crud/crud-screen-set/example/)
|
|
263
263
|
- Requires: `@jskit-ai/http-web`, `@jskit-ai/resource-crud-core`
|
|
@@ -323,7 +323,7 @@ Add JSKIT realtime events with an optional Redis backplane and an explicit shell
|
|
|
323
323
|
|
|
324
324
|
- Id: `realtime/realtime-application`
|
|
325
325
|
- Keywords: `realtime`, `redis`, `socket.io`, `sockets`, `status`, `websocket`
|
|
326
|
-
- Owner: `@jskit-ai/realtime@0.2.
|
|
326
|
+
- Owner: `@jskit-ai/realtime@0.2.2`
|
|
327
327
|
- Read: [PATTERN.md](patterns/realtime/realtime-application/PATTERN.md)
|
|
328
328
|
- Examples: [example/](patterns/realtime/realtime-application/example/)
|
|
329
329
|
- Requires: `@jskit-ai/realtime`, `@jskit-ai/shell-web`
|
|
@@ -334,7 +334,7 @@ Compose application-owned Google Publisher Tag delivery with the generic rewarde
|
|
|
334
334
|
|
|
335
335
|
- Id: `rewards/google-rewarded`
|
|
336
336
|
- Keywords: `ads`, `google`, `publisher tag`, `rewarded`, `unlock`
|
|
337
|
-
- Owner: `@jskit-ai/rewarded-web@0.2.
|
|
337
|
+
- Owner: `@jskit-ai/rewarded-web@0.2.2`
|
|
338
338
|
- Read: [PATTERN.md](patterns/rewards/google-rewarded/PATTERN.md)
|
|
339
339
|
- Examples: [example/](patterns/rewards/google-rewarded/example/)
|
|
340
340
|
- Requires: `@jskit-ai/rewarded-web`
|
|
@@ -345,7 +345,7 @@ Define a server feature through explicit capabilities and first-class actions, a
|
|
|
345
345
|
|
|
346
346
|
- Id: `server/feature-package`
|
|
347
347
|
- Keywords: `actions`, `feature`, `json-rest`, `knex`, `orchestration`, `package`, `provider`, `repository`, `routes`, `server`
|
|
348
|
-
- Owner: `@jskit-ai/agent-docs@0.1.
|
|
348
|
+
- Owner: `@jskit-ai/agent-docs@0.1.252`
|
|
349
349
|
- Read: [PATTERN.md](patterns/server/feature-package/PATTERN.md)
|
|
350
350
|
- Examples: [example/](patterns/server/feature-package/example/)
|
|
351
351
|
- Requires: `@jskit-ai/kernel`
|
|
@@ -374,11 +374,11 @@ Add product routes and shell extensions through file routing, semantic placement
|
|
|
374
374
|
|
|
375
375
|
## Account settings surface
|
|
376
376
|
|
|
377
|
-
Compose an account settings route and profile, preference, and
|
|
377
|
+
Compose an account settings route and profile, preference, notification, and sign-in method sections from JSKIT user web components.
|
|
378
378
|
|
|
379
379
|
- Id: `users/account-settings`
|
|
380
|
-
- Keywords: `account`, `notifications`, `preferences`, `profile`, `settings`, `user`, `vue`
|
|
381
|
-
- Owner: `@jskit-ai/users-web@0.2.
|
|
380
|
+
- Keywords: `account`, `link provider`, `notifications`, `oauth`, `preferences`, `profile`, `settings`, `sign-in methods`, `user`, `vue`
|
|
381
|
+
- Owner: `@jskit-ai/users-web@0.2.3`
|
|
382
382
|
- Read: [PATTERN.md](patterns/users/account-settings/PATTERN.md)
|
|
383
383
|
- Examples: [example/](patterns/users/account-settings/example/)
|
|
384
384
|
- Requires: `@jskit-ai/shell-web`, `@jskit-ai/users-core`, `@jskit-ai/users-web`
|
|
@@ -389,7 +389,7 @@ Expose user administration and workspace-scoped member operations through app-ow
|
|
|
389
389
|
|
|
390
390
|
- Id: `users/user-administration-server`
|
|
391
391
|
- Keywords: `account`, `admin`, `member`, `repository`, `resource`, `routes`, `service`, `user`, `workspace`
|
|
392
|
-
- Owner: `@jskit-ai/users-core@0.2.
|
|
392
|
+
- Owner: `@jskit-ai/users-core@0.2.2`
|
|
393
393
|
- Read: [PATTERN.md](patterns/users/user-administration-server/PATTERN.md)
|
|
394
394
|
- Examples: [example/](patterns/users/user-administration-server/example/)
|
|
395
395
|
- Requires: `@jskit-ai/crud-core`, `@jskit-ai/users-core`
|
|
@@ -400,7 +400,7 @@ Configure roles, workspace access policy, invitations, and app-owned invitation
|
|
|
400
400
|
|
|
401
401
|
- Id: `workspaces/workspace-server`
|
|
402
402
|
- Keywords: `access`, `invite`, `membership`, `multitenancy`, `policy`, `role`, `tenancy`, `workspace`
|
|
403
|
-
- Owner: `@jskit-ai/workspaces-core@0.2.
|
|
403
|
+
- Owner: `@jskit-ai/workspaces-core@0.2.2`
|
|
404
404
|
- Read: [PATTERN.md](patterns/workspaces/workspace-server/PATTERN.md)
|
|
405
405
|
- Examples: [example/](patterns/workspaces/workspace-server/example/)
|
|
406
406
|
- Requires: `@jskit-ai/users-core`, `@jskit-ai/workspaces-core`
|
|
@@ -411,7 +411,7 @@ Compose workspace selection, invitation, member administration, settings, and re
|
|
|
411
411
|
|
|
412
412
|
- Id: `workspaces/workspace-surfaces`
|
|
413
413
|
- Keywords: `admin`, `invite`, `member`, `navigation`, `settings`, `surface`, `switcher`, `workspace`
|
|
414
|
-
- Owner: `@jskit-ai/workspaces-web@0.2.
|
|
414
|
+
- Owner: `@jskit-ai/workspaces-web@0.2.3`
|
|
415
415
|
- Read: [PATTERN.md](patterns/workspaces/workspace-surfaces/PATTERN.md)
|
|
416
416
|
- Examples: [example/](patterns/workspaces/workspace-surfaces/example/)
|
|
417
417
|
- Requires: `@jskit-ai/shell-web`, `@jskit-ai/workspaces-core`, `@jskit-ai/workspaces-web`
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: users/account-settings
|
|
3
3
|
title: Account settings surface
|
|
4
|
-
summary: Compose an account settings route and profile, preference, and
|
|
5
|
-
keywords: account, notifications, preferences, profile, settings, user, vue
|
|
4
|
+
summary: Compose an account settings route and profile, preference, notification, and sign-in method sections from JSKIT user web components.
|
|
5
|
+
keywords: account, notifications, preferences, profile, settings, sign-in methods, oauth, link provider, user, vue
|
|
6
6
|
requires: @jskit-ai/users-core, @jskit-ai/users-web, @jskit-ai/shell-web
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -38,6 +38,15 @@ app's language; the app does, for example
|
|
|
38
38
|
`watch(useAccountLocale(), (code) => { if (code) i18n.global.locale.value = code; }, { immediate: true })`.
|
|
39
39
|
Section titles may be plain text, a message key or `{ key, fallback }`.
|
|
40
40
|
|
|
41
|
+
`runtime.signInMethods.methods` lists the auth provider's OAuth sign-in
|
|
42
|
+
methods as `{ provider, label, linked, canLink, canUnlink }`, read from the
|
|
43
|
+
settings security status. `link(provider)` leaves for the provider through
|
|
44
|
+
`GET /api/settings/security/oauth/:provider/start` and comes back to the current
|
|
45
|
+
page; `unlink(provider)` sends `DELETE /api/settings/security/oauth/:provider`
|
|
46
|
+
and reports the result with the standard toast. `canUnlink` is false for the
|
|
47
|
+
account's only sign-in method. Add this section only when the selected auth
|
|
48
|
+
provider offers provider linking (`providerLinking` in its capabilities).
|
|
49
|
+
|
|
41
50
|
## Invariants
|
|
42
51
|
|
|
43
52
|
- Sections use JSKIT account settings APIs rather than direct HTTP helpers.
|
|
@@ -51,7 +60,7 @@ Section titles may be plain text, a message key or `{ key, fallback }`.
|
|
|
51
60
|
|
|
52
61
|
## Example files
|
|
53
62
|
|
|
54
|
-
`example/` contains an account route and
|
|
63
|
+
`example/` contains an account route and four concrete settings sections.
|
|
55
64
|
Adapt their fields and copy while retaining the shared account runtime.
|
|
56
65
|
|
|
57
66
|
## Variation points
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const props = defineProps({
|
|
3
|
+
runtime: {
|
|
4
|
+
type: Object,
|
|
5
|
+
required: true
|
|
6
|
+
}
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const signInMethods = props.runtime.signInMethods;
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<v-sheet rounded="lg" border class="account-settings-section">
|
|
14
|
+
<v-list lines="two" class="py-0">
|
|
15
|
+
<v-list-item
|
|
16
|
+
v-for="method in signInMethods.methods.value"
|
|
17
|
+
:key="method.provider"
|
|
18
|
+
:title="method.label"
|
|
19
|
+
:subtitle="method.linked ? 'Linked' : 'Not linked'"
|
|
20
|
+
>
|
|
21
|
+
<template #append>
|
|
22
|
+
<v-btn
|
|
23
|
+
v-if="method.linked"
|
|
24
|
+
variant="text"
|
|
25
|
+
color="error"
|
|
26
|
+
:loading="signInMethods.unlinkingProvider.value === method.provider"
|
|
27
|
+
:disabled="!method.canUnlink || signInMethods.isRefreshing.value"
|
|
28
|
+
@click="signInMethods.unlink(method.provider)"
|
|
29
|
+
>
|
|
30
|
+
Unlink
|
|
31
|
+
</v-btn>
|
|
32
|
+
<v-btn
|
|
33
|
+
v-else
|
|
34
|
+
variant="tonal"
|
|
35
|
+
color="primary"
|
|
36
|
+
:disabled="!method.canLink || signInMethods.isRefreshing.value"
|
|
37
|
+
@click="signInMethods.link(method.provider)"
|
|
38
|
+
>
|
|
39
|
+
Link
|
|
40
|
+
</v-btn>
|
|
41
|
+
</template>
|
|
42
|
+
</v-list-item>
|
|
43
|
+
</v-list>
|
|
44
|
+
<p
|
|
45
|
+
v-if="signInMethods.methods.value.some((method) => method.linked && !method.canUnlink)"
|
|
46
|
+
class="account-settings-section__hint text-body-2 text-medium-emphasis mb-0"
|
|
47
|
+
>
|
|
48
|
+
Your only sign-in method can't be unlinked. Set a password or link another provider first.
|
|
49
|
+
</p>
|
|
50
|
+
</v-sheet>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<style scoped>
|
|
54
|
+
.account-settings-section {
|
|
55
|
+
overflow: hidden;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.account-settings-section__hint {
|
|
59
|
+
padding: 0 1rem 1rem;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@media (max-width: 640px) {
|
|
63
|
+
.account-settings-section :deep(.v-btn) {
|
|
64
|
+
min-height: 48px;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
</style>
|