@better-auth/electron 1.7.0-beta.3 → 1.7.0-beta.5
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/dist/{client-D6xRwPM0.d.mts → client-D5QKMJbp.d.mts} +13 -17
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +14 -12
- package/dist/index.d.mts +2 -8
- package/dist/index.mjs +6 -25
- package/dist/preload.d.mts +743 -116
- package/dist/preload.mjs +1 -1
- package/dist/proxy.d.mts +1 -1
- package/dist/proxy.mjs +1 -1
- package/dist/storage.d.mts +1 -1
- package/dist/{version-CLqkeI3u.mjs → version-DzWb5tB_.mjs} +1 -1
- package/package.json +8 -8
|
@@ -35,13 +35,6 @@ interface ElectronOptions extends ElectronSharedOptions {
|
|
|
35
35
|
* @default "better-auth"
|
|
36
36
|
*/
|
|
37
37
|
cookiePrefix?: string | undefined;
|
|
38
|
-
/**
|
|
39
|
-
* Override the origin for Electron API routes.
|
|
40
|
-
* Enable this if you're facing cors origin issues with Electron API routes.
|
|
41
|
-
*
|
|
42
|
-
* @default false
|
|
43
|
-
*/
|
|
44
|
-
disableOriginOverride?: boolean | undefined;
|
|
45
38
|
}
|
|
46
39
|
//#endregion
|
|
47
40
|
//#region src/preload.d.ts
|
|
@@ -248,6 +241,7 @@ declare const requestAuthOptionsSchema: z.ZodObject<{
|
|
|
248
241
|
disableRedirect: z.ZodOptional<z.ZodBoolean>;
|
|
249
242
|
scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
250
243
|
requestSignUp: z.ZodOptional<z.ZodBoolean>;
|
|
244
|
+
additionalParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
251
245
|
additionalData: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
252
246
|
}, z.core.$strip>;
|
|
253
247
|
type ElectronRequestAuthOptions = z.infer<typeof requestAuthOptionsSchema>;
|
|
@@ -323,11 +317,6 @@ declare const electronClient: <O extends ElectronClientOptions>(options: O) => {
|
|
|
323
317
|
mode?: RequestMode | undefined;
|
|
324
318
|
cache?: RequestCache | undefined;
|
|
325
319
|
credentials?: RequestCredentials | undefined;
|
|
326
|
-
headers?: (HeadersInit & (HeadersInit | {
|
|
327
|
-
accept: "application/json" | "text/plain" | "application/octet-stream";
|
|
328
|
-
"content-type": "application/json" | "text/plain" | "application/x-www-form-urlencoded" | "multipart/form-data" | "application/octet-stream";
|
|
329
|
-
authorization: "Bearer" | "Basic";
|
|
330
|
-
})) | undefined;
|
|
331
320
|
integrity?: string | undefined;
|
|
332
321
|
keepalive?: boolean | undefined;
|
|
333
322
|
method?: string | undefined;
|
|
@@ -361,6 +350,12 @@ declare const electronClient: <O extends ElectronClientOptions>(options: O) => {
|
|
|
361
350
|
prefix: string | (() => string | undefined) | undefined;
|
|
362
351
|
value: string | (() => string | undefined) | undefined;
|
|
363
352
|
}) | undefined;
|
|
353
|
+
headers?: {} | {
|
|
354
|
+
[x: string]: string | undefined;
|
|
355
|
+
accept?: ((string & {}) | "application/json" | "text/plain" | "application/octet-stream") | undefined;
|
|
356
|
+
"content-type"?: ((string & {}) | "application/x-www-form-urlencoded" | "application/json" | "text/plain" | "multipart/form-data" | "application/octet-stream") | undefined;
|
|
357
|
+
authorization?: ((string & {}) | `Bearer ${string}` | `Basic ${string}`) | undefined;
|
|
358
|
+
} | undefined;
|
|
364
359
|
body?: any;
|
|
365
360
|
query?: any;
|
|
366
361
|
params?: any;
|
|
@@ -378,11 +373,6 @@ declare const electronClient: <O extends ElectronClientOptions>(options: O) => {
|
|
|
378
373
|
mode?: RequestMode | undefined;
|
|
379
374
|
cache?: RequestCache | undefined;
|
|
380
375
|
credentials?: RequestCredentials | undefined;
|
|
381
|
-
headers?: (HeadersInit & (HeadersInit | {
|
|
382
|
-
accept: "application/json" | "text/plain" | "application/octet-stream";
|
|
383
|
-
"content-type": "application/json" | "text/plain" | "application/x-www-form-urlencoded" | "multipart/form-data" | "application/octet-stream";
|
|
384
|
-
authorization: "Bearer" | "Basic";
|
|
385
|
-
})) | undefined;
|
|
386
376
|
integrity?: string | undefined;
|
|
387
377
|
keepalive?: boolean | undefined;
|
|
388
378
|
method?: string | undefined;
|
|
@@ -416,6 +406,12 @@ declare const electronClient: <O extends ElectronClientOptions>(options: O) => {
|
|
|
416
406
|
prefix: string | (() => string | undefined) | undefined;
|
|
417
407
|
value: string | (() => string | undefined) | undefined;
|
|
418
408
|
}) | undefined;
|
|
409
|
+
headers?: {} | {
|
|
410
|
+
[x: string]: string | undefined;
|
|
411
|
+
accept?: ((string & {}) | "application/json" | "text/plain" | "application/octet-stream") | undefined;
|
|
412
|
+
"content-type"?: ((string & {}) | "application/x-www-form-urlencoded" | "application/json" | "text/plain" | "multipart/form-data" | "application/octet-stream") | undefined;
|
|
413
|
+
authorization?: ((string & {}) | `Bearer ${string}` | `Basic ${string}`) | undefined;
|
|
414
|
+
} | undefined;
|
|
419
415
|
body?: any;
|
|
420
416
|
query?: any;
|
|
421
417
|
params?: any;
|
package/dist/client.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as setupRenderer, a as authenticate, c as ElectronClientOptions, d as Storage, f as FetchUserImageResult, g as SetupRendererConfig, h as ExposedBridges, i as ElectronRequestAuthOptions, l as ElectronProxyClientOptions, m as normalizeUserOutput, n as handleDeepLink, o as kElectron, p as fetchUserImage, r as ElectronAuthenticateOptions, s as requestAuth, t as electronClient, u as ElectronSharedClientOptions, y as ElectronSharedOptions } from "./client-
|
|
1
|
+
import { _ as setupRenderer, a as authenticate, c as ElectronClientOptions, d as Storage, f as FetchUserImageResult, g as SetupRendererConfig, h as ExposedBridges, i as ElectronRequestAuthOptions, l as ElectronProxyClientOptions, m as normalizeUserOutput, n as handleDeepLink, o as kElectron, p as fetchUserImage, r as ElectronAuthenticateOptions, s as requestAuth, t as electronClient, u as ElectronSharedClientOptions, y as ElectronSharedOptions } from "./client-D5QKMJbp.mjs";
|
|
2
2
|
export { ElectronAuthenticateOptions, ElectronClientOptions, ElectronProxyClientOptions, ElectronRequestAuthOptions, ElectronSharedClientOptions, ElectronSharedOptions, ExposedBridges, FetchUserImageResult, SetupRendererConfig, Storage, authenticate, electronClient, fetchUserImage, handleDeepLink, kElectron, normalizeUserOutput, requestAuth, setupRenderer };
|
package/dist/client.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { t as PACKAGE_VERSION } from "./version-
|
|
1
|
+
import { t as PACKAGE_VERSION } from "./version-DzWb5tB_.mjs";
|
|
2
2
|
import { n as isProcessType, r as parseProtocolScheme, t as getChannelPrefixWithDelimiter } from "./utils-DxDKRT6e.mjs";
|
|
3
3
|
import { BetterAuthError } from "@better-auth/core/error";
|
|
4
4
|
import { base64, base64Url } from "@better-auth/utils/base64";
|
|
5
5
|
import { APIError as APIError$1, getBaseURL, isDevelopment, isTest, safeJSONParse } from "better-auth";
|
|
6
6
|
import { generateRandomString } from "better-auth/crypto";
|
|
7
7
|
import * as z from "zod";
|
|
8
|
-
import { Buffer } from "node:buffer";
|
|
9
|
-
import { createHash } from "@better-auth/utils/hash";
|
|
10
8
|
import { signInSocial } from "better-auth/api";
|
|
11
|
-
import { parseSetCookieHeader } from "better-auth/cookies";
|
|
9
|
+
import { cookieNameRegex, parseSetCookieHeader } from "better-auth/cookies";
|
|
10
|
+
import { generateCodeChallenge } from "better-auth/oauth2";
|
|
11
|
+
import { Buffer } from "node:buffer";
|
|
12
12
|
import electron, { shell } from "electron";
|
|
13
13
|
import { isDevelopment as isDevelopment$1 } from "@better-auth/core/env";
|
|
14
14
|
import { isPublicRoutableHost } from "@better-auth/core/utils/host";
|
|
@@ -150,8 +150,8 @@ async function requestAuth(clientOptions, options, cfg) {
|
|
|
150
150
|
if (!isProcessType("browser")) throw new BetterAuthError("`requestAuth` can only be called in the main process");
|
|
151
151
|
const { randomBytes } = await import("node:crypto");
|
|
152
152
|
const state = generateRandomString(16, "A-Z", "a-z", "0-9");
|
|
153
|
-
const codeVerifier = base64Url.encode(randomBytes(32));
|
|
154
|
-
const codeChallenge =
|
|
153
|
+
const codeVerifier = base64Url.encode(randomBytes(32), { padding: false });
|
|
154
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
155
155
|
(globalThis[kElectron] ??= /* @__PURE__ */ new Map()).set(state, codeVerifier);
|
|
156
156
|
let url = null;
|
|
157
157
|
if (cfg?.provider) {
|
|
@@ -168,7 +168,6 @@ async function requestAuth(clientOptions, options, cfg) {
|
|
|
168
168
|
} else url = new URL(options.signInURL);
|
|
169
169
|
url.searchParams.set("client_id", options.clientID || "electron");
|
|
170
170
|
url.searchParams.set("code_challenge", codeChallenge);
|
|
171
|
-
url.searchParams.set("code_challenge_method", "S256");
|
|
172
171
|
url.searchParams.set("state", state);
|
|
173
172
|
await shell.openExternal(url.toString(), { activate: true });
|
|
174
173
|
}
|
|
@@ -474,10 +473,13 @@ function getCookie(cookie) {
|
|
|
474
473
|
try {
|
|
475
474
|
parsed = JSON.parse(cookie);
|
|
476
475
|
} catch (_e) {}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
476
|
+
const pairs = [];
|
|
477
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
478
|
+
if (value.expires && new Date(value.expires) < /* @__PURE__ */ new Date()) continue;
|
|
479
|
+
if (!cookieNameRegex.test(key)) continue;
|
|
480
|
+
pairs.push(`${key}=${encodeURIComponent(value.value)}`);
|
|
481
|
+
}
|
|
482
|
+
return pairs.join("; ");
|
|
481
483
|
}
|
|
482
484
|
/**
|
|
483
485
|
* Compare if session cookies have actually changed by comparing their values.
|
|
@@ -589,10 +591,10 @@ const electronClient = (options) => {
|
|
|
589
591
|
options ||= {};
|
|
590
592
|
options.credentials = "omit";
|
|
591
593
|
options.headers = {
|
|
594
|
+
origin: `${scheme}:/`,
|
|
592
595
|
...options.headers,
|
|
593
596
|
cookie,
|
|
594
597
|
"user-agent": app.userAgentFallback,
|
|
595
|
-
"electron-origin": `${scheme}:/`,
|
|
596
598
|
"x-skip-oauth-proxy": "true"
|
|
597
599
|
};
|
|
598
600
|
if (url.endsWith("/sign-out")) {
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { f as FetchUserImageResult, m as normalizeUserOutput, p as fetchUserImage, v as ElectronOptions, y as ElectronSharedOptions } from "./client-
|
|
1
|
+
import { f as FetchUserImageResult, m as normalizeUserOutput, p as fetchUserImage, v as ElectronOptions, y as ElectronSharedOptions } from "./client-D5QKMJbp.mjs";
|
|
2
2
|
import * as better_auth0 from "better-auth";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import * as _better_auth_core0 from "@better-auth/core";
|
|
@@ -16,9 +16,6 @@ declare module "@better-auth/core" {
|
|
|
16
16
|
declare const electron: (options?: ElectronOptions | undefined) => {
|
|
17
17
|
id: "electron";
|
|
18
18
|
version: string;
|
|
19
|
-
onRequest(request: Request, _ctx: better_auth0.AuthContext): Promise<{
|
|
20
|
-
request: Request;
|
|
21
|
-
} | undefined>;
|
|
22
19
|
hooks: {
|
|
23
20
|
after: ({
|
|
24
21
|
matcher: (ctx: HookEndpointContext) => boolean;
|
|
@@ -102,7 +99,7 @@ declare const electron: (options?: ElectronOptions | undefined) => {
|
|
|
102
99
|
image?: string | null | undefined;
|
|
103
100
|
} & Record<string, any>;
|
|
104
101
|
} | null) => void;
|
|
105
|
-
socialProviders: better_auth0.
|
|
102
|
+
socialProviders: better_auth0.UpstreamProvider[];
|
|
106
103
|
authCookies: better_auth0.BetterAuthCookies;
|
|
107
104
|
logger: ReturnType<typeof better_auth0.createLogger>;
|
|
108
105
|
rateLimit: {
|
|
@@ -205,7 +202,6 @@ declare const electron: (options?: ElectronOptions | undefined) => {
|
|
|
205
202
|
provider: z.ZodString;
|
|
206
203
|
state: z.ZodString;
|
|
207
204
|
code_challenge: z.ZodString;
|
|
208
|
-
code_challenge_method: z.ZodOptional<z.ZodString>;
|
|
209
205
|
}, z.core.$strip>;
|
|
210
206
|
metadata: {
|
|
211
207
|
scope: "http";
|
|
@@ -255,7 +251,6 @@ declare const electron: (options?: ElectronOptions | undefined) => {
|
|
|
255
251
|
client_id: z.ZodString;
|
|
256
252
|
state: z.ZodString;
|
|
257
253
|
code_challenge: z.ZodString;
|
|
258
|
-
code_challenge_method: z.ZodOptional<z.ZodString>;
|
|
259
254
|
}, z.core.$strip>;
|
|
260
255
|
body: z.ZodObject<{
|
|
261
256
|
callbackURL: z.ZodOptional<z.ZodString>;
|
|
@@ -325,7 +320,6 @@ declare const electron: (options?: ElectronOptions | undefined) => {
|
|
|
325
320
|
codeExpiresIn: number;
|
|
326
321
|
redirectCookieExpiresIn: number;
|
|
327
322
|
cookiePrefix: string;
|
|
328
|
-
disableOriginOverride?: boolean | undefined;
|
|
329
323
|
clientID: string;
|
|
330
324
|
};
|
|
331
325
|
$ERROR_CODES: {
|
package/dist/index.mjs
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import { t as PACKAGE_VERSION } from "./version-
|
|
1
|
+
import { t as PACKAGE_VERSION } from "./version-DzWb5tB_.mjs";
|
|
2
2
|
import { createAuthMiddleware } from "@better-auth/core/api";
|
|
3
3
|
import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
|
|
4
4
|
import { base64Url } from "@better-auth/utils/base64";
|
|
5
5
|
import { defineErrorCodes, safeJSONParse } from "better-auth";
|
|
6
6
|
import { generateRandomString } from "better-auth/crypto";
|
|
7
7
|
import * as z from "zod";
|
|
8
|
-
import { Buffer } from "node:buffer";
|
|
9
|
-
import { timingSafeEqual } from "node:crypto";
|
|
10
8
|
import { safeJSONParse as safeJSONParse$1 } from "@better-auth/core/utils/json";
|
|
11
|
-
import { createHash } from "@better-auth/utils/hash";
|
|
12
9
|
import { betterFetch } from "@better-fetch/fetch";
|
|
13
10
|
import { createAuthEndpoint, sessionMiddleware } from "better-auth/api";
|
|
14
11
|
import { setSessionCookie } from "better-auth/cookies";
|
|
15
12
|
import { parseUserOutput } from "better-auth/db";
|
|
13
|
+
import { generateCodeChallenge } from "better-auth/oauth2";
|
|
16
14
|
//#region src/error-codes.ts
|
|
17
15
|
const ELECTRON_ERROR_CODES = defineErrorCodes({
|
|
18
16
|
INVALID_CLIENT_ID: "Invalid client ID",
|
|
@@ -61,11 +59,7 @@ const electronToken = (_opts) => createAuthEndpoint("/electron/token", {
|
|
|
61
59
|
if (!tokenRecord) throw APIError.from("INTERNAL_SERVER_ERROR", ELECTRON_ERROR_CODES.INVALID_TOKEN);
|
|
62
60
|
if (tokenRecord.state !== ctx.body.state) throw APIError.from("BAD_REQUEST", ELECTRON_ERROR_CODES.STATE_MISMATCH);
|
|
63
61
|
if (!tokenRecord.codeChallenge) throw APIError.from("BAD_REQUEST", ELECTRON_ERROR_CODES.MISSING_CODE_CHALLENGE);
|
|
64
|
-
if (tokenRecord.
|
|
65
|
-
const codeChallenge = Buffer.from(base64Url.decode(tokenRecord.codeChallenge));
|
|
66
|
-
const codeVerifier = Buffer.from(await createHash("SHA-256").digest(ctx.body.code_verifier));
|
|
67
|
-
if (codeChallenge.length !== codeVerifier.length || !timingSafeEqual(codeChallenge, codeVerifier)) throw APIError.from("BAD_REQUEST", ELECTRON_ERROR_CODES.INVALID_CODE_VERIFIER);
|
|
68
|
-
} else if (tokenRecord.codeChallenge !== ctx.body.code_verifier) throw APIError.from("BAD_REQUEST", ELECTRON_ERROR_CODES.INVALID_CODE_VERIFIER);
|
|
62
|
+
if (await generateCodeChallenge(ctx.body.code_verifier) !== tokenRecord.codeChallenge) throw APIError.from("BAD_REQUEST", ELECTRON_ERROR_CODES.INVALID_CODE_VERIFIER);
|
|
69
63
|
await ctx.context.internalAdapter.deleteVerificationByIdentifier(`electron:${ctx.body.token}`);
|
|
70
64
|
const user = await ctx.context.internalAdapter.findUserById(tokenRecord.userId);
|
|
71
65
|
if (!user) throw APIError.from("INTERNAL_SERVER_ERROR", BASE_ERROR_CODES.USER_NOT_FOUND);
|
|
@@ -83,8 +77,7 @@ const electronToken = (_opts) => createAuthEndpoint("/electron/token", {
|
|
|
83
77
|
const electronInitOAuthProxyQuerySchema = z.object({
|
|
84
78
|
provider: z.string().nonempty(),
|
|
85
79
|
state: z.string(),
|
|
86
|
-
code_challenge: z.string()
|
|
87
|
-
code_challenge_method: z.string().optional()
|
|
80
|
+
code_challenge: z.string()
|
|
88
81
|
});
|
|
89
82
|
const electronInitOAuthProxy = (opts) => createAuthEndpoint("/electron/init-oauth-proxy", {
|
|
90
83
|
method: "GET",
|
|
@@ -122,7 +115,6 @@ const electronInitOAuthProxy = (opts) => createAuthEndpoint("/electron/init-oaut
|
|
|
122
115
|
const searchParams = new URLSearchParams();
|
|
123
116
|
searchParams.set("client_id", opts.clientID || "electron");
|
|
124
117
|
searchParams.set("code_challenge", ctx.query.code_challenge);
|
|
125
|
-
searchParams.set("code_challenge_method", ctx.query.code_challenge_method || "plain");
|
|
126
118
|
searchParams.set("state", ctx.query.state);
|
|
127
119
|
const res = await betterFetch(`/sign-in/social?${searchParams.toString()}`, {
|
|
128
120
|
baseURL: ctx.context.baseURL,
|
|
@@ -145,8 +137,7 @@ const electronInitOAuthProxy = (opts) => createAuthEndpoint("/electron/init-oaut
|
|
|
145
137
|
const electronTransferUserQuerySchema = z.object({
|
|
146
138
|
client_id: z.string(),
|
|
147
139
|
state: z.string(),
|
|
148
|
-
code_challenge: z.string()
|
|
149
|
-
code_challenge_method: z.string().optional()
|
|
140
|
+
code_challenge: z.string()
|
|
150
141
|
});
|
|
151
142
|
const electronTransferUserBodySchema = z.object({ callbackURL: z.string().optional() });
|
|
152
143
|
const electronTransferUser = (_opts, { handleTransfer }) => createAuthEndpoint("/electron/transfer-user", {
|
|
@@ -201,7 +192,7 @@ const electron = (options) => {
|
|
|
201
192
|
return !!(ctx.path?.startsWith("/sign-in") || ctx.path?.startsWith("/sign-up") || ctx.path?.startsWith("/callback") || ctx.path?.startsWith("/magic-link/verify") || ctx.path?.startsWith("/email-otp/verify-email") || ctx.path?.startsWith("/verify-email") || ctx.path?.startsWith("/one-tap/callback") || ctx.path?.startsWith("/passkey/verify-authentication") || ctx.path?.startsWith("/phone-number/verify"));
|
|
202
193
|
};
|
|
203
194
|
const handleTransfer = async (ctx, payload) => {
|
|
204
|
-
const { client_id, state, code_challenge
|
|
195
|
+
const { client_id, state, code_challenge } = payload;
|
|
205
196
|
const userId = ctx.context.session?.user.id || ctx.context.newSession?.user.id;
|
|
206
197
|
if (!userId || client_id !== opts.clientID) return null;
|
|
207
198
|
if (!state) throw APIError.from("BAD_REQUEST", ELECTRON_ERROR_CODES.MISSING_STATE);
|
|
@@ -215,7 +206,6 @@ const electron = (options) => {
|
|
|
215
206
|
value: JSON.stringify({
|
|
216
207
|
userId,
|
|
217
208
|
codeChallenge: code_challenge,
|
|
218
|
-
codeChallengeMethod: code_challenge_method.toLowerCase(),
|
|
219
209
|
state
|
|
220
210
|
}),
|
|
221
211
|
expiresAt
|
|
@@ -234,14 +224,6 @@ const electron = (options) => {
|
|
|
234
224
|
return {
|
|
235
225
|
id: "electron",
|
|
236
226
|
version: PACKAGE_VERSION,
|
|
237
|
-
async onRequest(request, _ctx) {
|
|
238
|
-
if (opts.disableOriginOverride || request.headers.get("origin")) return;
|
|
239
|
-
const electronOrigin = request.headers.get("electron-origin");
|
|
240
|
-
if (!electronOrigin) return;
|
|
241
|
-
const req = request.clone();
|
|
242
|
-
req.headers.set("origin", electronOrigin);
|
|
243
|
-
return { request: req };
|
|
244
|
-
},
|
|
245
227
|
hooks: { after: [{
|
|
246
228
|
matcher: (ctx) => !hookMatcher(ctx),
|
|
247
229
|
handler: createAuthMiddleware(async (ctx) => {
|
|
@@ -256,7 +238,6 @@ const electron = (options) => {
|
|
|
256
238
|
const querySchema = z.object({
|
|
257
239
|
client_id: z.string(),
|
|
258
240
|
code_challenge: z.string().nonempty(),
|
|
259
|
-
code_challenge_method: z.string().optional().default("plain"),
|
|
260
241
|
state: z.string().nonempty()
|
|
261
242
|
});
|
|
262
243
|
const cookie = ctx.context.createAuthCookie("transfer_token", { maxAge: opts.codeExpiresIn });
|