@seamless-auth/core 0.10.0 → 0.11.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 (129) hide show
  1. package/README.md +50 -6
  2. package/dist/apiContract.d.ts +41 -0
  3. package/dist/apiContract.d.ts.map +1 -0
  4. package/dist/apiContract.js +48 -0
  5. package/dist/apiContract.js.map +1 -0
  6. package/dist/applyResult.d.ts +100 -0
  7. package/dist/applyResult.d.ts.map +1 -0
  8. package/dist/applyResult.js +95 -0
  9. package/dist/applyResult.js.map +1 -0
  10. package/dist/authMessaging.d.ts +14 -52
  11. package/dist/authMessaging.d.ts.map +1 -1
  12. package/dist/deliverAuthMessage.d.ts +15 -0
  13. package/dist/deliverAuthMessage.d.ts.map +1 -0
  14. package/dist/deliverAuthMessage.js +123 -0
  15. package/dist/deliverAuthMessage.js.map +1 -0
  16. package/dist/ensureCookies.d.ts +2 -2
  17. package/dist/ensureCookies.d.ts.map +1 -1
  18. package/dist/ensureCookies.js +5 -5
  19. package/dist/ensureCookies.js.map +1 -1
  20. package/dist/getSeamlessUser.d.ts +9 -8
  21. package/dist/getSeamlessUser.d.ts.map +1 -1
  22. package/dist/getSeamlessUser.js.map +1 -1
  23. package/dist/guards.d.ts +73 -0
  24. package/dist/guards.d.ts.map +1 -0
  25. package/dist/guards.js +115 -0
  26. package/dist/guards.js.map +1 -0
  27. package/dist/handlers/admin.d.ts +4 -3
  28. package/dist/handlers/admin.d.ts.map +1 -1
  29. package/dist/handlers/admin.js +4 -10
  30. package/dist/handlers/admin.js.map +1 -1
  31. package/dist/handlers/finishLogin.d.ts +2 -2
  32. package/dist/handlers/finishLogin.d.ts.map +1 -1
  33. package/dist/handlers/finishLogin.js +10 -37
  34. package/dist/handlers/finishLogin.js.map +1 -1
  35. package/dist/handlers/finishRegister.d.ts +2 -2
  36. package/dist/handlers/finishRegister.d.ts.map +1 -1
  37. package/dist/handlers/finishRegister.js +10 -34
  38. package/dist/handlers/finishRegister.js.map +1 -1
  39. package/dist/handlers/internalMetrics.d.ts +4 -3
  40. package/dist/handlers/internalMetrics.d.ts.map +1 -1
  41. package/dist/handlers/internalMetrics.js +4 -10
  42. package/dist/handlers/internalMetrics.js.map +1 -1
  43. package/dist/handlers/login.d.ts +2 -2
  44. package/dist/handlers/login.d.ts.map +1 -1
  45. package/dist/handlers/login.js +6 -9
  46. package/dist/handlers/login.js.map +1 -1
  47. package/dist/handlers/logout.d.ts.map +1 -1
  48. package/dist/handlers/logout.js.map +1 -1
  49. package/dist/handlers/me.d.ts +2 -2
  50. package/dist/handlers/me.d.ts.map +1 -1
  51. package/dist/handlers/me.js +1 -1
  52. package/dist/handlers/me.js.map +1 -1
  53. package/dist/handlers/oauthHandlers.d.ts +10 -6
  54. package/dist/handlers/oauthHandlers.d.ts.map +1 -1
  55. package/dist/handlers/oauthHandlers.js +12 -39
  56. package/dist/handlers/oauthHandlers.js.map +1 -1
  57. package/dist/handlers/pollMagicLinkConfirmationHandler.d.ts +2 -2
  58. package/dist/handlers/pollMagicLinkConfirmationHandler.d.ts.map +1 -1
  59. package/dist/handlers/pollMagicLinkConfirmationHandler.js +10 -37
  60. package/dist/handlers/pollMagicLinkConfirmationHandler.js.map +1 -1
  61. package/dist/handlers/register.d.ts +2 -2
  62. package/dist/handlers/register.d.ts.map +1 -1
  63. package/dist/handlers/register.js +4 -4
  64. package/dist/handlers/register.js.map +1 -1
  65. package/dist/handlers/requestMagicLinkHandler.d.ts +2 -2
  66. package/dist/handlers/requestMagicLinkHandler.d.ts.map +1 -1
  67. package/dist/handlers/requestMagicLinkHandler.js +4 -4
  68. package/dist/handlers/requestMagicLinkHandler.js.map +1 -1
  69. package/dist/handlers/requestOtpHandler.d.ts +2 -2
  70. package/dist/handlers/requestOtpHandler.d.ts.map +1 -1
  71. package/dist/handlers/requestOtpHandler.js +4 -4
  72. package/dist/handlers/requestOtpHandler.js.map +1 -1
  73. package/dist/handlers/sessions.d.ts +2 -2
  74. package/dist/handlers/sessions.d.ts.map +1 -1
  75. package/dist/handlers/sessions.js +2 -1
  76. package/dist/handlers/sessions.js.map +1 -1
  77. package/dist/handlers/switchOrganizationHandler.d.ts +2 -2
  78. package/dist/handlers/switchOrganizationHandler.d.ts.map +1 -1
  79. package/dist/handlers/switchOrganizationHandler.js +9 -28
  80. package/dist/handlers/switchOrganizationHandler.js.map +1 -1
  81. package/dist/handlers/systemConfig.d.ts +2 -2
  82. package/dist/handlers/systemConfig.d.ts.map +1 -1
  83. package/dist/handlers/systemConfig.js +4 -3
  84. package/dist/handlers/systemConfig.js.map +1 -1
  85. package/dist/handlers/verifyLoginOtpHandler.d.ts +2 -2
  86. package/dist/handlers/verifyLoginOtpHandler.d.ts.map +1 -1
  87. package/dist/handlers/verifyLoginOtpHandler.js +10 -37
  88. package/dist/handlers/verifyLoginOtpHandler.js.map +1 -1
  89. package/dist/handlers/verifyMagicLinkHandler.d.ts +2 -2
  90. package/dist/handlers/verifyMagicLinkHandler.d.ts.map +1 -1
  91. package/dist/handlers/verifyMagicLinkHandler.js +2 -1
  92. package/dist/handlers/verifyMagicLinkHandler.js.map +1 -1
  93. package/dist/index.d.ts +15 -1
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +19 -1
  96. package/dist/index.js.map +1 -1
  97. package/dist/logger.d.ts +26 -0
  98. package/dist/logger.d.ts.map +1 -0
  99. package/dist/logger.js +24 -0
  100. package/dist/logger.js.map +1 -0
  101. package/dist/proxyRequest.d.ts +62 -0
  102. package/dist/proxyRequest.d.ts.map +1 -0
  103. package/dist/proxyRequest.js +82 -0
  104. package/dist/proxyRequest.js.map +1 -0
  105. package/dist/redaction.d.ts.map +1 -1
  106. package/dist/redaction.js +8 -2
  107. package/dist/redaction.js.map +1 -1
  108. package/dist/refreshAccessToken.d.ts.map +1 -1
  109. package/dist/refreshAccessToken.js.map +1 -1
  110. package/dist/result.d.ts +23 -0
  111. package/dist/result.d.ts.map +1 -0
  112. package/dist/result.js +2 -0
  113. package/dist/result.js.map +1 -0
  114. package/dist/upstreamError.d.ts +31 -0
  115. package/dist/upstreamError.d.ts.map +1 -0
  116. package/dist/upstreamError.js +49 -0
  117. package/dist/upstreamError.js.map +1 -0
  118. package/dist/upstreamSession.d.ts +53 -0
  119. package/dist/upstreamSession.d.ts.map +1 -0
  120. package/dist/upstreamSession.js +56 -0
  121. package/dist/upstreamSession.js.map +1 -0
  122. package/dist/verifySignedAuthResponse.d.ts.map +1 -1
  123. package/dist/verifySignedAuthResponse.js +2 -1
  124. package/dist/verifySignedAuthResponse.js.map +1 -1
  125. package/package.json +2 -1
  126. package/dist/scopedRoles.d.ts +0 -3
  127. package/dist/scopedRoles.d.ts.map +0 -1
  128. package/dist/scopedRoles.js +0 -39
  129. package/dist/scopedRoles.js.map +0 -1
package/README.md CHANGED
@@ -82,21 +82,65 @@ Core helpers enforce transitions between these states.
82
82
 
83
83
  ## Public API (Overview)
84
84
 
85
- Key exports include:
85
+ Everything below is available from the package root. The `./handlers/*` subpaths
86
+ remain for direct imports.
87
+
88
+ **Sessions and cookies**
86
89
 
87
90
  - `ensureCookies(...)` – validates and refreshes session cookies
88
91
  - `refreshAccessToken(...)` – rotates expired access sessions
89
92
  - `verifyCookieJwt(...)` – verifies signed cookie payloads
90
- - `createServiceToken(...)` – creates short-lived M2M assertions
93
+ - `verifyRefreshCookie(...)` – verifies a refresh cookie, returning `null` on failure
94
+ - `verifySignedAuthResponse(...)` – verifies an auth API response signature against its JWKS
91
95
  - `getSeamlessUser(...)` – resolves the hydrated user, typed as `SeamlessUser | null`
92
96
  - `hasScopedRole(...)` – checks scoped role grants such as `admin:read`
97
+
98
+ **Building an adapter**
99
+
100
+ - `applyResult(result, adapter, opts)` – turns a handler result into a response
101
+ - `applyCookies(result, adapter, opts)` – cookie instructions only, for middleware
102
+ - `ResponseAdapter` – the three methods an adapter provides: `setCookie`, `clearCookie`, `send`
103
+ - `proxyRequest(...)` – forwards a request to the auth API and returns its status and body
104
+ - `checkProxyIdentity(...)` – checks a request carries the session a proxied route requires
105
+ - `buildQueryString(...)` / `buildUpstreamUrl(...)` – build an upstream URL
106
+ - `signSessionCookie(...)` / `resolveCookieSameSite(...)` – cookie format and policy
107
+ - `authFetch(...)` – calls the auth API with the adapter's headers and a tolerant `json()`
108
+
109
+ **Auth flow handlers**
110
+
111
+ `loginHandler`, `finishLoginHandler`, `registerHandler`, `finishRegisterHandler`,
112
+ `logoutHandler`, `meHandler`, `requestOtpHandler`, `verifyLoginOtpHandler`,
113
+ `verifyRegistrationOtpHandler`, `requestMagicLinkHandler`, `verifyMagicLinkHandler`,
114
+ `pollMagicLinkConfirmationHandler`, `switchOrganizationHandler`,
115
+ `listOAuthProvidersHandler`, `startOAuthLoginHandler`, `finishOAuthLoginHandler`.
116
+
117
+ **Admin and operations handlers**
118
+
119
+ User, session, auth-event, metrics, and system-config handlers, for example
120
+ `getUsersHandler`, `updateUserHandler`, `listSessionsHandler`,
121
+ `getAuthEventsHandler`, `getDashboardMetricsHandler`, and
122
+ `getAvailableRolesHandler`.
123
+
124
+ **Message delivery**
125
+
126
+ - `deliverAuthMessage(...)` – delivers an auth message through the configured transports
127
+ - `applyExternalDelivery(...)` – delivers the payload on a response body and strips it
128
+ - `stripDelivery(...)` – removes the delivery payload from a body
129
+
130
+ **Auth API contract**
131
+
132
+ - `SERVICE_TOKEN_ISSUER` / `SERVICE_TOKEN_AUDIENCE` – the fixed identity for M2M service tokens
133
+ - `AUTH_DELIVERY_MODE_HEADER` / `EXTERNAL_DELIVERY_MODE` / `EXTERNAL_DELIVERY_HEADERS`
134
+ - `DEV_JWKS_KID` – the fallback key id, which is a misconfiguration to deploy on
135
+ - `createServiceToken(...)` / `buildExternalDeliveryAuthorization(...)` – mint service tokens
136
+
137
+ **Utilities**
138
+
93
139
  - `assertSecretStrength(...)` / `assertSecrets(...)` – enforce the minimum secret length
94
140
  - `redactSensitiveText(...)` – masks tokens, bearer values, and secrets before logging
95
- - `listOAuthProvidersHandler(...)` – retrieves public OAuth provider metadata
96
- - `startOAuthLoginHandler(...)` – starts an OAuth authorization-code login
97
- - `finishOAuthLoginHandler(...)` – finishes OAuth login and returns cookie instructions
98
141
 
99
- These functions return **descriptive results**, not HTTP responses.
142
+ Handlers return **descriptive results**, not HTTP responses. `applyResult` is what
143
+ turns one into a response, and it is the only place that decides how.
100
144
 
101
145
  ### Secret strength
102
146
 
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Values the auth API defines. Changing one of these is a coordinated change
3
+ * with `seamless-auth-api`, so they live here rather than being written out at
4
+ * each call site, and every adapter reads the same value.
5
+ */
6
+ /**
7
+ * Asks the auth API to return a delivery payload instead of sending the message
8
+ * itself, so the adopter's own transports deliver it.
9
+ */
10
+ export declare const AUTH_DELIVERY_MODE_HEADER = "x-seamless-auth-delivery-mode";
11
+ export declare const EXTERNAL_DELIVERY_MODE = "external";
12
+ /** Headers that request external delivery, spreadable into an `authFetch` call. */
13
+ export declare const EXTERNAL_DELIVERY_HEADERS: Readonly<Record<string, string>>;
14
+ /**
15
+ * The auth API validates machine-to-machine service tokens against a fixed
16
+ * issuer and audience. These are not the adopter's configured audience, which
17
+ * applies to user tokens: a service token signed with the adopter's audience is
18
+ * rejected.
19
+ */
20
+ export declare const SERVICE_TOKEN_ISSUER = "seamless-portal-api";
21
+ export declare const SERVICE_TOKEN_AUDIENCE = "seamless-auth";
22
+ /**
23
+ * Fallback JWKS key id. Deploying on it is a misconfiguration, and adapters
24
+ * warn when it is in use.
25
+ */
26
+ export declare const DEV_JWKS_KID = "dev-main";
27
+ /**
28
+ * Subject for the token that authorizes an external-delivery request. It names
29
+ * the caller's role rather than a browser user, because no user is involved:
30
+ * the adapter is telling the API to hand back a payload instead of sending it.
31
+ */
32
+ export declare const EXTERNAL_DELIVERY_TOKEN_SUBJECT = "seamless-auth-external-delivery";
33
+ export interface ServiceIdentityOptions {
34
+ serviceSecret: string;
35
+ jwksKid?: string;
36
+ }
37
+ /**
38
+ * Mints the `Authorization` value for an external-delivery request.
39
+ */
40
+ export declare function buildExternalDeliveryAuthorization(opts: ServiceIdentityOptions): string;
41
+ //# sourceMappingURL=apiContract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContract.d.ts","sourceRoot":"","sources":["../src/apiContract.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH;;;GAGG;AACH,eAAO,MAAM,yBAAyB,kCAAkC,CAAC;AACzE,eAAO,MAAM,sBAAsB,aAAa,CAAC;AAEjD,mFAAmF;AACnF,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGnE,CAAC;AAEL;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,wBAAwB,CAAC;AAC1D,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,oCACT,CAAC;AAEpC,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,sBAAsB,GAC3B,MAAM,CAQR"}
@@ -0,0 +1,48 @@
1
+ import { createServiceToken } from "./createServiceToken.js";
2
+ /**
3
+ * Values the auth API defines. Changing one of these is a coordinated change
4
+ * with `seamless-auth-api`, so they live here rather than being written out at
5
+ * each call site, and every adapter reads the same value.
6
+ */
7
+ /**
8
+ * Asks the auth API to return a delivery payload instead of sending the message
9
+ * itself, so the adopter's own transports deliver it.
10
+ */
11
+ export const AUTH_DELIVERY_MODE_HEADER = "x-seamless-auth-delivery-mode";
12
+ export const EXTERNAL_DELIVERY_MODE = "external";
13
+ /** Headers that request external delivery, spreadable into an `authFetch` call. */
14
+ export const EXTERNAL_DELIVERY_HEADERS = Object.freeze({
15
+ [AUTH_DELIVERY_MODE_HEADER]: EXTERNAL_DELIVERY_MODE,
16
+ });
17
+ /**
18
+ * The auth API validates machine-to-machine service tokens against a fixed
19
+ * issuer and audience. These are not the adopter's configured audience, which
20
+ * applies to user tokens: a service token signed with the adopter's audience is
21
+ * rejected.
22
+ */
23
+ export const SERVICE_TOKEN_ISSUER = "seamless-portal-api";
24
+ export const SERVICE_TOKEN_AUDIENCE = "seamless-auth";
25
+ /**
26
+ * Fallback JWKS key id. Deploying on it is a misconfiguration, and adapters
27
+ * warn when it is in use.
28
+ */
29
+ export const DEV_JWKS_KID = "dev-main";
30
+ /**
31
+ * Subject for the token that authorizes an external-delivery request. It names
32
+ * the caller's role rather than a browser user, because no user is involved:
33
+ * the adapter is telling the API to hand back a payload instead of sending it.
34
+ */
35
+ export const EXTERNAL_DELIVERY_TOKEN_SUBJECT = "seamless-auth-external-delivery";
36
+ /**
37
+ * Mints the `Authorization` value for an external-delivery request.
38
+ */
39
+ export function buildExternalDeliveryAuthorization(opts) {
40
+ return `Bearer ${createServiceToken({
41
+ subject: EXTERNAL_DELIVERY_TOKEN_SUBJECT,
42
+ issuer: SERVICE_TOKEN_ISSUER,
43
+ audience: SERVICE_TOKEN_AUDIENCE,
44
+ serviceSecret: opts.serviceSecret,
45
+ keyId: opts.jwksKid || DEV_JWKS_KID,
46
+ })}`;
47
+ }
48
+ //# sourceMappingURL=apiContract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContract.js","sourceRoot":"","sources":["../src/apiContract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,+BAA+B,CAAC;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,UAAU,CAAC;AAEjD,mFAAmF;AACnF,MAAM,CAAC,MAAM,yBAAyB,GACpC,MAAM,CAAC,MAAM,CAAC;IACZ,CAAC,yBAAyB,CAAC,EAAE,sBAAsB;CACpD,CAAC,CAAC;AAEL;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,qBAAqB,CAAC;AAC1D,MAAM,CAAC,MAAM,sBAAsB,GAAG,eAAe,CAAC;AAEtD;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAC1C,iCAAiC,CAAC;AAOpC;;GAEG;AACH,MAAM,UAAU,kCAAkC,CAChD,IAA4B;IAE5B,OAAO,UAAU,kBAAkB,CAAC;QAClC,OAAO,EAAE,+BAA+B;QACxC,MAAM,EAAE,oBAAoB;QAC5B,QAAQ,EAAE,sBAAsB;QAChC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,KAAK,EAAE,IAAI,CAAC,OAAO,IAAI,YAAY;KACpC,CAAC,EAAE,CAAC;AACP,CAAC"}
@@ -0,0 +1,100 @@
1
+ import type { CookiePayload } from "./ensureCookies.js";
2
+ import type { ResultFailure } from "./result.js";
3
+ export type CookieSameSite = "lax" | "none" | "strict";
4
+ export interface CookieSecurityOptions {
5
+ cookieSecret: string;
6
+ cookieDomain?: string;
7
+ cookieSecure?: boolean;
8
+ cookieSameSite?: CookieSameSite;
9
+ }
10
+ /**
11
+ * Resolves the effective `SameSite` policy. Shared so the cookie attributes and
12
+ * any policy that keys off `SameSite=None` cannot drift. Browsers reject
13
+ * `SameSite=None` without `Secure`, so the default tracks `secure`.
14
+ */
15
+ export declare function resolveCookieSameSite(opts: Pick<CookieSecurityOptions, "cookieSecure" | "cookieSameSite">): CookieSameSite;
16
+ export interface SetCookieCommand {
17
+ name: string;
18
+ /** Already signed. Adapters emit it as-is. */
19
+ value: string;
20
+ domain?: string;
21
+ maxAgeSeconds: number;
22
+ /**
23
+ * The same lifetime as `maxAgeSeconds`, as an absolute time.
24
+ *
25
+ * Both are specified so every adapter emits the same header. `Max-Age` wins
26
+ * wherever it is understood; `Expires` is the fallback for clients that do
27
+ * not, which would otherwise treat the cookie as a session cookie. Leaving
28
+ * this to the adapter is how two adapters end up issuing different cookies for
29
+ * the same session.
30
+ */
31
+ expires: Date;
32
+ httpOnly: boolean;
33
+ secure: boolean;
34
+ sameSite: CookieSameSite;
35
+ path: string;
36
+ }
37
+ export interface ClearCookieCommand {
38
+ name: string;
39
+ domain?: string;
40
+ /**
41
+ * The epoch, which is what tells the browser to drop the cookie. Specified
42
+ * here for the same reason as on the set path: so every adapter emits the
43
+ * same header rather than each picking its own expression of "delete this".
44
+ */
45
+ expires: Date;
46
+ secure: boolean;
47
+ sameSite: CookieSameSite;
48
+ path: string;
49
+ }
50
+ /**
51
+ * The three things an adapter has to be able to do with its framework's
52
+ * response. Everything else about turning a handler result into a response,
53
+ * including cookie format and attribute policy, is decided here so adapters do
54
+ * not each reimplement it.
55
+ */
56
+ export interface ResponseAdapter {
57
+ setCookie(command: SetCookieCommand): void;
58
+ clearCookie(command: ClearCookieCommand): void;
59
+ /** `body` is `undefined` when the response carries none. */
60
+ send(status: number, body: unknown): void;
61
+ }
62
+ export interface SessionCookie {
63
+ name: string;
64
+ value: CookiePayload;
65
+ ttl: number;
66
+ domain?: string;
67
+ }
68
+ export interface AppliableResult extends ResultFailure {
69
+ status: number;
70
+ body?: unknown;
71
+ setCookies?: SessionCookie[];
72
+ clearCookies?: string[];
73
+ }
74
+ /**
75
+ * Signs a session cookie payload. The cookie format is core's, not the
76
+ * adapter's: an adapter that signed differently would mint sessions this
77
+ * package cannot read back.
78
+ */
79
+ export declare function signSessionCookie(payload: CookiePayload, secret: string, ttlSeconds: number): string;
80
+ /**
81
+ * Writes a result's cookie instructions, without touching the body.
82
+ *
83
+ * Separate from {@link applyResult} for middleware, which has to apply cookies
84
+ * on a request that then continues rather than one that is being answered.
85
+ *
86
+ * Clears run before sets, because a result that does both is replacing a
87
+ * session rather than ending one.
88
+ */
89
+ export declare function applyCookies(result: Pick<AppliableResult, "setCookies" | "clearCookies">, adapter: Pick<ResponseAdapter, "setCookie" | "clearCookie">, opts: CookieSecurityOptions): void;
90
+ /**
91
+ * Applies a handler result to a response.
92
+ *
93
+ * Cookies are written before the body.
94
+ *
95
+ * A failure carrying `errorBody` is the auth API's own body and goes out
96
+ * untouched; callers read fields off it. A failure carrying `errorCode` is this
97
+ * package's own and is rendered as `{ error, details }`.
98
+ */
99
+ export declare function applyResult(result: AppliableResult, adapter: ResponseAdapter, opts: CookieSecurityOptions): void;
100
+ //# sourceMappingURL=applyResult.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applyResult.d.ts","sourceRoot":"","sources":["../src/applyResult.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEvD,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,CAAC,qBAAqB,EAAE,cAAc,GAAG,gBAAgB,CAAC,GACnE,cAAc,CAGhB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;;;;OAQG;IACH,OAAO,EAAE,IAAI,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAKD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC3C,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC/C,4DAA4D;IAC5D,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,MAAM,CAKR;AAUD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,YAAY,GAAG,cAAc,CAAC,EAC5D,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,aAAa,CAAC,EAC3D,IAAI,EAAE,qBAAqB,GAC1B,IAAI,CAoCN;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,qBAAqB,GAC1B,IAAI,CAmBN"}
@@ -0,0 +1,95 @@
1
+ import jwt from "jsonwebtoken";
2
+ /**
3
+ * Resolves the effective `SameSite` policy. Shared so the cookie attributes and
4
+ * any policy that keys off `SameSite=None` cannot drift. Browsers reject
5
+ * `SameSite=None` without `Secure`, so the default tracks `secure`.
6
+ */
7
+ export function resolveCookieSameSite(opts) {
8
+ const secure = opts.cookieSecure ?? true;
9
+ return opts.cookieSameSite ?? (secure ? "none" : "lax");
10
+ }
11
+ /** Any time in the past drops the cookie; the epoch is the conventional one. */
12
+ const COOKIE_EPOCH = new Date(0);
13
+ /**
14
+ * Signs a session cookie payload. The cookie format is core's, not the
15
+ * adapter's: an adapter that signed differently would mint sessions this
16
+ * package cannot read back.
17
+ */
18
+ export function signSessionCookie(payload, secret, ttlSeconds) {
19
+ return jwt.sign(payload, secret, {
20
+ algorithm: "HS256",
21
+ expiresIn: `${ttlSeconds}s`,
22
+ });
23
+ }
24
+ function requireSecret(opts) {
25
+ if (!opts.cookieSecret) {
26
+ throw new Error("Missing cookieSecret");
27
+ }
28
+ return opts.cookieSecret;
29
+ }
30
+ /**
31
+ * Writes a result's cookie instructions, without touching the body.
32
+ *
33
+ * Separate from {@link applyResult} for middleware, which has to apply cookies
34
+ * on a request that then continues rather than one that is being answered.
35
+ *
36
+ * Clears run before sets, because a result that does both is replacing a
37
+ * session rather than ending one.
38
+ */
39
+ export function applyCookies(result, adapter, opts) {
40
+ const secure = opts.cookieSecure ?? true;
41
+ const sameSite = resolveCookieSameSite(opts);
42
+ if (result.clearCookies?.length) {
43
+ for (const name of result.clearCookies) {
44
+ adapter.clearCookie({
45
+ name,
46
+ domain: opts.cookieDomain,
47
+ expires: COOKIE_EPOCH,
48
+ secure,
49
+ sameSite,
50
+ path: "/",
51
+ });
52
+ }
53
+ }
54
+ if (result.setCookies?.length) {
55
+ const secret = requireSecret(opts);
56
+ const now = Date.now();
57
+ for (const cookie of result.setCookies) {
58
+ adapter.setCookie({
59
+ name: cookie.name,
60
+ value: signSessionCookie(cookie.value, secret, cookie.ttl),
61
+ domain: cookie.domain,
62
+ maxAgeSeconds: cookie.ttl,
63
+ expires: new Date(now + cookie.ttl * 1000),
64
+ httpOnly: true,
65
+ secure,
66
+ sameSite,
67
+ path: "/",
68
+ });
69
+ }
70
+ }
71
+ }
72
+ /**
73
+ * Applies a handler result to a response.
74
+ *
75
+ * Cookies are written before the body.
76
+ *
77
+ * A failure carrying `errorBody` is the auth API's own body and goes out
78
+ * untouched; callers read fields off it. A failure carrying `errorCode` is this
79
+ * package's own and is rendered as `{ error, details }`.
80
+ */
81
+ export function applyResult(result, adapter, opts) {
82
+ applyCookies(result, adapter, opts);
83
+ if (result.errorBody !== undefined) {
84
+ adapter.send(result.status, result.errorBody);
85
+ return;
86
+ }
87
+ if (result.errorCode !== undefined) {
88
+ adapter.send(result.status, result.details === undefined
89
+ ? { error: result.errorCode }
90
+ : { error: result.errorCode, details: result.details });
91
+ return;
92
+ }
93
+ adapter.send(result.status, result.body);
94
+ }
95
+ //# sourceMappingURL=applyResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applyResult.js","sourceRoot":"","sources":["../src/applyResult.ts"],"names":[],"mappings":"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"}
@@ -1,23 +1,17 @@
1
- export type MessagingChannel = "email" | "sms";
2
- export interface DeliveryResult {
3
- accepted: boolean;
4
- provider: string;
5
- channel: MessagingChannel;
6
- messageId?: string;
7
- raw?: unknown;
8
- }
9
- export interface EmailMessage {
10
- to: string;
11
- from?: string;
12
- subject: string;
13
- text: string;
14
- html?: string;
15
- }
16
- export interface SmsMessage {
17
- to: string;
18
- from?: string;
19
- body: string;
20
- }
1
+ /**
2
+ * The messaging contract.
3
+ *
4
+ * The wire shapes belong to `@seamless-auth/types`, so they are re-exported rather
5
+ * than declared again: the auth API sends the delivery instruction and this
6
+ * package consumes it, and two definitions of that could drift. The re-export is
7
+ * type-only, so it is erased at compile time and neither zod nor the schema
8
+ * barrel enters the runtime module graph.
9
+ *
10
+ * What stays here is what is genuinely this package's: the transport interfaces,
11
+ * which carry provider implementations, and the adopter-facing configuration.
12
+ */
13
+ export type { AuthDeliveryInstruction, DeliveryResult, EmailMessage, MessagingChannel, SendMagicLinkEmailInput, SendOtpEmailInput, SendOtpSmsInput, SmsMessage, } from "@seamless-auth/types";
14
+ import type { DeliveryResult, EmailMessage, SendMagicLinkEmailInput, SendOtpEmailInput, SendOtpSmsInput, SmsMessage } from "@seamless-auth/types";
21
15
  export interface EmailTransport {
22
16
  readonly name: string;
23
17
  send(message: EmailMessage): Promise<DeliveryResult>;
@@ -26,24 +20,6 @@ export interface SmsTransport {
26
20
  readonly name: string;
27
21
  send(message: SmsMessage): Promise<DeliveryResult>;
28
22
  }
29
- export interface SendOtpEmailInput {
30
- to: string;
31
- token: string;
32
- from?: string;
33
- subject?: string;
34
- }
35
- export interface SendOtpSmsInput {
36
- to: string;
37
- token: string | number;
38
- from?: string;
39
- }
40
- export interface SendMagicLinkEmailInput {
41
- to: string;
42
- magicLinkUrl: string;
43
- token?: string;
44
- from?: string;
45
- subject?: string;
46
- }
47
23
  export interface AuthMessageOverrideContext {
48
24
  appName?: string;
49
25
  }
@@ -68,18 +44,4 @@ export interface SeamlessAuthMessagingOptions {
68
44
  smsFrom?: string;
69
45
  };
70
46
  }
71
- export type AuthDeliveryInstruction = {
72
- kind: "otp_email";
73
- to: string;
74
- token: string;
75
- } | {
76
- kind: "otp_sms";
77
- to: string;
78
- token: string | number;
79
- } | {
80
- kind: "magic_link_email";
81
- to: string;
82
- token?: string;
83
- magicLinkUrl: string;
84
- };
85
47
  //# sourceMappingURL=authMessaging.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"authMessaging.d.ts","sourceRoot":"","sources":["../src/authMessaging.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authMessaging.d.ts","sourceRoot":"","sources":["../src/authMessaging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,UAAU,GACX,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACX,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,0BAA0B,KAChC,YAAY,CAAC;IAClB,MAAM,CAAC,EAAE,CACP,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,0BAA0B,KAChC,UAAU,CAAC;IAChB,cAAc,CAAC,EAAE,CACf,KAAK,EAAE,uBAAuB,EAC9B,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,0BAA0B,KAChC,YAAY,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAChE,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC5D,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC7E;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC1C,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,QAAQ,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH"}
@@ -0,0 +1,15 @@
1
+ import type { AuthDeliveryInstruction, SeamlessAuthMessagingOptions } from "./authMessaging.js";
2
+ export declare function deliverAuthMessage(messaging: SeamlessAuthMessagingOptions | undefined, delivery: AuthDeliveryInstruction | undefined): Promise<void>;
3
+ export declare function stripDelivery<T extends {
4
+ delivery?: unknown;
5
+ }>(body: T): Omit<T, "delivery">;
6
+ /**
7
+ * Applies external delivery to an upstream response body and returns the body to send on.
8
+ *
9
+ * When messaging is configured the adapter asks the auth API for a delivery payload instead of
10
+ * having the API send the message itself. A missing payload means nobody sent anything, so it is
11
+ * surfaced here: the four endpoints that route through this helper always include `delivery` when
12
+ * the API accepts the request as externally delivered.
13
+ */
14
+ export declare function applyExternalDelivery(messaging: SeamlessAuthMessagingOptions | undefined, body: unknown): Promise<unknown>;
15
+ //# sourceMappingURL=deliverAuthMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deliverAuthMessage.d.ts","sourceRoot":"","sources":["../src/deliverAuthMessage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EAEvB,4BAA4B,EAE7B,MAAM,oBAAoB,CAAC;AA0G5B,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,4BAA4B,GAAG,SAAS,EACnD,QAAQ,EAAE,uBAAuB,GAAG,SAAS,GAC5C,OAAO,CAAC,IAAI,CAAC,CA0Df;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,EAC5D,IAAI,EAAE,CAAC,GACN,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAGrB;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,4BAA4B,GAAG,SAAS,EACnD,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,OAAO,CAAC,CAgBlB"}
@@ -0,0 +1,123 @@
1
+ import { getSeamlessLogger } from "./logger.js";
2
+ function applyEmailOverride(override, input, defaults, appName) {
3
+ return override ? override(input, defaults, { appName }) : defaults;
4
+ }
5
+ function applySmsOverride(override, input, defaults, appName) {
6
+ return override ? override(input, defaults, { appName }) : defaults;
7
+ }
8
+ function buildOtpEmailMessage(input, messaging) {
9
+ const appName = messaging.defaults?.appName ?? "Seamless Auth";
10
+ return applyEmailOverride(messaging.overrides?.otpEmail, {
11
+ to: input.to,
12
+ token: input.token,
13
+ from: messaging.defaults?.emailFrom,
14
+ subject: `${appName} - Verify your email`,
15
+ }, {
16
+ to: input.to,
17
+ from: messaging.defaults?.emailFrom,
18
+ subject: `${appName} - Verify your email`,
19
+ text: `Verify your account with ${appName}.\n\nYour verification code is: ${input.token}\n\nIf you did not request this code, you can safely ignore this message.`,
20
+ html: `<div><h1>Verify your account with ${appName}</h1><p>Please use the verification code below:</p><p><strong>${input.token}</strong></p><p>If you did not request this code, you can safely ignore this message.</p></div>`,
21
+ }, appName);
22
+ }
23
+ function buildOtpSmsMessage(input, messaging) {
24
+ const appName = messaging.defaults?.appName ?? "Seamless Auth";
25
+ return applySmsOverride(messaging.overrides?.otpSms, {
26
+ to: input.to,
27
+ token: input.token,
28
+ from: messaging.defaults?.smsFrom,
29
+ }, {
30
+ to: input.to,
31
+ from: messaging.defaults?.smsFrom,
32
+ body: `Your ${appName} verification code is: ${input.token}. No one will ever ask you for this code. Do not share it.`,
33
+ }, appName);
34
+ }
35
+ function buildMagicLinkMessage(input, messaging) {
36
+ const appName = messaging.defaults?.appName ?? "Seamless Auth";
37
+ return applyEmailOverride(messaging.overrides?.magicLinkEmail, {
38
+ to: input.to,
39
+ magicLinkUrl: input.magicLinkUrl,
40
+ token: input.token,
41
+ from: messaging.defaults?.emailFrom,
42
+ subject: `${appName} - Your sign-in link`,
43
+ }, {
44
+ to: input.to,
45
+ from: messaging.defaults?.emailFrom,
46
+ subject: `${appName} - Your sign-in link`,
47
+ text: `Use the link below to sign in to ${appName}:\n\n${input.magicLinkUrl}\n\nIf you did not request this email, you can safely ignore it.`,
48
+ html: `<div><h1>Sign in to ${appName}</h1><p>Use the link below to complete sign-in:</p><p><a href="${input.magicLinkUrl}">${input.magicLinkUrl}</a></p><p>If you did not request this email, you can safely ignore it.</p></div>`,
49
+ }, appName);
50
+ }
51
+ export async function deliverAuthMessage(messaging, delivery) {
52
+ if (!messaging || !delivery) {
53
+ return;
54
+ }
55
+ switch (delivery.kind) {
56
+ case "otp_email":
57
+ if (messaging.handlers?.sendOtpEmail) {
58
+ await messaging.handlers.sendOtpEmail({
59
+ to: delivery.to,
60
+ token: delivery.token,
61
+ from: messaging.defaults?.emailFrom,
62
+ });
63
+ return;
64
+ }
65
+ if (!messaging.email) {
66
+ throw new Error("Missing email transport for OTP email delivery.");
67
+ }
68
+ await messaging.email.send(buildOtpEmailMessage(delivery, messaging));
69
+ return;
70
+ case "otp_sms":
71
+ if (messaging.handlers?.sendOtpSms) {
72
+ await messaging.handlers.sendOtpSms({
73
+ to: delivery.to,
74
+ token: delivery.token,
75
+ from: messaging.defaults?.smsFrom,
76
+ });
77
+ return;
78
+ }
79
+ if (!messaging.sms) {
80
+ throw new Error("Missing SMS transport for OTP SMS delivery.");
81
+ }
82
+ await messaging.sms.send(buildOtpSmsMessage(delivery, messaging));
83
+ return;
84
+ case "magic_link_email":
85
+ if (messaging.handlers?.sendMagicLinkEmail) {
86
+ await messaging.handlers.sendMagicLinkEmail({
87
+ to: delivery.to,
88
+ token: delivery.token,
89
+ magicLinkUrl: delivery.magicLinkUrl,
90
+ from: messaging.defaults?.emailFrom,
91
+ });
92
+ return;
93
+ }
94
+ if (!messaging.email) {
95
+ throw new Error("Missing email transport for magic link delivery.");
96
+ }
97
+ await messaging.email.send(buildMagicLinkMessage(delivery, messaging));
98
+ return;
99
+ }
100
+ }
101
+ export function stripDelivery(body) {
102
+ const { delivery: _delivery, ...rest } = body;
103
+ return rest;
104
+ }
105
+ /**
106
+ * Applies external delivery to an upstream response body and returns the body to send on.
107
+ *
108
+ * When messaging is configured the adapter asks the auth API for a delivery payload instead of
109
+ * having the API send the message itself. A missing payload means nobody sent anything, so it is
110
+ * surfaced here: the four endpoints that route through this helper always include `delivery` when
111
+ * the API accepts the request as externally delivered.
112
+ */
113
+ export async function applyExternalDelivery(messaging, body) {
114
+ if (body && typeof body === "object" && "delivery" in body) {
115
+ await deliverAuthMessage(messaging, body.delivery);
116
+ return stripDelivery(body);
117
+ }
118
+ if (messaging) {
119
+ getSeamlessLogger().warn("[SeamlessAuth] External delivery was requested but the auth API returned no delivery payload, so no message was sent. Verify that serviceSecret matches the auth API's API_SERVICE_TOKEN.");
120
+ }
121
+ return body;
122
+ }
123
+ //# sourceMappingURL=deliverAuthMessage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deliverAuthMessage.js","sourceRoot":"","sources":["../src/deliverAuthMessage.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import type { ResultFailure } from "./result.js";
1
2
  export interface EnsureCookiesInput {
2
3
  path: string;
3
4
  cookies: Record<string, string | undefined>;
@@ -18,10 +19,9 @@ export interface CookieInstruction {
18
19
  ttl: number;
19
20
  domain?: string;
20
21
  }
21
- export interface EnsureCookiesResult {
22
+ export interface EnsureCookiesResult extends ResultFailure {
22
23
  type: "ok" | "error";
23
24
  status?: number;
24
- error?: string;
25
25
  user?: {
26
26
  sub: string;
27
27
  sessionId?: string;