@draftlab/auth 0.15.0 → 0.15.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 (51) hide show
  1. package/dist/adapters/node.d.mts +0 -1
  2. package/dist/client.d.mts +293 -287
  3. package/dist/client.mjs +1 -0
  4. package/dist/core.d.mts +22 -23
  5. package/dist/core.mjs +3 -3
  6. package/dist/error.d.mts +53 -53
  7. package/dist/keys.d.mts +0 -1
  8. package/dist/mutex.d.mts +14 -14
  9. package/dist/provider/apple.d.mts +34 -35
  10. package/dist/provider/code.d.mts +75 -85
  11. package/dist/provider/discord.d.mts +49 -50
  12. package/dist/provider/facebook.d.mts +49 -50
  13. package/dist/provider/github.d.mts +50 -51
  14. package/dist/provider/gitlab.d.mts +34 -35
  15. package/dist/provider/google.d.mts +49 -50
  16. package/dist/provider/linkedin.d.mts +47 -48
  17. package/dist/provider/magiclink.d.mts +28 -38
  18. package/dist/provider/microsoft.d.mts +67 -68
  19. package/dist/provider/oauth2.d.mts +75 -76
  20. package/dist/provider/passkey.d.mts +20 -21
  21. package/dist/provider/password.d.mts +174 -202
  22. package/dist/provider/provider.d.mts +105 -107
  23. package/dist/provider/reddit.d.mts +33 -34
  24. package/dist/provider/slack.d.mts +34 -35
  25. package/dist/provider/spotify.d.mts +34 -35
  26. package/dist/provider/totp.d.mts +43 -44
  27. package/dist/provider/twitch.d.mts +33 -34
  28. package/dist/provider/vercel.d.mts +65 -66
  29. package/dist/revocation.d.mts +29 -30
  30. package/dist/storage/memory.d.mts +11 -12
  31. package/dist/storage/storage.d.mts +110 -110
  32. package/dist/storage/turso.d.mts +0 -1
  33. package/dist/storage/unstorage.d.mts +0 -1
  34. package/dist/subject.d.mts +0 -1
  35. package/dist/themes/theme.d.mts +101 -101
  36. package/dist/toolkit/client.d.mts +56 -57
  37. package/dist/toolkit/providers/facebook.d.mts +0 -1
  38. package/dist/toolkit/providers/github.d.mts +0 -1
  39. package/dist/toolkit/providers/google.d.mts +0 -1
  40. package/dist/toolkit/storage.d.mts +8 -8
  41. package/dist/ui/base.d.mts +0 -1
  42. package/dist/ui/code.d.mts +5 -6
  43. package/dist/ui/form.d.mts +6 -7
  44. package/dist/ui/icon.d.mts +0 -1
  45. package/dist/ui/magiclink.d.mts +5 -6
  46. package/dist/ui/passkey.d.mts +0 -1
  47. package/dist/ui/password.d.mts +2 -3
  48. package/dist/ui/select.d.mts +0 -1
  49. package/dist/ui/totp.d.mts +0 -1
  50. package/dist/util.d.mts +0 -1
  51. package/package.json +3 -3
package/dist/client.mjs CHANGED
@@ -210,6 +210,7 @@ const createClient = (input) => {
210
210
  success: true,
211
211
  data: {
212
212
  aud: jwtResult.payload.aud,
213
+ sub: jwtResult.payload.sub,
213
214
  subject: {
214
215
  type: jwtResult.payload.type,
215
216
  properties: validated?.value
package/dist/core.d.mts CHANGED
@@ -9,7 +9,6 @@ import { Theme } from "./themes/theme.mjs";
9
9
  import { AuthorizationState } from "./types.mjs";
10
10
 
11
11
  //#region src/core.d.ts
12
-
13
12
  /**
14
13
  * Sets the subject payload in the JWT token and returns the response.
15
14
  */
@@ -61,28 +60,28 @@ interface IssuerInput<Providers extends Record<string, Provider<unknown>>, Subje
61
60
  /** Client authorization check function */
62
61
  allow?(input: AllowCheckInput, req: Request): Promise<boolean>;
63
62
  /**
64
- * Refresh callback for updating user claims.
65
- *
66
- * @example
67
- * ```typescript
68
- * refresh: async (payload, req) => {
69
- * const user = await getUserBySubject(payload.subject)
70
- * if (!user || !user.active) {
71
- * return undefined // Revoke the token
72
- * }
73
- *
74
- * return {
75
- * type: payload.type,
76
- * properties: {
77
- * userID: user.id,
78
- * role: user.role,
79
- * permissions: user.permissions,
80
- * lastLogin: new Date().toISOString()
81
- * }
82
- * }
83
- * }
84
- * ```
85
- */
63
+ * Refresh callback for updating user claims.
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * refresh: async (payload, req) => {
68
+ * const user = await getUserBySubject(payload.subject)
69
+ * if (!user || !user.active) {
70
+ * return undefined // Revoke the token
71
+ * }
72
+ *
73
+ * return {
74
+ * type: payload.type,
75
+ * properties: {
76
+ * userID: user.id,
77
+ * role: user.role,
78
+ * permissions: user.permissions,
79
+ * lastLogin: new Date().toISOString()
80
+ * }
81
+ * }
82
+ * }
83
+ * ```
84
+ */
86
85
  refresh?(payload: {
87
86
  type: SubjectPayload<Subjects>["type"];
88
87
  properties: SubjectPayload<Subjects>["properties"];
package/dist/core.mjs CHANGED
@@ -84,7 +84,7 @@ const issuer = (input) => {
84
84
  * Resolves issuer URL from context.
85
85
  * Returns the base URL for the OAuth issuer, considering basePath configuration.
86
86
  */
87
- const issuer$1 = (ctx) => {
87
+ const issuer = (ctx) => {
88
88
  const baseUrl = new URL(getRelativeUrl(ctx, "/"));
89
89
  if (input.basePath) {
90
90
  baseUrl.pathname = (input.basePath.startsWith("/") ? input.basePath : `/${input.basePath}`).replace(/\/$/, "");
@@ -158,7 +158,7 @@ const issuer = (input) => {
158
158
  properties: value.properties,
159
159
  sub: value.subject,
160
160
  aud: value.clientID,
161
- iss: issuer$1(ctx),
161
+ iss: issuer(ctx),
162
162
  exp: now + value.ttl.access,
163
163
  iat: now,
164
164
  mode: "access"
@@ -313,7 +313,7 @@ const issuer = (input) => {
313
313
  credentials: false
314
314
  })],
315
315
  handler: (c) => {
316
- const iss = issuer$1(c);
316
+ const iss = issuer(c);
317
317
  const oauth2Document = {
318
318
  issuer: iss,
319
319
  authorization_endpoint: `${iss}/authorize`,
package/dist/error.d.mts CHANGED
@@ -49,28 +49,28 @@ declare class OauthError extends Error {
49
49
  /** Human-readable description of the error */
50
50
  readonly description: string;
51
51
  /**
52
- * Creates a new OAuth error with the specified error code and description.
53
- *
54
- * @param error - The OAuth error type
55
- * @param description - Human-readable error description
56
- *
57
- * @example
58
- * ```ts
59
- * throw new OauthError("invalid_grant", "Authorization code has expired")
60
- * ```
61
- */
52
+ * Creates a new OAuth error with the specified error code and description.
53
+ *
54
+ * @param error - The OAuth error type
55
+ * @param description - Human-readable error description
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * throw new OauthError("invalid_grant", "Authorization code has expired")
60
+ * ```
61
+ */
62
62
  constructor(error: OauthErrorType, description: string);
63
63
  /**
64
- * Converts the error to a standard OAuth JSON response format.
65
- *
66
- * @returns Object with error and error_description fields
67
- *
68
- * @example
69
- * ```ts
70
- * const oauthError = new OauthError("invalid_request", "Missing parameter")
71
- * return c.json(oauthError.toJSON(), 400)
72
- * ```
73
- */
64
+ * Converts the error to a standard OAuth JSON response format.
65
+ *
66
+ * @returns Object with error and error_description fields
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * const oauthError = new OauthError("invalid_request", "Missing parameter")
71
+ * return c.json(oauthError.toJSON(), 400)
72
+ * ```
73
+ */
74
74
  toJSON(): {
75
75
  error: OauthErrorType;
76
76
  error_description: string;
@@ -82,9 +82,9 @@ declare class OauthError extends Error {
82
82
  */
83
83
  declare class MissingProviderError extends OauthError {
84
84
  /**
85
- * Creates a missing provider error.
86
- * Thrown when the provider query parameter is required but not provided.
87
- */
85
+ * Creates a missing provider error.
86
+ * Thrown when the provider query parameter is required but not provided.
87
+ */
88
88
  constructor();
89
89
  }
90
90
  /**
@@ -95,15 +95,15 @@ declare class MissingParameterError extends OauthError {
95
95
  /** The name of the missing parameter */
96
96
  readonly parameter: string;
97
97
  /**
98
- * Creates a missing parameter error.
99
- *
100
- * @param parameter - The name of the missing parameter
101
- *
102
- * @example
103
- * ```ts
104
- * throw new MissingParameterError("client_id")
105
- * ```
106
- */
98
+ * Creates a missing parameter error.
99
+ *
100
+ * @param parameter - The name of the missing parameter
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * throw new MissingParameterError("client_id")
105
+ * ```
106
+ */
107
107
  constructor(parameter: string);
108
108
  }
109
109
  /**
@@ -114,16 +114,16 @@ declare class UnauthorizedClientError extends OauthError {
114
114
  /** The client ID that attempted unauthorized access */
115
115
  readonly clientID: string;
116
116
  /**
117
- * Creates an unauthorized client error.
118
- *
119
- * @param clientID - The client ID attempting unauthorized access
120
- * @param redirectURI - The unauthorized redirect URI
121
- *
122
- * @example
123
- * ```ts
124
- * throw new UnauthorizedClientError("malicious-client", "https://evil.com/callback")
125
- * ```
126
- */
117
+ * Creates an unauthorized client error.
118
+ *
119
+ * @param clientID - The client ID attempting unauthorized access
120
+ * @param redirectURI - The unauthorized redirect URI
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * throw new UnauthorizedClientError("malicious-client", "https://evil.com/callback")
125
+ * ```
126
+ */
127
127
  constructor(clientID: string, redirectURI: string);
128
128
  }
129
129
  /**
@@ -146,9 +146,9 @@ declare class UnauthorizedClientError extends OauthError {
146
146
  */
147
147
  declare class UnknownStateError extends Error {
148
148
  /**
149
- * Creates an unknown state error.
150
- * Indicates that the authentication flow cannot continue due to missing state.
151
- */
149
+ * Creates an unknown state error.
150
+ * Indicates that the authentication flow cannot continue due to missing state.
151
+ */
152
152
  constructor();
153
153
  }
154
154
  /**
@@ -166,8 +166,8 @@ declare class UnknownStateError extends Error {
166
166
  */
167
167
  declare class InvalidSubjectError extends Error {
168
168
  /**
169
- * Creates an invalid subject error.
170
- */
169
+ * Creates an invalid subject error.
170
+ */
171
171
  constructor();
172
172
  }
173
173
  /**
@@ -189,8 +189,8 @@ declare class InvalidSubjectError extends Error {
189
189
  */
190
190
  declare class InvalidRefreshTokenError extends Error {
191
191
  /**
192
- * Creates an invalid refresh token error.
193
- */
192
+ * Creates an invalid refresh token error.
193
+ */
194
194
  constructor();
195
195
  }
196
196
  /**
@@ -212,8 +212,8 @@ declare class InvalidRefreshTokenError extends Error {
212
212
  */
213
213
  declare class InvalidAccessTokenError extends Error {
214
214
  /**
215
- * Creates an invalid access token error.
216
- */
215
+ * Creates an invalid access token error.
216
+ */
217
217
  constructor();
218
218
  }
219
219
  /**
@@ -235,8 +235,8 @@ declare class InvalidAccessTokenError extends Error {
235
235
  */
236
236
  declare class InvalidAuthorizationCodeError extends Error {
237
237
  /**
238
- * Creates an invalid authorization code error.
239
- */
238
+ * Creates an invalid authorization code error.
239
+ */
240
240
  constructor();
241
241
  }
242
242
  //#endregion
package/dist/keys.d.mts CHANGED
@@ -2,7 +2,6 @@ import { StorageAdapter } from "./storage/storage.mjs";
2
2
  import { CryptoKey, JWK } from "jose";
3
3
 
4
4
  //#region src/keys.d.ts
5
-
6
5
  /**
7
6
  * Runtime key pair with loaded cryptographic keys and metadata.
8
7
  * Ready for immediate use in signing and encryption operations.
package/dist/mutex.d.mts CHANGED
@@ -18,26 +18,26 @@
18
18
  declare class Mutex {
19
19
  private semaphore;
20
20
  /**
21
- * Checks if the mutex is currently locked.
22
- * @returns True if the mutex is locked, false otherwise.
23
- */
21
+ * Checks if the mutex is currently locked.
22
+ * @returns True if the mutex is locked, false otherwise.
23
+ */
24
24
  get isLocked(): boolean;
25
25
  /**
26
- * Acquires the mutex, blocking if necessary until it is available.
27
- * @returns A promise that resolves when the mutex is acquired.
28
- */
26
+ * Acquires the mutex, blocking if necessary until it is available.
27
+ * @returns A promise that resolves when the mutex is acquired.
28
+ */
29
29
  acquire(): Promise<void>;
30
30
  /**
31
- * Releases the mutex, allowing another waiting task to proceed.
32
- */
31
+ * Releases the mutex, allowing another waiting task to proceed.
32
+ */
33
33
  release(): void;
34
34
  /**
35
- * Runs a function while holding the mutex lock.
36
- * Automatically acquires before and releases after the function execution.
37
- *
38
- * @param fn - The function to execute while holding the lock
39
- * @returns The result of the function
40
- */
35
+ * Runs a function while holding the mutex lock.
36
+ * Automatically acquires before and releases after the function execution.
37
+ *
38
+ * @param fn - The function to execute while holding the lock
39
+ * @returns The result of the function
40
+ */
41
41
  runExclusive<T>(fn: () => Promise<T>): Promise<T>;
42
42
  }
43
43
  //#endregion
@@ -2,51 +2,50 @@ import { Provider } from "./provider.mjs";
2
2
  import { Oauth2UserData, Oauth2WrappedConfig } from "./oauth2.mjs";
3
3
 
4
4
  //#region src/provider/apple.d.ts
5
-
6
5
  /**
7
6
  * Configuration options for Apple OAuth 2.0 provider.
8
7
  * Extends the base OAuth 2.0 configuration with Apple-specific documentation.
9
8
  */
10
9
  interface AppleConfig extends Oauth2WrappedConfig {
11
10
  /**
12
- * Apple Service ID (app identifier for your Sign in with Apple implementation).
13
- * Get this from your Apple Developer account when creating a Service ID.
14
- *
15
- * @example
16
- * ```ts
17
- * {
18
- * clientID: "com.example.app.signin"
19
- * }
20
- * ```
21
- */
11
+ * Apple Service ID (app identifier for your Sign in with Apple implementation).
12
+ * Get this from your Apple Developer account when creating a Service ID.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * {
17
+ * clientID: "com.example.app.signin"
18
+ * }
19
+ * ```
20
+ */
22
21
  readonly clientID: string;
23
22
  /**
24
- * Apple client secret (JWT token signed with your private key).
25
- * This is different from other providers - Apple requires a JWT token
26
- * generated from your private key.
27
- *
28
- * @example
29
- * ```ts
30
- * {
31
- * clientSecret: process.env.APPLE_CLIENT_SECRET
32
- * }
33
- * ```
34
- */
23
+ * Apple client secret (JWT token signed with your private key).
24
+ * This is different from other providers - Apple requires a JWT token
25
+ * generated from your private key.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * {
30
+ * clientSecret: process.env.APPLE_CLIENT_SECRET
31
+ * }
32
+ * ```
33
+ */
35
34
  readonly clientSecret: string;
36
35
  /**
37
- * Apple OAuth scopes to request access for.
38
- * Apple only supports "name" and "email" scopes.
39
- *
40
- * Important: Apple only provides user data (name, email) on the FIRST authorization.
41
- * Subsequent authorizations won't include this data.
42
- *
43
- * @example
44
- * ```ts
45
- * {
46
- * scopes: ["name", "email"]
47
- * }
48
- * ```
49
- */
36
+ * Apple OAuth scopes to request access for.
37
+ * Apple only supports "name" and "email" scopes.
38
+ *
39
+ * Important: Apple only provides user data (name, email) on the FIRST authorization.
40
+ * Subsequent authorizations won't include this data.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * {
45
+ * scopes: ["name", "email"]
46
+ * }
47
+ * ```
48
+ */
50
49
  readonly scopes: string[];
51
50
  }
52
51
  /**
@@ -1,7 +1,6 @@
1
1
  import { Provider } from "./provider.mjs";
2
2
 
3
3
  //#region src/provider/code.d.ts
4
-
5
4
  /**
6
5
  * Configuration options for the PIN code authentication provider.
7
6
  *
@@ -9,78 +8,78 @@ import { Provider } from "./provider.mjs";
9
8
  */
10
9
  interface CodeProviderConfig<Claims extends Record<string, string> = Record<string, string>> {
11
10
  /**
12
- * The length of the generated PIN code.
13
- * Common values are 4, 6, or 8 digits.
14
- *
15
- * @default 6
16
- *
17
- * @example
18
- * ```ts
19
- * {
20
- * length: 4 // 4-digit PIN for easier entry
21
- * }
22
- * ```
23
- */
11
+ * The length of the generated PIN code.
12
+ * Common values are 4, 6, or 8 digits.
13
+ *
14
+ * @default 6
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * {
19
+ * length: 4 // 4-digit PIN for easier entry
20
+ * }
21
+ * ```
22
+ */
24
23
  readonly length?: number;
25
24
  /**
26
- * Request handler for rendering the authentication UI.
27
- * Handles both the initial claim collection and PIN code entry screens.
28
- *
29
- * @param req - The HTTP request object
30
- * @param state - Current authentication state (start or code verification)
31
- * @param form - Form data from POST requests (if any)
32
- * @param error - Authentication error to display (if any)
33
- * @returns Promise resolving to the authentication page response
34
- *
35
- * @example
36
- * ```ts
37
- * request: async (req, state, form, error) => {
38
- * if (state.type === 'start') {
39
- * return new Response(renderClaimForm(form, error))
40
- * } else {
41
- * return new Response(renderCodeForm(state.claims.email, error))
42
- * }
43
- * }
44
- * ```
45
- */
25
+ * Request handler for rendering the authentication UI.
26
+ * Handles both the initial claim collection and PIN code entry screens.
27
+ *
28
+ * @param req - The HTTP request object
29
+ * @param state - Current authentication state (start or code verification)
30
+ * @param form - Form data from POST requests (if any)
31
+ * @param error - Authentication error to display (if any)
32
+ * @returns Promise resolving to the authentication page response
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * request: async (req, state, form, error) => {
37
+ * if (state.type === 'start') {
38
+ * return new Response(renderClaimForm(form, error))
39
+ * } else {
40
+ * return new Response(renderCodeForm(state.claims.email, error))
41
+ * }
42
+ * }
43
+ * ```
44
+ */
46
45
  request: (req: Request, state: CodeProviderState, form?: FormData, error?: CodeProviderError) => Promise<Response>;
47
46
  /**
48
- * Callback for sending PIN codes to users via their preferred method.
49
- * Should handle delivery via email, SMS, or other communication channels.
50
- *
51
- * @param claims - User claims containing contact information
52
- * @param code - The generated PIN code to send
53
- * @returns Promise resolving to undefined on success, or error object on failure
54
- *
55
- * @example
56
- * ```ts
57
- * sendCode: async (claims, code) => {
58
- * try {
59
- * if (claims.email) {
60
- * await emailService.send({
61
- * to: claims.email,
62
- * subject: 'Your verification code',
63
- * text: `Your PIN code is: ${code}`
64
- * })
65
- * } else if (claims.phone) {
66
- * await smsService.send(claims.phone, `PIN: ${code}`)
67
- * } else {
68
- * return {
69
- * type: "invalid_claim",
70
- * key: "email",
71
- * value: "Email or phone number is required"
72
- * }
73
- * }
74
- * } catch (error) {
75
- * return {
76
- * type: "invalid_claim",
77
- * key: "delivery",
78
- * value: "Failed to send code"
79
- * }
80
- * }
81
- * }
82
- * ```
83
- */
47
+ * Callback for sending PIN codes to users via their preferred method.
48
+ * Should handle delivery via email, SMS, or other communication channels.
49
+ *
50
+ * @param claims - User claims containing contact information
51
+ * @param code - The generated PIN code to send
52
+ * @returns Promise resolving to undefined on success, or error object on failure
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * sendCode: async (claims, code) => {
57
+ * try {
58
+ * if (claims.email) {
59
+ * await emailService.send({
60
+ * to: claims.email,
61
+ * subject: 'Your verification code',
62
+ * text: `Your PIN code is: ${code}`
63
+ * })
64
+ * } else if (claims.phone) {
65
+ * await smsService.send(claims.phone, `PIN: ${code}`)
66
+ * } else {
67
+ * return {
68
+ * type: "invalid_claim",
69
+ * key: "email",
70
+ * value: "Email or phone number is required"
71
+ * }
72
+ * }
73
+ * } catch (error) {
74
+ * return {
75
+ * type: "invalid_claim",
76
+ * key: "delivery",
77
+ * value: "Failed to send code"
78
+ * }
79
+ * }
80
+ * }
81
+ * ```
82
+ */
84
83
  sendCode: (claims: Claims, code: string) => Promise<CodeProviderError | undefined>;
85
84
  }
86
85
  /**
@@ -88,30 +87,21 @@ interface CodeProviderConfig<Claims extends Record<string, string> = Record<stri
88
87
  * The provider transitions between these states during authentication.
89
88
  */
90
89
  type CodeProviderState = {
91
- /** Initial state: user enters their claims (email, phone, etc.) */
92
- readonly type: "start";
90
+ /** Initial state: user enters their claims (email, phone, etc.) */readonly type: "start";
93
91
  } | {
94
- /** Code verification state: user enters the PIN code */
95
- readonly type: "code";
96
- /** Whether this is a code resend request */
97
- readonly resend?: boolean;
98
- /** The generated PIN code for verification */
99
- readonly code: string;
100
- /** User claims collected during the start phase */
92
+ /** Code verification state: user enters the PIN code */readonly type: "code"; /** Whether this is a code resend request */
93
+ readonly resend?: boolean; /** The generated PIN code for verification */
94
+ readonly code: string; /** User claims collected during the start phase */
101
95
  readonly claims: Record<string, string>;
102
96
  };
103
97
  /**
104
98
  * Possible errors during PIN code authentication.
105
99
  */
106
100
  type CodeProviderError = {
107
- /** The entered PIN code is incorrect */
108
- readonly type: "invalid_code";
101
+ /** The entered PIN code is incorrect */readonly type: "invalid_code";
109
102
  } | {
110
- /** A user claim is invalid or missing */
111
- readonly type: "invalid_claim";
112
- /** The claim field that failed validation */
113
- readonly key: string;
114
- /** The invalid value or error description */
103
+ /** A user claim is invalid or missing */readonly type: "invalid_claim"; /** The claim field that failed validation */
104
+ readonly key: string; /** The invalid value or error description */
115
105
  readonly value: string;
116
106
  };
117
107
  /**