@spfn/auth 0.3.0-beta.23 → 0.3.0-beta.24
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 +165 -2
- package/dist/client-proof.js +13 -5
- package/dist/client-proof.js.map +1 -1
- package/dist/client.d.ts +52 -1
- package/dist/client.js +40 -0
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +82 -0
- package/dist/config.js +37 -0
- package/dist/config.js.map +1 -1
- package/dist/crypto.d.ts +1 -1
- package/dist/errors.d.ts +113 -3
- package/dist/errors.js +68 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +38 -5
- package/dist/index.js +73 -2
- package/dist/index.js.map +1 -1
- package/dist/{machine-principals-CaEFq61K.d.ts → machine-principals-ZJd9anVT.d.ts} +1667 -900
- package/dist/nextjs/api.js +156 -6
- package/dist/nextjs/api.js.map +1 -1
- package/dist/nextjs/server.d.ts +42 -24
- package/dist/nextjs/server.js +72 -5
- package/dist/nextjs/server.js.map +1 -1
- package/dist/server.d.ts +448 -525
- package/dist/server.js +1389 -653
- package/dist/server.js.map +1 -1
- package/dist/{session-Dfwu5g2W.d.ts → session-BbhAGZtA.d.ts} +57 -1
- package/dist/{types-DYyhze28.d.ts → types-CTdoTOxM.d.ts} +24 -1
- package/migrations/20260918184037_happy_mordo/migration.sql +4 -0
- package/migrations/20260918184037_happy_mordo/snapshot.json +6000 -0
- package/migrations/20260918184152_dear_rictor/migration.sql +3 -0
- package/migrations/20260918184152_dear_rictor/snapshot.json +6039 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { K as KeyAlgorithmType } from './types-
|
|
1
|
+
import { K as KeyAlgorithmType, S as SessionBindingType } from './types-CTdoTOxM.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @spfn/auth - Return-path validation
|
|
@@ -27,6 +27,35 @@ import { K as KeyAlgorithmType } from './types-DYyhze28.js';
|
|
|
27
27
|
*/
|
|
28
28
|
declare function isSafeReturnPath(returnPath: string): boolean;
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* The browser family a `user-agent` names — five badges, and nothing else.
|
|
32
|
+
*
|
|
33
|
+
* A bound session records the family it was sealed from and the Next.js proxy
|
|
34
|
+
* compares every later request against it (#97). The comparison has to be coarse
|
|
35
|
+
* on purpose: a version bump, a minor-version reduction, a platform token that
|
|
36
|
+
* changes when someone taps "Request desktop site" must all still be the same
|
|
37
|
+
* browser, or the check signs people out for ordinary acts instead of catching
|
|
38
|
+
* the cookie that moved to another machine.
|
|
39
|
+
*
|
|
40
|
+
* A fixed table rather than a parsing dependency. `package.json` carries no
|
|
41
|
+
* user-agent parser and adding one to answer a five-valued question would be out
|
|
42
|
+
* of proportion; the table below is the whole of what this package needs to know
|
|
43
|
+
* about user-agent strings.
|
|
44
|
+
*
|
|
45
|
+
* @module server/lib/ua-family
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* The five answers, and deliberately no sixth.
|
|
49
|
+
*
|
|
50
|
+
* There is no desktop/mobile axis. Android's "Request desktop site" flips the
|
|
51
|
+
* platform token on the same browser in the same cookie jar, and a session that
|
|
52
|
+
* refused after that would be a support ticket for a thing the user did on
|
|
53
|
+
* purpose. What this check is looking for is a cookie that moved to a *different*
|
|
54
|
+
* browser, and the browser is what the badge names.
|
|
55
|
+
*/
|
|
56
|
+
declare const UA_FAMILIES: readonly ["edge", "chrome", "firefox", "safari", "other"];
|
|
57
|
+
type UaFamily = typeof UA_FAMILIES[number];
|
|
58
|
+
|
|
30
59
|
/**
|
|
31
60
|
* @spfn/auth - Client Session Management
|
|
32
61
|
*
|
|
@@ -34,11 +63,38 @@ declare function isSafeReturnPath(returnPath: string): boolean;
|
|
|
34
63
|
* More efficient than Iron Session with better Edge Runtime support
|
|
35
64
|
*/
|
|
36
65
|
|
|
66
|
+
/**
|
|
67
|
+
* What the sealed cookie carries.
|
|
68
|
+
*
|
|
69
|
+
* The first four fields are the session itself and have always been here. The
|
|
70
|
+
* last three are what #97 added, and all three are optional together: a cookie
|
|
71
|
+
* without them is an unbound session, which is every session an account that did
|
|
72
|
+
* not opt in gets and every session an app seals by hand with `saveSession()`.
|
|
73
|
+
* The proxy reads their absence as "behave exactly as before".
|
|
74
|
+
*/
|
|
37
75
|
interface SessionData {
|
|
38
76
|
userId: string;
|
|
39
77
|
privateKey: string;
|
|
40
78
|
keyId: string;
|
|
41
79
|
algorithm: KeyAlgorithmType;
|
|
80
|
+
/**
|
|
81
|
+
* `'passkey'` when the key sealed here is bound.
|
|
82
|
+
*
|
|
83
|
+
* The backend is the only party that knows an account opted in — the proxy
|
|
84
|
+
* generated the key but never saw the setting — so this is copied out of the
|
|
85
|
+
* `LoginResult` the sign-in answered with. Absent means unbound.
|
|
86
|
+
*/
|
|
87
|
+
binding?: SessionBindingType;
|
|
88
|
+
/** Epoch milliseconds the bound key expires at. Only set alongside `binding`. */
|
|
89
|
+
keyExpiresAt?: number;
|
|
90
|
+
/**
|
|
91
|
+
* Browser family the session was sealed from, per `uaFamily`.
|
|
92
|
+
*
|
|
93
|
+
* Recorded here rather than read off the key row because the comparison
|
|
94
|
+
* happens in the proxy: it is the only hop that sees the browser's own
|
|
95
|
+
* `user-agent`, and a server component's call to the RPC proxy carries none.
|
|
96
|
+
*/
|
|
97
|
+
uaFamily?: UaFamily;
|
|
42
98
|
}
|
|
43
99
|
/**
|
|
44
100
|
* Seal session data into encrypted JWT (JWE)
|
|
@@ -28,6 +28,29 @@ declare const KEY_PLATFORM: readonly ["ios", "android", "web", "desktop"];
|
|
|
28
28
|
type KeyPlatformType = typeof KEY_PLATFORM[number];
|
|
29
29
|
/** Longest device label accepted at registration, and what the list returns. */
|
|
30
30
|
declare const KEY_DEVICE_NAME_MAX_LENGTH = 64;
|
|
31
|
+
/**
|
|
32
|
+
* Whether a session's device key is tied to something that cannot be copied out
|
|
33
|
+
* of the browser.
|
|
34
|
+
*
|
|
35
|
+
* `'none'` is every session this package issued before #97: a key that lives
|
|
36
|
+
* ninety days, sealed inside the cookie, so a copy of that cookie signs exactly
|
|
37
|
+
* as the original does for as long as the key lasts. `'passkey'` is the opt-in —
|
|
38
|
+
* a key that lives hours instead, which only a fresh WebAuthn assertion may
|
|
39
|
+
* replace, so the copy stops working at the first renewal.
|
|
40
|
+
*
|
|
41
|
+
* The same two values name the account setting (`users.session_binding`) and the
|
|
42
|
+
* fact recorded on one key row (`user_public_keys.binding`). They are one list
|
|
43
|
+
* because a key is bound exactly when the account that owns it asked for it, and
|
|
44
|
+
* a second vocabulary would only invite the two to drift.
|
|
45
|
+
*
|
|
46
|
+
* Server-decided, always. Nothing on a request body chooses it — see
|
|
47
|
+
* `registerPublicKeyService`.
|
|
48
|
+
*/
|
|
49
|
+
declare const SESSION_BINDINGS: readonly ["none", "passkey"];
|
|
50
|
+
/**
|
|
51
|
+
* Session binding type derived from the const array
|
|
52
|
+
*/
|
|
53
|
+
type SessionBindingType = typeof SESSION_BINDINGS[number];
|
|
31
54
|
/**
|
|
32
55
|
* Invitation status enum values
|
|
33
56
|
* Single source of truth for all invitation statuses
|
|
@@ -95,4 +118,4 @@ declare const PURGE_STRATEGIES: readonly ["anonymize", "hard-delete"];
|
|
|
95
118
|
*/
|
|
96
119
|
type PurgeStrategy = typeof PURGE_STRATEGIES[number];
|
|
97
120
|
|
|
98
|
-
export { ACCOUNT_DELETION_REQUESTED_BY as A, INVITATION_STATUSES as I, type KeyAlgorithmType as K, PURGE_STRATEGIES as P,
|
|
121
|
+
export { ACCOUNT_DELETION_REQUESTED_BY as A, INVITATION_STATUSES as I, type KeyAlgorithmType as K, PURGE_STRATEGIES as P, type SessionBindingType as S, USER_STATUSES as U, ACCOUNT_DELETION_REQUEST_STATUSES as a, type AccountDeletionRequestStatus as b, type AccountDeletionRequestedBy as c, type InvitationStatus as d, KEY_ALGORITHM as e, KEY_DEVICE_NAME_MAX_LENGTH as f, KEY_PLATFORM as g, type KeyPlatformType as h, type PurgeStrategy as i, SESSION_BINDINGS as j, SOCIAL_PROVIDERS as k, type SocialProvider as l, type UserStatus as m };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
ALTER TABLE "spfn_auth"."users" ADD COLUMN "session_binding" text DEFAULT 'none' NOT NULL;--> statement-breakpoint
|
|
2
|
+
ALTER TABLE "spfn_auth"."users" ADD COLUMN "session_binding_changed_at" timestamp with time zone;--> statement-breakpoint
|
|
3
|
+
ALTER TABLE "spfn_auth"."user_public_keys" ADD COLUMN "registered_ua_family" text;--> statement-breakpoint
|
|
4
|
+
ALTER TABLE "spfn_auth"."user_public_keys" ADD COLUMN "binding" text DEFAULT 'none' NOT NULL;
|