@idp.global/sdk 18.0.1 → 18.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/changelog.md +28 -0
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts_relyingparty/classes.actorscope.d.ts +23 -0
  4. package/dist_ts_relyingparty/classes.actorscope.js +22 -0
  5. package/dist_ts_relyingparty/classes.authorityobserver.d.ts +81 -0
  6. package/dist_ts_relyingparty/classes.authorityobserver.js +185 -0
  7. package/dist_ts_relyingparty/classes.errors.d.ts +37 -0
  8. package/dist_ts_relyingparty/classes.errors.js +60 -0
  9. package/dist_ts_relyingparty/classes.idpoidcprovider.d.ts +142 -0
  10. package/dist_ts_relyingparty/classes.idpoidcprovider.js +255 -0
  11. package/dist_ts_relyingparty/classes.relyingpartyroutes.d.ts +102 -0
  12. package/dist_ts_relyingparty/classes.relyingpartyroutes.js +248 -0
  13. package/dist_ts_relyingparty/classes.relyingpartysessions.d.ts +223 -0
  14. package/dist_ts_relyingparty/classes.relyingpartysessions.js +825 -0
  15. package/dist_ts_relyingparty/classes.rpmodels.d.ts +87 -0
  16. package/dist_ts_relyingparty/classes.rpmodels.js +302 -0
  17. package/dist_ts_relyingparty/classes.secretbox.d.ts +14 -0
  18. package/dist_ts_relyingparty/classes.secretbox.js +45 -0
  19. package/dist_ts_relyingparty/classes.socketbinding.d.ts +84 -0
  20. package/dist_ts_relyingparty/classes.socketbinding.js +100 -0
  21. package/dist_ts_relyingparty/helpers.cookies.d.ts +11 -0
  22. package/dist_ts_relyingparty/helpers.cookies.js +62 -0
  23. package/dist_ts_relyingparty/helpers.crypto.d.ts +12 -0
  24. package/dist_ts_relyingparty/helpers.crypto.js +40 -0
  25. package/dist_ts_relyingparty/helpers.returnpath.d.ts +9 -0
  26. package/dist_ts_relyingparty/helpers.returnpath.js +39 -0
  27. package/dist_ts_relyingparty/index.d.ts +13 -0
  28. package/dist_ts_relyingparty/index.js +14 -0
  29. package/dist_ts_relyingparty/interfaces.d.ts +142 -0
  30. package/dist_ts_relyingparty/interfaces.js +2 -0
  31. package/dist_ts_relyingparty/plugins.d.ts +10 -0
  32. package/dist_ts_relyingparty/plugins.js +11 -0
  33. package/package.json +13 -10
  34. package/readme.md +215 -4
  35. package/ts/00_commitinfo_data.ts +1 -1
  36. package/ts_relyingparty/classes.actorscope.ts +39 -0
  37. package/ts_relyingparty/classes.authorityobserver.ts +253 -0
  38. package/ts_relyingparty/classes.errors.ts +77 -0
  39. package/ts_relyingparty/classes.idpoidcprovider.ts +386 -0
  40. package/ts_relyingparty/classes.relyingpartyroutes.ts +319 -0
  41. package/ts_relyingparty/classes.relyingpartysessions.ts +1017 -0
  42. package/ts_relyingparty/classes.rpmodels.ts +170 -0
  43. package/ts_relyingparty/classes.secretbox.ts +49 -0
  44. package/ts_relyingparty/classes.socketbinding.ts +156 -0
  45. package/ts_relyingparty/helpers.cookies.ts +79 -0
  46. package/ts_relyingparty/helpers.crypto.ts +49 -0
  47. package/ts_relyingparty/helpers.returnpath.ts +44 -0
  48. package/ts_relyingparty/index.ts +13 -0
  49. package/ts_relyingparty/interfaces.ts +165 -0
  50. package/ts_relyingparty/plugins.ts +17 -0
@@ -0,0 +1,223 @@
1
+ import { type IOidcProvider } from './classes.idpoidcprovider.js';
2
+ import type { IRelyingPartyModels } from './classes.rpmodels.js';
3
+ import type { IAuthorityTokenSource, IProviderToken, IRelyingPartyHooks, IRelyingPartyLiveSession, IRelyingPartyLoginStart, IRelyingPartySession, IRelyingPartySessionOpening, IResolvedRelyingPartySession, TRelyingPartyPrincipals, TRelyingPartySessionEndReason } from './interfaces.js';
4
+ export declare const RELYING_PARTY_DEFAULT_SESSION_MAX_AGE_SECONDS: number;
5
+ export declare const RELYING_PARTY_DEFAULT_LOGIN_PATH_PREFIX = "/auth/";
6
+ /** The label the CSRF HMAC starts with unless the application names its own. */
7
+ export declare const RELYING_PARTY_DEFAULT_CSRF_LABEL: string;
8
+ /** A sign-in transaction has to survive an interactive login at the provider, not a working day. */
9
+ export declare const LOGIN_ATTEMPT_MAX_AGE_SECONDS: number;
10
+ /**
11
+ * How long ending a session waits for the provider to take its tokens back.
12
+ * The local session is already revoked when that call runs.
13
+ */
14
+ export declare const TOKEN_REVOCATION_BUDGET_MS = 3000;
15
+ /** How long before its expiry the provider access token is rotated. */
16
+ export declare const ACCESS_TOKEN_REFRESH_SKEW_MS = 60000;
17
+ /**
18
+ * What the refresh lock adds on top of the provider request it has to cover:
19
+ * the claim and the store around it, and clock disagreement between replicas.
20
+ */
21
+ export declare const REFRESH_LOCK_MARGIN_MS = 20000;
22
+ export interface IRelyingPartySessionsOptions<TPrincipal extends object | undefined = undefined> {
23
+ models: IRelyingPartyModels;
24
+ /**
25
+ * `isActive` principals, or a `resolve` that answers the principal itself;
26
+ * its answer is then the `principal` of every live session.
27
+ */
28
+ principals: TRelyingPartyPrincipals<TPrincipal>;
29
+ /** absent: no provider login; sessions are opened by the application only */
30
+ provider?: IOidcProvider;
31
+ /** the application's public origin, e.g. `https://app.example`; cookies are `Secure` exactly on https */
32
+ publicOrigin: string;
33
+ /** 32 bytes; seals the PKCE verifier and the provider tokens at rest */
34
+ sessionEncryptionKey: Buffer;
35
+ /** 32 bytes; the CSRF HMAC key */
36
+ csrfKey: Buffer;
37
+ /** the label the CSRF HMAC starts with; an application with live sessions keeps its own */
38
+ csrfLabel?: string;
39
+ sessionMaxAgeSeconds?: number;
40
+ /**
41
+ * defaults: `__Host-idp_rp_session` / `__Host-idp_rp_intent` on https,
42
+ * without the prefix otherwise. A `__Host-` or `__Secure-` name needs an
43
+ * https origin and is refused on http.
44
+ */
45
+ cookieNames?: {
46
+ session?: string;
47
+ intent?: string;
48
+ };
49
+ /** the prefix of the login routes; a login never returns into it */
50
+ loginPathPrefix?: string;
51
+ hooks?: IRelyingPartyHooks;
52
+ /** the clock every comparison reads; tests step it instead of sleeping */
53
+ now?: () => number;
54
+ }
55
+ /**
56
+ * The relying-party session layer: provider logins through the authorization
57
+ * code flow with PKCE, HttpOnly cookie sessions with a session-bound CSRF
58
+ * token, provider tokens sealed at rest and rotated under a cross-replica
59
+ * lock, and session ends that hand the tokens back.
60
+ *
61
+ * Nothing here runs on a timer: expired login attempts are swept when the next
62
+ * login starts, and the only timer — the revocation budget — is unreferenced
63
+ * and cleared on every path. Nothing here does I/O while it is constructed,
64
+ * so it is built before the database connects.
65
+ *
66
+ * `TPrincipal` is what a `principals.resolve` answers; with `isActive`
67
+ * principals it stays `undefined`.
68
+ */
69
+ export declare class RelyingPartySessions<TPrincipal extends object | undefined = undefined> implements IAuthorityTokenSource {
70
+ #private;
71
+ readonly publicOrigin: string;
72
+ readonly secureCookies: boolean;
73
+ readonly sessionCookieName: string;
74
+ readonly intentCookieName: string;
75
+ readonly loginPathPrefix: string;
76
+ readonly sessionMaxAgeSeconds: number;
77
+ constructor(optionsArg: IRelyingPartySessionsOptions<TPrincipal>);
78
+ /** Whether provider logins are offered at all. */
79
+ get providerLoginEnabled(): boolean;
80
+ /**
81
+ * How long one replica holds the right to rotate a session's tokens. The
82
+ * provider detects reuse of a superseded refresh token and kills the family,
83
+ * so the lock strictly outlives its longest possible holder: one provider
84
+ * request at its full deadline plus the margin.
85
+ */
86
+ get refreshLockMs(): number;
87
+ /**
88
+ * Opens a session the application authenticated itself (a local password
89
+ * login). It carries no provider tokens.
90
+ */
91
+ openSession(optionsArg: {
92
+ principalId: string;
93
+ }): Promise<IRelyingPartySessionOpening>;
94
+ /** The live session behind the session cookie, or `null`. A read touches it at most once a minute. */
95
+ resolveCookieSession(cookieHeaderArg: string | null | undefined): Promise<IResolvedRelyingPartySession<TPrincipal> | null>;
96
+ /**
97
+ * Re-checks a session by its id with the same strength as a cookie request:
98
+ * live, its principal active, and touched under the liveness it was read
99
+ * with. What a pinned socket connection runs per request.
100
+ */
101
+ revalidateSession(sessionIdArg: string): Promise<IRelyingPartySession | null>;
102
+ /** `revalidateSession`, answering the principal the same read resolved as well. */
103
+ revalidateLiveSession(sessionIdArg: string): Promise<IRelyingPartyLiveSession<TPrincipal> | null>;
104
+ /** Whether a session is live right now, without touching it; what a sweep asks. */
105
+ isSessionLive(sessionIdArg: string): Promise<boolean>;
106
+ /** Whether a candidate is the CSRF token of a resolved (or just opened) session, compared in constant time. */
107
+ validateCsrf(resolvedArg: {
108
+ csrfToken: string;
109
+ }, candidateArg: unknown): boolean;
110
+ /** Ends one session; see `endSession`. */
111
+ logout(sessionIdArg: string): Promise<boolean>;
112
+ /**
113
+ * Revokes a session once, with one conditional update: a touch running
114
+ * beside it cannot write the revocation away, and a second call finds
115
+ * nothing. Its provider tokens go back within `TOKEN_REVOCATION_BUDGET_MS`,
116
+ * after the local revocation, which never depends on the provider. Answers
117
+ * whether this call ended it.
118
+ */
119
+ endSession(sessionIdArg: string, reasonArg?: TRelyingPartySessionEndReason): Promise<boolean>;
120
+ /**
121
+ * Ends every live session of a principal but `keepSessionId` (a password
122
+ * change keeps the session that asked for it) and answers how many ended.
123
+ */
124
+ endSessionsOfPrincipal(principalIdArg: string, optionsArg?: {
125
+ keepSessionId?: string;
126
+ }): Promise<number>;
127
+ clearSessionCookie(): string;
128
+ clearIntentCookie(): string;
129
+ /**
130
+ * Starts a sign-in transaction: one attempt document with the PKCE verifier
131
+ * sealed next to it, and an intent cookie that binds the callback to this
132
+ * browser.
133
+ */
134
+ startLogin(returnPathArg: unknown): Promise<IRelyingPartyLoginStart>;
135
+ /**
136
+ * Consumes the attempt exactly once, exchanges the code, admits the
137
+ * principal and opens a session. A replayed callback, a foreign intent
138
+ * cookie and an expired attempt all find nothing to consume. Nothing of a
139
+ * failed login survives: its tokens are handed back before the failure
140
+ * leaves.
141
+ */
142
+ completeLogin(callbackUrlArg: URL, cookieHeaderArg: string | null | undefined): Promise<IRelyingPartySessionOpening>;
143
+ /**
144
+ * The provider sent the browser back without a code. The attempt is
145
+ * consumed so its state can never complete afterwards; a callback that
146
+ * matches no open attempt leaves nothing to do.
147
+ */
148
+ abandonLogin(callbackUrlArg: URL, cookieHeaderArg: string | null | undefined): Promise<void>;
149
+ /**
150
+ * The last step of a login: the browser arrives with both cookies, and the
151
+ * return path is released only when the session cookie belongs to the
152
+ * session this very attempt created.
153
+ */
154
+ finalizeLogin(cookieHeaderArg: string | null | undefined): Promise<string>;
155
+ /**
156
+ * An access token of this login session that is usable right now. A token
157
+ * within `ACCESS_TOKEN_REFRESH_SKEW_MS` of its expiry — or one whose expiry
158
+ * is unknown — is rotated first. The session has to belong to
159
+ * `expectedPrincipalIdArg`, so a credential is never evaluated with another
160
+ * person's tokens.
161
+ */
162
+ liveProviderToken(sessionIdArg: string, expectedPrincipalIdArg: string): Promise<IProviderToken>;
163
+ private refreshProviderToken;
164
+ private runProviderRefresh;
165
+ /**
166
+ * Another replica is rotating this session right now. Whatever it has
167
+ * written by the time this request looks again is used; otherwise the
168
+ * request fails closed and the next one finds the rotated pair.
169
+ */
170
+ private tokenAfterForeignRefresh;
171
+ private requireProvider;
172
+ private newSessionDoc;
173
+ private csrfTokenOf;
174
+ private opening;
175
+ private snapshot;
176
+ /** A session document that is live right now with its active principal, touched at most once a minute. */
177
+ private liveSession;
178
+ private createProviderSession;
179
+ /** Revokes a session that was never handed out and erases its sealed tokens. */
180
+ private discardUnopenedSession;
181
+ /**
182
+ * Tells the application a session ended. Its hook never stands between the
183
+ * local revocation and the provider revocation: a throw or a rejection is
184
+ * reported as `hook_failed` and the end runs on.
185
+ */
186
+ private notifySessionEnded;
187
+ /**
188
+ * The conditional revocation every end of a session runs. Answers the
189
+ * sealed tokens it took off the session when this call revoked it, `null`
190
+ * when the session was already over.
191
+ */
192
+ private revokeSession;
193
+ /** The provider says the login is over: the session ends here without asking it anything more. */
194
+ private endProviderSession;
195
+ /**
196
+ * Hands the tokens of an ended session back, best-effort and within the
197
+ * budget. A sealed value this deployment can no longer open is skipped.
198
+ */
199
+ private revokeSealedTokens;
200
+ private revokeRotatedTokens;
201
+ private revokeCompletionTokens;
202
+ private revokeToken;
203
+ /**
204
+ * Runs a best-effort provider step under `TOKEN_REVOCATION_BUDGET_MS`. What
205
+ * is still in flight at the deadline keeps running and ends on the provider
206
+ * client's own request timeout; only the waiting stops. The timer is cleared
207
+ * on every path and unreferenced.
208
+ */
209
+ private withinRevocationBudget;
210
+ /** A sealed value this deployment can still open, or `undefined`. */
211
+ private openSealed;
212
+ /**
213
+ * Removes attempts an hour past their expiry, one bounded page per login
214
+ * start. A sweep that cannot run never blocks a sign-in.
215
+ */
216
+ private sweepExpiredAttempts;
217
+ /**
218
+ * Reports one diagnostic. Every cleanup step reports through here, so a
219
+ * throwing sink must not end it: the event and the sink's failure go to
220
+ * `console.error` instead.
221
+ */
222
+ private emit;
223
+ }