@draftlab/auth 0.0.1

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 (86) hide show
  1. package/dist/adapters/node.d.ts +18 -0
  2. package/dist/adapters/node.js +71 -0
  3. package/dist/allow-CixonwTW.d.ts +59 -0
  4. package/dist/allow-DX5cehSc.js +63 -0
  5. package/dist/allow.d.ts +2 -0
  6. package/dist/allow.js +4 -0
  7. package/dist/base-DRutbxgL.js +422 -0
  8. package/dist/client.d.ts +413 -0
  9. package/dist/client.js +209 -0
  10. package/dist/code-l_uvMR1j.d.ts +212 -0
  11. package/dist/core-8WTqfnb4.d.ts +129 -0
  12. package/dist/core-CncE5rPg.js +498 -0
  13. package/dist/core.d.ts +9 -0
  14. package/dist/core.js +14 -0
  15. package/dist/error-CWAdNAzm.d.ts +243 -0
  16. package/dist/error-DgAKK7b2.js +237 -0
  17. package/dist/error.d.ts +2 -0
  18. package/dist/error.js +3 -0
  19. package/dist/form-6XKM_cOk.js +61 -0
  20. package/dist/icon-Ci5uqGB_.js +192 -0
  21. package/dist/index.d.ts +9 -0
  22. package/dist/index.js +14 -0
  23. package/dist/keys-EEfxEGfO.js +140 -0
  24. package/dist/keys.d.ts +67 -0
  25. package/dist/keys.js +5 -0
  26. package/dist/oauth2-B7-6Z7Lc.js +155 -0
  27. package/dist/oauth2-DtKwtl8p.d.ts +176 -0
  28. package/dist/password-Cm0dRMwa.d.ts +385 -0
  29. package/dist/pkce-276Za_rZ.js +162 -0
  30. package/dist/pkce.d.ts +72 -0
  31. package/dist/pkce.js +3 -0
  32. package/dist/provider/code.d.ts +4 -0
  33. package/dist/provider/code.js +145 -0
  34. package/dist/provider/facebook.d.ts +137 -0
  35. package/dist/provider/facebook.js +85 -0
  36. package/dist/provider/github.d.ts +141 -0
  37. package/dist/provider/github.js +88 -0
  38. package/dist/provider/google.d.ts +113 -0
  39. package/dist/provider/google.js +62 -0
  40. package/dist/provider/oauth2.d.ts +4 -0
  41. package/dist/provider/oauth2.js +7 -0
  42. package/dist/provider/password.d.ts +4 -0
  43. package/dist/provider/password.js +366 -0
  44. package/dist/provider/provider.d.ts +3 -0
  45. package/dist/provider/provider.js +44 -0
  46. package/dist/provider-CwWMG-1l.d.ts +227 -0
  47. package/dist/random-SXMYlaVr.js +87 -0
  48. package/dist/random.d.ts +66 -0
  49. package/dist/random.js +3 -0
  50. package/dist/select-BjySLL8I.js +280 -0
  51. package/dist/storage/memory.d.ts +82 -0
  52. package/dist/storage/memory.js +127 -0
  53. package/dist/storage/storage.d.ts +2 -0
  54. package/dist/storage/storage.js +3 -0
  55. package/dist/storage/turso.d.ts +31 -0
  56. package/dist/storage/turso.js +117 -0
  57. package/dist/storage/unstorage.d.ts +38 -0
  58. package/dist/storage/unstorage.js +97 -0
  59. package/dist/storage-BEaqEPNQ.js +62 -0
  60. package/dist/storage-CxKerLlc.d.ts +162 -0
  61. package/dist/subject-DiQdRWGt.d.ts +62 -0
  62. package/dist/subject.d.ts +3 -0
  63. package/dist/subject.js +36 -0
  64. package/dist/theme-C9by7VXf.d.ts +209 -0
  65. package/dist/theme-CswaLtbW.js +120 -0
  66. package/dist/themes/theme.d.ts +2 -0
  67. package/dist/themes/theme.js +3 -0
  68. package/dist/types.d.ts +94 -0
  69. package/dist/types.js +0 -0
  70. package/dist/ui/base.d.ts +43 -0
  71. package/dist/ui/base.js +4 -0
  72. package/dist/ui/code.d.ts +158 -0
  73. package/dist/ui/code.js +197 -0
  74. package/dist/ui/form.d.ts +31 -0
  75. package/dist/ui/form.js +3 -0
  76. package/dist/ui/icon.d.ts +98 -0
  77. package/dist/ui/icon.js +3 -0
  78. package/dist/ui/password.d.ts +54 -0
  79. package/dist/ui/password.js +300 -0
  80. package/dist/ui/select.d.ts +233 -0
  81. package/dist/ui/select.js +6 -0
  82. package/dist/util-CSdHUFOo.js +108 -0
  83. package/dist/util-ChlgVqPN.d.ts +72 -0
  84. package/dist/util.d.ts +2 -0
  85. package/dist/util.js +3 -0
  86. package/package.json +63 -0
@@ -0,0 +1,413 @@
1
+ import { InvalidAccessTokenError, InvalidAuthorizationCodeError, InvalidRefreshTokenError, InvalidSubjectError } from "./error-CWAdNAzm.js";
2
+ import "./util-ChlgVqPN.js";
3
+ import { SubjectSchema } from "./subject-DiQdRWGt.js";
4
+ import { StandardSchemaV1 } from "@standard-schema/spec";
5
+
6
+ //#region src/client.d.ts
7
+
8
+ /**
9
+ * Result type for operations that can succeed or fail.
10
+ *
11
+ * @template T - The success data type
12
+ * @template E - The error type
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * const result = await client.exchange(code, redirectUri)
17
+ * if (result.success) {
18
+ * // Access token available: result.data.access
19
+ * } else {
20
+ * // Handle error: result.error.message
21
+ * }
22
+ * ```
23
+ */
24
+ type Result<T, E = Error> = {
25
+ success: true;
26
+ data: T;
27
+ } | {
28
+ success: false;
29
+ error: E;
30
+ };
31
+ interface FetchResponse {
32
+ ok: boolean;
33
+ text(): Promise<string>;
34
+ json(): Promise<unknown>;
35
+ }
36
+ type FetchLike = (url: string, init?: RequestInit) => Promise<FetchResponse>;
37
+ /**
38
+ * Authorization server metadata from well-known endpoints.
39
+ */
40
+ interface WellKnown {
41
+ /**
42
+ * URI to the JWKS endpoint for token verification.
43
+ */
44
+ jwks_uri: string;
45
+ /**
46
+ * URI to the token endpoint for authorization code exchange.
47
+ */
48
+ token_endpoint: string;
49
+ /**
50
+ * URI to the authorization endpoint for starting flows.
51
+ */
52
+ authorization_endpoint: string;
53
+ }
54
+ /**
55
+ * Tokens returned by the authorization server.
56
+ */
57
+ interface Tokens {
58
+ /**
59
+ * Access token for making authenticated API requests.
60
+ */
61
+ access: string;
62
+ /**
63
+ * Refresh token for obtaining new access tokens.
64
+ */
65
+ refresh: string;
66
+ /**
67
+ * Number of seconds until the access token expires.
68
+ */
69
+ expiresIn: number;
70
+ }
71
+ /**
72
+ * Challenge data for PKCE flows.
73
+ */
74
+ type Challenge = {
75
+ /**
76
+ * State parameter for CSRF protection.
77
+ */
78
+ state: string;
79
+ /**
80
+ * PKCE code verifier for token exchange.
81
+ */
82
+ verifier?: string;
83
+ };
84
+ /**
85
+ * Client configuration options.
86
+ */
87
+ interface ClientInput {
88
+ /**
89
+ * Client ID that identifies your application.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * {
94
+ * clientID: "my-web-app"
95
+ * }
96
+ * ```
97
+ */
98
+ clientID: string;
99
+ /**
100
+ * Base URL of your Draft Auth server.
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * {
105
+ * issuer: "https://auth.myserver.com"
106
+ * }
107
+ * ```
108
+ */
109
+ issuer: string;
110
+ /**
111
+ * Optionally, override the internally used fetch function.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * {
116
+ * fetch: customFetch
117
+ * }
118
+ * ```
119
+ */
120
+ fetch?: FetchLike;
121
+ }
122
+ /**
123
+ * Options for starting an authorization flow.
124
+ */
125
+ interface AuthorizeOptions {
126
+ /**
127
+ * Enable PKCE flow for enhanced security.
128
+ *
129
+ * Recommended for single-page applications and mobile apps.
130
+ *
131
+ * @default false
132
+ * @example
133
+ * ```ts
134
+ * {
135
+ * pkce: true
136
+ * }
137
+ * ```
138
+ */
139
+ pkce?: boolean;
140
+ /**
141
+ * Specific authentication provider to use.
142
+ *
143
+ * If not specified, users see a provider selection screen
144
+ * or are redirected to the single configured provider.
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * {
149
+ * provider: "google"
150
+ * }
151
+ * ```
152
+ */
153
+ provider?: string;
154
+ }
155
+ /**
156
+ * Result of starting an authorization flow.
157
+ */
158
+ interface AuthorizeResult {
159
+ /**
160
+ * Challenge data needed for PKCE flows.
161
+ *
162
+ * Store this securely and use when exchanging the code.
163
+ *
164
+ * @example
165
+ * ```ts
166
+ * sessionStorage.setItem("challenge", JSON.stringify(challenge))
167
+ * ```
168
+ */
169
+ challenge: Challenge;
170
+ /**
171
+ * Authorization URL to redirect the user to.
172
+ *
173
+ * @example
174
+ * ```ts
175
+ * window.location.href = url
176
+ * ```
177
+ */
178
+ url: string;
179
+ }
180
+ /**
181
+ * Options for token refresh operations.
182
+ */
183
+ interface RefreshOptions {
184
+ /**
185
+ * Current access token to check before refreshing.
186
+ *
187
+ * Helps avoid unnecessary refresh requests.
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * {
192
+ * access: currentAccessToken
193
+ * }
194
+ * ```
195
+ */
196
+ access?: string;
197
+ }
198
+ /**
199
+ * Options for token verification.
200
+ */
201
+ interface VerifyOptions {
202
+ /**
203
+ * Refresh token for automatic refresh if access token is expired.
204
+ *
205
+ * If passed in, this will automatically refresh the access token if it has expired.
206
+ *
207
+ * @example
208
+ * ```ts
209
+ * {
210
+ * refresh: refreshToken
211
+ * }
212
+ * ```
213
+ */
214
+ refresh?: string;
215
+ /**
216
+ * Expected issuer for validation.
217
+ * @internal
218
+ */
219
+ issuer?: string;
220
+ /**
221
+ * Expected audience for validation.
222
+ * @internal
223
+ */
224
+ audience?: string;
225
+ /**
226
+ * Custom fetch for HTTP requests.
227
+ *
228
+ * Optionally, override the internally used fetch function.
229
+ */
230
+ fetch?: FetchLike;
231
+ }
232
+ /**
233
+ * Result of successful token verification.
234
+ */
235
+ interface VerifyResult<T extends SubjectSchema> {
236
+ /**
237
+ * New tokens if access token was refreshed during verification.
238
+ */
239
+ tokens?: Tokens;
240
+ /**
241
+ * Audience (client ID) the token was issued for.
242
+ * @internal
243
+ */
244
+ aud: string;
245
+ /**
246
+ * Decoded subject information from the access token.
247
+ *
248
+ * Contains user data that was encoded when the token was issued.
249
+ */
250
+ subject: { [K in keyof T]: {
251
+ type: K;
252
+ properties: StandardSchemaV1.InferOutput<T[K]>;
253
+ } }[keyof T];
254
+ }
255
+ /**
256
+ * Options for UserInfo requests.
257
+ */
258
+ /**
259
+ * Draft Auth client with OAuth 2.0 operations.
260
+ */
261
+ interface Client {
262
+ /**
263
+ * Start an OAuth authorization flow.
264
+ *
265
+ * @param redirectURI - Where users will be sent after authorization
266
+ * @param response - Response type ("code" or "token")
267
+ * @param opts - Additional authorization options
268
+ * @returns Authorization URL and challenge data
269
+ *
270
+ * @example Basic flow
271
+ * ```ts
272
+ * const result = await client.authorize(
273
+ * "https://myapp.com/callback",
274
+ * "code"
275
+ * )
276
+ * if (result.success) {
277
+ * window.location.href = result.data.url
278
+ * }
279
+ * ```
280
+ *
281
+ * @example PKCE flow
282
+ * ```ts
283
+ * const result = await client.authorize(
284
+ * "https://spa.example.com/callback",
285
+ * "code",
286
+ * { pkce: true, scopes: ["read", "write"] }
287
+ * )
288
+ * if (result.success) {
289
+ * sessionStorage.setItem("challenge", JSON.stringify(result.data.challenge))
290
+ * window.location.href = result.data.url
291
+ * }
292
+ * ```
293
+ */
294
+ authorize(redirectURI: string, response: "code" | "token", opts?: AuthorizeOptions): Promise<Result<AuthorizeResult>>;
295
+ /**
296
+ * Exchange authorization code for tokens.
297
+ *
298
+ * @param code - Authorization code from the callback
299
+ * @param redirectURI - Same redirect URI used in authorization
300
+ * @param verifier - PKCE code verifier (required for PKCE flows)
301
+ * @returns Access tokens and metadata
302
+ *
303
+ * @example Basic exchange
304
+ * ```ts
305
+ * const urlParams = new URLSearchParams(window.location.search)
306
+ * const code = urlParams.get('code')
307
+ *
308
+ * if (code) {
309
+ * const result = await client.exchange(code, "https://myapp.com/callback")
310
+ * if (result.success) {
311
+ * const { access, refresh } = result.data
312
+ * // Store tokens securely
313
+ * }
314
+ * }
315
+ * ```
316
+ *
317
+ * @example PKCE exchange
318
+ * ```ts
319
+ * const challenge = JSON.parse(sessionStorage.getItem("challenge") || "{}")
320
+ * const code = new URLSearchParams(window.location.search).get('code')
321
+ *
322
+ * if (code && challenge.verifier) {
323
+ * const result = await client.exchange(
324
+ * code,
325
+ * "https://spa.example.com/callback",
326
+ * challenge.verifier
327
+ * )
328
+ * if (result.success) {
329
+ * sessionStorage.removeItem("challenge")
330
+ * // Handle tokens
331
+ * }
332
+ * }
333
+ * ```
334
+ */
335
+ exchange(code: string, redirectURI: string, verifier?: string): Promise<Result<Tokens, InvalidAuthorizationCodeError>>;
336
+ /**
337
+ * Refresh an access token using a refresh token.
338
+ *
339
+ * @param refresh - Refresh token to use
340
+ * @param opts - Additional refresh options
341
+ * @returns New tokens if refresh was needed
342
+ *
343
+ * @example Basic refresh
344
+ * ```ts
345
+ * const result = await client.refresh(storedRefreshToken)
346
+ *
347
+ * if (result.success && result.data.tokens) {
348
+ * const { access, refresh: newRefresh } = result.data.tokens
349
+ * updateStoredTokens(access, newRefresh)
350
+ * } else if (result.success) {
351
+ * // Token still valid
352
+ * } else {
353
+ * redirectToLogin()
354
+ * }
355
+ * ```
356
+ */
357
+ refresh(refresh: string, opts?: RefreshOptions): Promise<Result<{
358
+ tokens?: Tokens;
359
+ }, InvalidRefreshTokenError | InvalidAccessTokenError>>;
360
+ /**
361
+ * Verify and decode an access token.
362
+ *
363
+ * @param subjects - Subject schema used when creating the issuer
364
+ * @param token - Access token to verify
365
+ * @param options - Additional verification options
366
+ * @returns Decoded token data and user information
367
+ *
368
+ * @example Basic verification
369
+ * ```ts
370
+ * const result = await client.verify(subjects, accessToken)
371
+ *
372
+ * if (result.success) {
373
+ * const { subject, scopes } = result.data
374
+ * // Access user ID: subject.properties.userID
375
+ * // Access scopes: scopes?.join(', ')
376
+ * }
377
+ * ```
378
+ *
379
+ * @example With automatic refresh
380
+ * ```ts
381
+ * const result = await client.verify(subjects, accessToken, {
382
+ * refresh: refreshToken
383
+ * })
384
+ *
385
+ * if (result.success) {
386
+ * if (result.data.tokens) {
387
+ * // Tokens were refreshed
388
+ * updateStoredTokens(result.data.tokens.access, result.data.tokens.refresh)
389
+ * }
390
+ * // Use verified subject data
391
+ * const user = result.data.subject.properties
392
+ * }
393
+ * ```
394
+ */
395
+ verify<T extends SubjectSchema>(subjects: T, token: string, options?: VerifyOptions): Promise<Result<VerifyResult<T>, InvalidRefreshTokenError | InvalidAccessTokenError | InvalidSubjectError>>;
396
+ }
397
+ /**
398
+ * Create a Draft Auth client.
399
+ *
400
+ * @param input - Client configuration
401
+ * @returns Configured client instance
402
+ *
403
+ * @example Basic setup
404
+ * ```ts
405
+ * const client = createClient({
406
+ * clientID: "my-web-app",
407
+ * issuer: "https://auth.mycompany.com"
408
+ * })
409
+ * ```
410
+ */
411
+ declare const createClient: (input: ClientInput) => Client;
412
+ //#endregion
413
+ export { AuthorizeOptions, AuthorizeResult, Challenge, Client, ClientInput, RefreshOptions, Result, Tokens, VerifyOptions, VerifyResult, WellKnown, createClient };
package/dist/client.js ADDED
@@ -0,0 +1,209 @@
1
+ import { InvalidAccessTokenError, InvalidAuthorizationCodeError, InvalidRefreshTokenError, InvalidSubjectError } from "./error-DgAKK7b2.js";
2
+ import { generatePKCE } from "./pkce-276Za_rZ.js";
3
+ import { createLocalJWKSet, errors, jwtVerify } from "jose";
4
+
5
+ //#region src/client.ts
6
+ /**
7
+ * Create a Draft Auth client.
8
+ *
9
+ * @param input - Client configuration
10
+ * @returns Configured client instance
11
+ *
12
+ * @example Basic setup
13
+ * ```ts
14
+ * const client = createClient({
15
+ * clientID: "my-web-app",
16
+ * issuer: "https://auth.mycompany.com"
17
+ * })
18
+ * ```
19
+ */
20
+ const createClient = (input) => {
21
+ const jwksCache = /* @__PURE__ */ new Map();
22
+ const issuerCache = /* @__PURE__ */ new Map();
23
+ const issuer = input.issuer;
24
+ if (!issuer) throw new Error("No issuer configured");
25
+ const f = input.fetch ?? fetch;
26
+ const getIssuer = async () => {
27
+ const cached = issuerCache.get(issuer);
28
+ if (cached) return cached;
29
+ const wellKnown = await f(`${issuer}/.well-known/oauth-authorization-server`).then((r) => r.json());
30
+ issuerCache.set(issuer, wellKnown);
31
+ return wellKnown;
32
+ };
33
+ const getJWKS = async () => {
34
+ const wk = await getIssuer();
35
+ const cached = jwksCache.get(issuer);
36
+ if (cached) return cached;
37
+ const keyset = await f(wk.jwks_uri).then((r) => r.json());
38
+ const result = createLocalJWKSet(keyset);
39
+ jwksCache.set(issuer, result);
40
+ return result;
41
+ };
42
+ const client = {
43
+ async authorize(redirectURI, response, opts) {
44
+ try {
45
+ const wk = await getIssuer();
46
+ const authUrl = new URL(wk.authorization_endpoint);
47
+ const challenge = { state: crypto.randomUUID() };
48
+ authUrl.searchParams.set("client_id", input.clientID);
49
+ authUrl.searchParams.set("redirect_uri", redirectURI);
50
+ authUrl.searchParams.set("response_type", response);
51
+ authUrl.searchParams.set("state", challenge.state);
52
+ if (opts?.provider) authUrl.searchParams.set("provider", opts.provider);
53
+ if (opts?.pkce && response === "code") {
54
+ const pkce = await generatePKCE();
55
+ authUrl.searchParams.set("code_challenge_method", "S256");
56
+ authUrl.searchParams.set("code_challenge", pkce.challenge);
57
+ challenge.verifier = pkce.verifier;
58
+ }
59
+ return {
60
+ success: true,
61
+ data: {
62
+ challenge,
63
+ url: authUrl.toString()
64
+ }
65
+ };
66
+ } catch (error) {
67
+ return {
68
+ success: false,
69
+ error
70
+ };
71
+ }
72
+ },
73
+ async exchange(code, redirectURI, verifier) {
74
+ try {
75
+ const wk = await getIssuer();
76
+ const response = await f(wk.token_endpoint, {
77
+ method: "POST",
78
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
79
+ body: new URLSearchParams({
80
+ code,
81
+ redirect_uri: redirectURI,
82
+ grant_type: "authorization_code",
83
+ client_id: input.clientID,
84
+ ...verifier ? { code_verifier: verifier } : {}
85
+ }).toString()
86
+ });
87
+ if (!response.ok) return {
88
+ success: false,
89
+ error: new InvalidAuthorizationCodeError()
90
+ };
91
+ const responseText = await response.text();
92
+ let json;
93
+ try {
94
+ json = JSON.parse(responseText);
95
+ } catch {
96
+ return {
97
+ success: false,
98
+ error: new InvalidAuthorizationCodeError()
99
+ };
100
+ }
101
+ const tokenResponse = json;
102
+ return {
103
+ success: true,
104
+ data: {
105
+ access: tokenResponse.access_token,
106
+ refresh: tokenResponse.refresh_token,
107
+ expiresIn: tokenResponse.expires_in
108
+ }
109
+ };
110
+ } catch {
111
+ return {
112
+ success: false,
113
+ error: new InvalidAuthorizationCodeError()
114
+ };
115
+ }
116
+ },
117
+ async refresh(refresh, opts) {
118
+ try {
119
+ if (opts?.access) try {
120
+ const jwks = await getJWKS();
121
+ await jwtVerify(opts.access, jwks, { issuer });
122
+ return {
123
+ success: true,
124
+ data: {}
125
+ };
126
+ } catch {}
127
+ const wk = await getIssuer();
128
+ const response = await f(wk.token_endpoint, {
129
+ method: "POST",
130
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
131
+ body: new URLSearchParams({
132
+ refresh_token: refresh,
133
+ grant_type: "refresh_token"
134
+ }).toString()
135
+ });
136
+ if (!response.ok) return {
137
+ success: false,
138
+ error: new InvalidRefreshTokenError()
139
+ };
140
+ const tokenResponse = await response.json();
141
+ return {
142
+ success: true,
143
+ data: { tokens: {
144
+ access: tokenResponse.access_token,
145
+ refresh: tokenResponse.refresh_token,
146
+ expiresIn: tokenResponse.expires_in
147
+ } }
148
+ };
149
+ } catch {
150
+ return {
151
+ success: false,
152
+ error: new InvalidRefreshTokenError()
153
+ };
154
+ }
155
+ },
156
+ async verify(subjects, token, options) {
157
+ try {
158
+ const jwks = await getJWKS();
159
+ const jwtResult = await jwtVerify(token, jwks, { issuer });
160
+ const validated = await subjects[jwtResult.payload.type]?.["~standard"].validate(jwtResult.payload.properties);
161
+ if (!validated?.issues && jwtResult.payload.mode === "access") return {
162
+ success: true,
163
+ data: {
164
+ aud: jwtResult.payload.aud,
165
+ subject: {
166
+ type: jwtResult.payload.type,
167
+ properties: validated?.value
168
+ }
169
+ }
170
+ };
171
+ return {
172
+ success: false,
173
+ error: new InvalidSubjectError()
174
+ };
175
+ } catch (e) {
176
+ if (e instanceof errors.JWTExpired && options?.refresh) {
177
+ const refreshed = await client.refresh(options.refresh);
178
+ if (!refreshed.success) return refreshed;
179
+ if (!refreshed.data.tokens) return {
180
+ success: false,
181
+ error: new InvalidAccessTokenError()
182
+ };
183
+ const verified = await client.verify(subjects, refreshed.data.tokens.access, {
184
+ refresh: refreshed.data.tokens.refresh,
185
+ issuer: options?.issuer,
186
+ audience: options?.audience,
187
+ fetch: options?.fetch
188
+ });
189
+ if (!verified.success) return verified;
190
+ return {
191
+ success: true,
192
+ data: {
193
+ ...verified.data,
194
+ tokens: refreshed.data.tokens
195
+ }
196
+ };
197
+ }
198
+ return {
199
+ success: false,
200
+ error: new InvalidAccessTokenError()
201
+ };
202
+ }
203
+ }
204
+ };
205
+ return client;
206
+ };
207
+
208
+ //#endregion
209
+ export { createClient };