@draftlab/auth 0.15.1 → 0.16.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 (272) hide show
  1. package/dist/esm/allow.js +26 -0
  2. package/dist/esm/client.js +254 -0
  3. package/dist/esm/core.js +597 -0
  4. package/dist/esm/css.d.js +0 -0
  5. package/dist/esm/error.js +88 -0
  6. package/dist/esm/index.js +5 -0
  7. package/dist/esm/keys.js +126 -0
  8. package/dist/esm/mutex.js +53 -0
  9. package/dist/esm/pkce.js +87 -0
  10. package/dist/esm/provider/apple.js +15 -0
  11. package/dist/esm/provider/code.js +62 -0
  12. package/dist/esm/provider/discord.js +15 -0
  13. package/dist/esm/provider/facebook.js +15 -0
  14. package/dist/esm/provider/github.js +15 -0
  15. package/dist/esm/provider/gitlab.js +15 -0
  16. package/dist/esm/provider/google.js +16 -0
  17. package/dist/esm/provider/linkedin.js +15 -0
  18. package/dist/esm/provider/magiclink.js +83 -0
  19. package/dist/esm/provider/microsoft.js +15 -0
  20. package/dist/esm/provider/oauth2.js +130 -0
  21. package/dist/esm/provider/password.js +331 -0
  22. package/dist/esm/provider/provider.js +18 -0
  23. package/dist/esm/provider/reddit.js +15 -0
  24. package/dist/esm/provider/slack.js +15 -0
  25. package/dist/esm/provider/spotify.js +15 -0
  26. package/dist/esm/provider/twitch.js +15 -0
  27. package/dist/esm/provider/vercel.js +17 -0
  28. package/dist/esm/random.js +40 -0
  29. package/dist/esm/revocation.js +27 -0
  30. package/dist/esm/storage/memory.js +110 -0
  31. package/dist/esm/storage/storage.js +56 -0
  32. package/dist/esm/storage/turso.js +93 -0
  33. package/dist/esm/storage/unstorage.js +78 -0
  34. package/dist/esm/subject.js +7 -0
  35. package/dist/esm/themes/theme.js +115 -0
  36. package/dist/esm/toolkit/client.js +119 -0
  37. package/dist/esm/toolkit/index.js +25 -0
  38. package/dist/esm/toolkit/providers/facebook.js +11 -0
  39. package/dist/esm/toolkit/providers/github.js +11 -0
  40. package/dist/esm/toolkit/providers/google.js +11 -0
  41. package/dist/esm/toolkit/providers/strategy.js +0 -0
  42. package/dist/esm/toolkit/storage.js +81 -0
  43. package/dist/esm/toolkit/utils.js +18 -0
  44. package/dist/esm/types.js +0 -0
  45. package/dist/esm/ui/base.js +478 -0
  46. package/dist/esm/ui/code.js +186 -0
  47. package/dist/esm/ui/form.js +46 -0
  48. package/dist/esm/ui/icon.js +242 -0
  49. package/dist/esm/ui/magiclink.js +158 -0
  50. package/dist/esm/ui/password.js +435 -0
  51. package/dist/esm/ui/select.js +102 -0
  52. package/dist/esm/util.js +59 -0
  53. package/dist/{allow.d.mts → types/allow.d.ts} +9 -11
  54. package/dist/types/allow.d.ts.map +1 -0
  55. package/dist/types/client.d.ts +462 -0
  56. package/dist/types/client.d.ts.map +1 -0
  57. package/dist/types/core.d.ts +113 -0
  58. package/dist/types/core.d.ts.map +1 -0
  59. package/dist/{error.d.mts → types/error.d.ts} +95 -97
  60. package/dist/types/error.d.ts.map +1 -0
  61. package/dist/types/index.d.ts +2 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/{keys.d.mts → types/keys.d.ts} +20 -23
  64. package/dist/types/keys.d.ts.map +1 -0
  65. package/dist/types/mutex.d.ts +42 -0
  66. package/dist/types/mutex.d.ts.map +1 -0
  67. package/dist/{pkce.d.mts → types/pkce.d.ts} +10 -11
  68. package/dist/types/pkce.d.ts.map +1 -0
  69. package/dist/types/provider/apple.d.ts +197 -0
  70. package/dist/types/provider/apple.d.ts.map +1 -0
  71. package/dist/types/provider/code.d.ts +288 -0
  72. package/dist/types/provider/code.d.ts.map +1 -0
  73. package/dist/types/provider/discord.d.ts +206 -0
  74. package/dist/types/provider/discord.d.ts.map +1 -0
  75. package/dist/types/provider/facebook.d.ts +200 -0
  76. package/dist/types/provider/facebook.d.ts.map +1 -0
  77. package/dist/types/provider/github.d.ts +220 -0
  78. package/dist/types/provider/github.d.ts.map +1 -0
  79. package/dist/types/provider/gitlab.d.ts +180 -0
  80. package/dist/types/provider/gitlab.d.ts.map +1 -0
  81. package/dist/types/provider/google.d.ts +158 -0
  82. package/dist/types/provider/google.d.ts.map +1 -0
  83. package/dist/types/provider/linkedin.d.ts +190 -0
  84. package/dist/types/provider/linkedin.d.ts.map +1 -0
  85. package/dist/types/provider/magiclink.d.ts +141 -0
  86. package/dist/types/provider/magiclink.d.ts.map +1 -0
  87. package/dist/types/provider/microsoft.d.ts +247 -0
  88. package/dist/types/provider/microsoft.d.ts.map +1 -0
  89. package/dist/types/provider/oauth2.d.ts +229 -0
  90. package/dist/types/provider/oauth2.d.ts.map +1 -0
  91. package/dist/types/provider/password.d.ts +408 -0
  92. package/dist/types/provider/password.d.ts.map +1 -0
  93. package/dist/types/provider/provider.d.ts +226 -0
  94. package/dist/types/provider/provider.d.ts.map +1 -0
  95. package/dist/types/provider/reddit.d.ts +159 -0
  96. package/dist/types/provider/reddit.d.ts.map +1 -0
  97. package/dist/types/provider/slack.d.ts +171 -0
  98. package/dist/types/provider/slack.d.ts.map +1 -0
  99. package/dist/types/provider/spotify.d.ts +168 -0
  100. package/dist/types/provider/spotify.d.ts.map +1 -0
  101. package/dist/types/provider/twitch.d.ts +163 -0
  102. package/dist/types/provider/twitch.d.ts.map +1 -0
  103. package/dist/types/provider/vercel.d.ts +294 -0
  104. package/dist/types/provider/vercel.d.ts.map +1 -0
  105. package/dist/{random.d.mts → types/random.d.ts} +4 -6
  106. package/dist/types/random.d.ts.map +1 -0
  107. package/dist/types/revocation.d.ts +76 -0
  108. package/dist/types/revocation.d.ts.map +1 -0
  109. package/dist/{storage/memory.d.mts → types/storage/memory.d.ts} +17 -20
  110. package/dist/types/storage/memory.d.ts.map +1 -0
  111. package/dist/types/storage/storage.d.ts +177 -0
  112. package/dist/types/storage/storage.d.ts.map +1 -0
  113. package/dist/{storage/turso.d.mts → types/storage/turso.d.ts} +4 -7
  114. package/dist/types/storage/turso.d.ts.map +1 -0
  115. package/dist/{storage/unstorage.d.mts → types/storage/unstorage.d.ts} +12 -10
  116. package/dist/types/storage/unstorage.d.ts.map +1 -0
  117. package/dist/types/subject.d.ts +115 -0
  118. package/dist/types/subject.d.ts.map +1 -0
  119. package/dist/types/themes/theme.d.ts +207 -0
  120. package/dist/types/themes/theme.d.ts.map +1 -0
  121. package/dist/types/toolkit/client.d.ts +235 -0
  122. package/dist/types/toolkit/client.d.ts.map +1 -0
  123. package/dist/types/toolkit/index.d.ts +45 -0
  124. package/dist/types/toolkit/index.d.ts.map +1 -0
  125. package/dist/types/toolkit/providers/facebook.d.ts +8 -0
  126. package/dist/types/toolkit/providers/facebook.d.ts.map +1 -0
  127. package/dist/types/toolkit/providers/github.d.ts +8 -0
  128. package/dist/types/toolkit/providers/github.d.ts.map +1 -0
  129. package/dist/types/toolkit/providers/google.d.ts +8 -0
  130. package/dist/types/toolkit/providers/google.d.ts.map +1 -0
  131. package/dist/types/toolkit/providers/strategy.d.ts +38 -0
  132. package/dist/types/toolkit/providers/strategy.d.ts.map +1 -0
  133. package/dist/{toolkit/storage.d.mts → types/toolkit/storage.d.ts} +37 -39
  134. package/dist/types/toolkit/storage.d.ts.map +1 -0
  135. package/dist/{toolkit/utils.d.mts → types/toolkit/utils.d.ts} +2 -4
  136. package/dist/types/toolkit/utils.d.ts.map +1 -0
  137. package/dist/types/types.d.ts +92 -0
  138. package/dist/types/types.d.ts.map +1 -0
  139. package/dist/types/ui/base.d.ts +18 -0
  140. package/dist/types/ui/base.d.ts.map +1 -0
  141. package/dist/types/ui/code.d.ts +43 -0
  142. package/dist/types/ui/code.d.ts.map +1 -0
  143. package/dist/types/ui/form.d.ts +24 -0
  144. package/dist/types/ui/form.d.ts.map +1 -0
  145. package/dist/types/ui/icon.d.ts +60 -0
  146. package/dist/types/ui/icon.d.ts.map +1 -0
  147. package/dist/types/ui/magiclink.d.ts +41 -0
  148. package/dist/types/ui/magiclink.d.ts.map +1 -0
  149. package/dist/types/ui/password.d.ts +43 -0
  150. package/dist/types/ui/password.d.ts.map +1 -0
  151. package/dist/types/ui/select.d.ts +33 -0
  152. package/dist/types/ui/select.d.ts.map +1 -0
  153. package/dist/{util.d.mts → types/util.d.ts} +11 -12
  154. package/dist/types/util.d.ts.map +1 -0
  155. package/package.json +10 -16
  156. package/dist/adapters/node.d.mts +0 -17
  157. package/dist/adapters/node.mjs +0 -69
  158. package/dist/allow.mjs +0 -63
  159. package/dist/client.d.mts +0 -462
  160. package/dist/client.mjs +0 -284
  161. package/dist/core.d.mts +0 -109
  162. package/dist/core.mjs +0 -595
  163. package/dist/error.mjs +0 -237
  164. package/dist/index.d.mts +0 -2
  165. package/dist/index.mjs +0 -3
  166. package/dist/keys.mjs +0 -146
  167. package/dist/mutex.d.mts +0 -44
  168. package/dist/mutex.mjs +0 -110
  169. package/dist/pkce.mjs +0 -157
  170. package/dist/provider/apple.d.mts +0 -110
  171. package/dist/provider/apple.mjs +0 -164
  172. package/dist/provider/code.d.mts +0 -218
  173. package/dist/provider/code.mjs +0 -246
  174. package/dist/provider/discord.d.mts +0 -145
  175. package/dist/provider/discord.mjs +0 -156
  176. package/dist/provider/facebook.d.mts +0 -141
  177. package/dist/provider/facebook.mjs +0 -150
  178. package/dist/provider/github.d.mts +0 -139
  179. package/dist/provider/github.mjs +0 -169
  180. package/dist/provider/gitlab.d.mts +0 -105
  181. package/dist/provider/gitlab.mjs +0 -147
  182. package/dist/provider/google.d.mts +0 -111
  183. package/dist/provider/google.mjs +0 -109
  184. package/dist/provider/linkedin.d.mts +0 -131
  185. package/dist/provider/linkedin.mjs +0 -142
  186. package/dist/provider/magiclink.d.mts +0 -79
  187. package/dist/provider/magiclink.mjs +0 -143
  188. package/dist/provider/microsoft.d.mts +0 -177
  189. package/dist/provider/microsoft.mjs +0 -177
  190. package/dist/provider/oauth2.d.mts +0 -175
  191. package/dist/provider/oauth2.mjs +0 -222
  192. package/dist/provider/passkey.d.mts +0 -103
  193. package/dist/provider/passkey.mjs +0 -320
  194. package/dist/provider/password.d.mts +0 -384
  195. package/dist/provider/password.mjs +0 -363
  196. package/dist/provider/provider.d.mts +0 -225
  197. package/dist/provider/provider.mjs +0 -44
  198. package/dist/provider/reddit.d.mts +0 -106
  199. package/dist/provider/reddit.mjs +0 -127
  200. package/dist/provider/slack.d.mts +0 -113
  201. package/dist/provider/slack.mjs +0 -138
  202. package/dist/provider/spotify.d.mts +0 -112
  203. package/dist/provider/spotify.mjs +0 -135
  204. package/dist/provider/totp.d.mts +0 -111
  205. package/dist/provider/totp.mjs +0 -191
  206. package/dist/provider/twitch.d.mts +0 -107
  207. package/dist/provider/twitch.mjs +0 -131
  208. package/dist/provider/vercel.d.mts +0 -176
  209. package/dist/provider/vercel.mjs +0 -230
  210. package/dist/random.mjs +0 -86
  211. package/dist/revocation.d.mts +0 -54
  212. package/dist/revocation.mjs +0 -63
  213. package/dist/router/context.d.mts +0 -21
  214. package/dist/router/context.mjs +0 -193
  215. package/dist/router/cookies.d.mts +0 -8
  216. package/dist/router/cookies.mjs +0 -13
  217. package/dist/router/index.d.mts +0 -21
  218. package/dist/router/index.mjs +0 -107
  219. package/dist/router/matcher.d.mts +0 -15
  220. package/dist/router/matcher.mjs +0 -76
  221. package/dist/router/middleware/cors.d.mts +0 -15
  222. package/dist/router/middleware/cors.mjs +0 -114
  223. package/dist/router/safe-request.d.mts +0 -52
  224. package/dist/router/safe-request.mjs +0 -160
  225. package/dist/router/types.d.mts +0 -67
  226. package/dist/router/types.mjs +0 -1
  227. package/dist/router/variables.d.mts +0 -12
  228. package/dist/router/variables.mjs +0 -20
  229. package/dist/storage/memory.mjs +0 -125
  230. package/dist/storage/storage.d.mts +0 -179
  231. package/dist/storage/storage.mjs +0 -104
  232. package/dist/storage/turso.mjs +0 -117
  233. package/dist/storage/unstorage.mjs +0 -103
  234. package/dist/subject.d.mts +0 -61
  235. package/dist/subject.mjs +0 -36
  236. package/dist/themes/theme.d.mts +0 -209
  237. package/dist/themes/theme.mjs +0 -120
  238. package/dist/toolkit/client.d.mts +0 -168
  239. package/dist/toolkit/client.mjs +0 -209
  240. package/dist/toolkit/index.d.mts +0 -9
  241. package/dist/toolkit/index.mjs +0 -9
  242. package/dist/toolkit/providers/facebook.d.mts +0 -11
  243. package/dist/toolkit/providers/facebook.mjs +0 -16
  244. package/dist/toolkit/providers/github.d.mts +0 -11
  245. package/dist/toolkit/providers/github.mjs +0 -16
  246. package/dist/toolkit/providers/google.d.mts +0 -11
  247. package/dist/toolkit/providers/google.mjs +0 -20
  248. package/dist/toolkit/providers/strategy.d.mts +0 -40
  249. package/dist/toolkit/providers/strategy.mjs +0 -1
  250. package/dist/toolkit/storage.mjs +0 -157
  251. package/dist/toolkit/utils.mjs +0 -30
  252. package/dist/types.d.mts +0 -94
  253. package/dist/types.mjs +0 -1
  254. package/dist/ui/base.d.mts +0 -29
  255. package/dist/ui/base.mjs +0 -407
  256. package/dist/ui/code.d.mts +0 -42
  257. package/dist/ui/code.mjs +0 -173
  258. package/dist/ui/form.d.mts +0 -31
  259. package/dist/ui/form.mjs +0 -49
  260. package/dist/ui/icon.d.mts +0 -57
  261. package/dist/ui/icon.mjs +0 -247
  262. package/dist/ui/magiclink.d.mts +0 -40
  263. package/dist/ui/magiclink.mjs +0 -152
  264. package/dist/ui/passkey.d.mts +0 -26
  265. package/dist/ui/passkey.mjs +0 -323
  266. package/dist/ui/password.d.mts +0 -41
  267. package/dist/ui/password.mjs +0 -402
  268. package/dist/ui/select.d.mts +0 -33
  269. package/dist/ui/select.mjs +0 -98
  270. package/dist/ui/totp.d.mts +0 -33
  271. package/dist/ui/totp.mjs +0 -270
  272. package/dist/util.mjs +0 -128
@@ -1,246 +0,0 @@
1
- import { generateUnbiasedDigits, timingSafeCompare } from "../random.mjs";
2
-
3
- //#region src/provider/code.ts
4
- /**
5
- * PIN code authentication provider for Draft Auth.
6
- * Supports flexible claim-based authentication via email, phone, or custom identifiers.
7
- *
8
- * ## Quick Setup
9
- *
10
- * ```ts
11
- * import { CodeUI } from "@draftlab/auth/ui/code"
12
- * import { CodeProvider } from "@draftlab/auth/provider/code"
13
- *
14
- * export default issuer({
15
- * providers: {
16
- * code: CodeProvider(
17
- * CodeUI({
18
- * copy: {
19
- * code_info: "We'll send a PIN code to your email"
20
- * },
21
- * sendCode: async (claims, code) => {
22
- * try {
23
- * await sendEmail(claims.email, `Your code: ${code}`)
24
- * } catch {
25
- * return { type: "invalid_claim", key: "delivery", value: "Failed to send code" }
26
- * }
27
- * }
28
- * })
29
- * )
30
- * }
31
- * })
32
- * ```
33
- *
34
- * ## Custom Configuration
35
- *
36
- * ```ts
37
- * const customCodeProvider = CodeProvider({
38
- * length: 4, // 4-digit PIN instead of default 6
39
- * request: async (req, state, form, error) => {
40
- * return new Response(renderCodePage(state, form, error))
41
- * },
42
- * sendCode: async (claims, code) => {
43
- * try {
44
- * if (claims.email) {
45
- * await emailService.send(claims.email, code)
46
- * } else if (claims.phone) {
47
- * await smsService.send(claims.phone, code)
48
- * } else {
49
- * return { type: "invalid_claim", key: "email", value: "Email or phone number is required" }
50
- * }
51
- * } catch {
52
- * return { type: "invalid_claim", key: "delivery", value: "Failed to send code" }
53
- * }
54
- * }
55
- * })
56
- * ```
57
- *
58
- * ## Features
59
- *
60
- * - **Flexible claims**: Support any claim type (email, phone, username, etc.)
61
- * - **Configurable PIN length**: 4-6 digit codes typically
62
- * - **Resend functionality**: Built-in code resend capability
63
- * - **Custom UI**: Full control over the authentication interface
64
- * - **Error handling**: Comprehensive error states for different failure modes
65
- *
66
- * ## Flow States
67
- *
68
- * The provider manages a two-step authentication flow:
69
- *
70
- * 1. **Start**: User enters their claim (email, phone, etc.)
71
- * 2. **Code**: User enters the PIN code sent to their claim
72
- *
73
- * ## User Data
74
- *
75
- * ```ts
76
- * success: async (ctx, value) => {
77
- * if (value.provider === "code") {
78
- * // User's email: value.claims.email
79
- * // User's phone (if provided): value.claims.phone
80
- * // Any other claims collected during the flow
81
- * }
82
- * }
83
- * ```
84
- *
85
- * @packageDocumentation
86
- */
87
- /**
88
- * Creates a PIN code authentication provider.
89
- * Implements a flexible claim-based authentication flow with PIN verification.
90
- *
91
- * @template Claims - Type of claims to collect (email, phone, username, etc.)
92
- * @param config - PIN code provider configuration
93
- * @returns Provider instance implementing PIN code authentication
94
- *
95
- * @example
96
- * ```ts
97
- * // Email-based PIN authentication
98
- * const emailCodeProvider = CodeProvider<{ email: string }>({
99
- * length: 6,
100
- * request: async (req, state, form, error) => {
101
- * if (state.type === 'start') {
102
- * return new Response(renderEmailForm(form?.get('email'), error))
103
- * } else {
104
- * return new Response(renderPinForm(state.claims.email, error, state.resend))
105
- * }
106
- * },
107
- * sendCode: async (claims, code) => {
108
- * if (!claims.email || !isValidEmail(claims.email)) {
109
- * return {
110
- * type: "invalid_claim",
111
- * key: "email",
112
- * value: "Invalid email address"
113
- * }
114
- * }
115
- *
116
- * try {
117
- * await emailService.send(claims.email, `Your verification code: ${code}`)
118
- * } catch {
119
- * return {
120
- * type: "invalid_claim",
121
- * key: "delivery",
122
- * value: "Failed to send code"
123
- * }
124
- * }
125
- * }
126
- * })
127
- *
128
- * // Multi-channel PIN authentication (email or phone)
129
- * const flexibleCodeProvider = CodeProvider<{ email?: string; phone?: string }>({
130
- * length: 4,
131
- * request: async (req, state, form, error) => {
132
- * if (state.type === 'start') {
133
- * return new Response(renderContactForm(form, error))
134
- * } else {
135
- * const contact = state.claims.email || state.claims.phone
136
- * return new Response(renderPinForm(contact, error))
137
- * }
138
- * },
139
- * sendCode: async (claims, code) => {
140
- * try {
141
- * if (claims.email) {
142
- * await emailService.send(claims.email, `PIN: ${code}`)
143
- * } else if (claims.phone) {
144
- * await smsService.send(claims.phone, `PIN: ${code}`)
145
- * } else {
146
- * return {
147
- * type: "invalid_claim",
148
- * key: "email",
149
- * value: "Provide either email or phone number"
150
- * }
151
- * }
152
- * } catch {
153
- * return {
154
- * type: "invalid_claim",
155
- * key: "delivery",
156
- * value: "Failed to send code"
157
- * }
158
- * }
159
- * }
160
- * })
161
- *
162
- * // Usage in issuer
163
- * export default issuer({
164
- * providers: {
165
- * email: emailCodeProvider,
166
- * flexible: flexibleCodeProvider
167
- * },
168
- * success: async (ctx, value) => {
169
- * if (value.provider === "code") {
170
- * const email = value.claims.email
171
- * const phone = value.claims.phone
172
- *
173
- * // Look up or create user based on verified claims
174
- * const userId = await findOrCreateUser({ email, phone })
175
- *
176
- * return ctx.subject("user", { userId, email, phone })
177
- * }
178
- * }
179
- * })
180
- * ```
181
- */
182
- const CodeProvider = (config) => {
183
- const codeLength = config.length || 6;
184
- /**
185
- * Generates a cryptographically secure PIN code.
186
- */
187
- const generateCode = () => {
188
- return generateUnbiasedDigits(codeLength);
189
- };
190
- return {
191
- type: "code",
192
- init(routes, ctx) {
193
- /**
194
- * Transitions between authentication states and renders the appropriate UI.
195
- */
196
- const transition = async (c, nextState, formData, error) => {
197
- await ctx.set(c, "provider", 3600 * 24, nextState);
198
- const response = await config.request(c.request, nextState, formData, error);
199
- return ctx.forward(c, response);
200
- };
201
- /**
202
- * GET /authorize - Display initial claim collection form
203
- */
204
- routes.get("/authorize", (c) => {
205
- return transition(c, { type: "start" });
206
- });
207
- /**
208
- * POST /authorize - Handle form submissions and state transitions
209
- */
210
- routes.post("/authorize", async (c) => {
211
- const formData = await c.formData();
212
- const currentState = await ctx.get(c, "provider");
213
- const action = formData.get("action")?.toString();
214
- if (action === "request" || action === "resend") {
215
- const code = generateCode();
216
- const { action: _, ...claims } = Object.fromEntries(formData);
217
- const sendError = await config.sendCode(claims, code);
218
- if (sendError) return transition(c, { type: "start" }, formData, sendError);
219
- return transition(c, {
220
- type: "code",
221
- resend: action === "resend",
222
- claims,
223
- code
224
- }, formData);
225
- } else if (action === "verify" && currentState?.type === "code") {
226
- const enteredCode = formData.get("code")?.toString();
227
- if (!(currentState.code && enteredCode && timingSafeCompare(currentState.code, enteredCode))) return transition(c, {
228
- ...currentState,
229
- resend: false
230
- }, formData, { type: "invalid_code" });
231
- if (!await ctx.get(c, "authorization")) return transition(c, { type: "start" }, formData, {
232
- type: "invalid_claim",
233
- key: "session",
234
- value: "Authentication session expired"
235
- });
236
- await ctx.unset(c, "provider");
237
- return await ctx.success(c, { claims: currentState.claims });
238
- }
239
- return transition(c, { type: "start" });
240
- });
241
- }
242
- };
243
- };
244
-
245
- //#endregion
246
- export { CodeProvider };
@@ -1,145 +0,0 @@
1
- import { Provider } from "./provider.mjs";
2
- import { Oauth2UserData, Oauth2WrappedConfig } from "./oauth2.mjs";
3
-
4
- //#region src/provider/discord.d.ts
5
- /**
6
- * Configuration options for Discord OAuth 2.0 provider.
7
- * Extends the base OAuth 2.0 configuration with Discord-specific documentation.
8
- */
9
- interface DiscordConfig extends Oauth2WrappedConfig {
10
- /**
11
- * Discord OAuth 2.0 client ID from Discord Developer Portal.
12
- * Found in your Discord application settings.
13
- *
14
- * @example
15
- * ```ts
16
- * {
17
- * clientID: "1234567890123456789"
18
- * }
19
- * ```
20
- */
21
- readonly clientID: string;
22
- /**
23
- * Discord OAuth 2.0 client secret from Discord Developer Portal.
24
- * Keep this secure and never expose it to client-side code.
25
- *
26
- * @example
27
- * ```ts
28
- * {
29
- * clientSecret: process.env.DISCORD_CLIENT_SECRET
30
- * }
31
- * ```
32
- */
33
- readonly clientSecret: string;
34
- /**
35
- * Discord OAuth scopes to request access for.
36
- * Determines what data and actions your app can access.
37
- *
38
- * @example
39
- * ```ts
40
- * {
41
- * scopes: [
42
- * "identify", // Basic user information
43
- * "email", // Email address
44
- * "guilds", // User's Discord servers
45
- * "connections" // Connected accounts (Steam, etc.)
46
- * ]
47
- * }
48
- * ```
49
- */
50
- readonly scopes: string[];
51
- /**
52
- * Additional query parameters for Discord OAuth authorization.
53
- * Useful for Discord-specific options like permissions.
54
- *
55
- * @example
56
- * ```ts
57
- * {
58
- * query: {
59
- * permissions: "8", // Administrator permission
60
- * guild_id: "123456789", // Pre-select specific guild
61
- * disable_guild_select: "true" // Disable guild selection
62
- * }
63
- * }
64
- * ```
65
- */
66
- readonly query?: Record<string, string>;
67
- }
68
- /**
69
- * Creates a Discord OAuth 2.0 authentication provider.
70
- * Use this when you need access tokens to call Discord APIs on behalf of the user.
71
- *
72
- * @param config - Discord OAuth 2.0 configuration
73
- * @returns OAuth 2.0 provider configured for Discord
74
- *
75
- * @example
76
- * ```ts
77
- * // Basic Discord authentication
78
- * const basicDiscord = DiscordProvider({
79
- * clientID: process.env.DISCORD_CLIENT_ID,
80
- * clientSecret: process.env.DISCORD_CLIENT_SECRET
81
- * })
82
- *
83
- * // Discord with specific scopes
84
- * const discordWithScopes = DiscordProvider({
85
- * clientID: process.env.DISCORD_CLIENT_ID,
86
- * clientSecret: process.env.DISCORD_CLIENT_SECRET,
87
- * scopes: [
88
- * "identify",
89
- * "email",
90
- * "guilds",
91
- * "connections"
92
- * ]
93
- * })
94
- *
95
- * // Discord bot integration
96
- * const discordBot = DiscordProvider({
97
- * clientID: process.env.DISCORD_CLIENT_ID,
98
- * clientSecret: process.env.DISCORD_CLIENT_SECRET,
99
- * scopes: ["bot", "guilds"],
100
- * query: {
101
- * permissions: "2048" // Send Messages permission
102
- * }
103
- * })
104
- *
105
- * // Using the access token to fetch data
106
- * export default issuer({
107
- * providers: { discord: discordWithScopes },
108
- * success: async (ctx, value) => {
109
- * if (value.provider === "discord") {
110
- * const token = value.tokenset.access
111
- *
112
- * // Get user profile
113
- * const userRes = await fetch('https://discord.com/api/users/@me', {
114
- * headers: { Authorization: `Bearer ${token}` }
115
- * })
116
- * const user = await userRes.json()
117
- *
118
- * // Get user guilds (if guilds scope granted)
119
- * const guildsRes = await fetch('https://discord.com/api/users/@me/guilds', {
120
- * headers: { Authorization: `Bearer ${token}` }
121
- * })
122
- * const guilds = await guildsRes.json()
123
- *
124
- * return ctx.subject("user", {
125
- * discordId: user.id,
126
- * username: user.username,
127
- * discriminator: user.discriminator,
128
- * email: user.email,
129
- * avatar: user.avatar ? `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png` : null,
130
- * guildCount: guilds.length
131
- * })
132
- * }
133
- * }
134
- * })
135
- * ```
136
- *
137
- * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
138
- * - Development: `http://localhost:3000/auth/discord/callback`
139
- * - Production: `https://yourapp.com/auth/discord/callback`
140
- *
141
- * Register this URL in your Discord Developer Portal.
142
- */
143
- declare const DiscordProvider: (config: DiscordConfig) => Provider<Oauth2UserData>;
144
- //#endregion
145
- export { DiscordConfig, DiscordProvider };
@@ -1,156 +0,0 @@
1
- import { Oauth2Provider } from "./oauth2.mjs";
2
-
3
- //#region src/provider/discord.ts
4
- /**
5
- * Discord OAuth 2.0 authentication provider for Draft Auth.
6
- * Provides access tokens for calling Discord APIs on behalf of users.
7
- *
8
- * ## Quick Setup
9
- *
10
- * ```ts
11
- * import { DiscordProvider } from "@draftlab/auth/provider/discord"
12
- *
13
- * export default issuer({
14
- * basePath: "/auth", // Important for callback URL
15
- * providers: {
16
- * discord: DiscordProvider({
17
- * clientID: process.env.DISCORD_CLIENT_ID,
18
- * clientSecret: process.env.DISCORD_CLIENT_SECRET,
19
- * scopes: ["identify", "email", "guilds"]
20
- * })
21
- * }
22
- * })
23
- * ```
24
- *
25
- * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
26
- * - Development: `http://localhost:3000/auth/discord/callback`
27
- * - Production: `https://yourapp.com/auth/discord/callback`
28
- *
29
- * Register this URL in your Discord Developer Portal.
30
- *
31
- * ## Common Scopes
32
- *
33
- * - `identify` - Access to user's basic account information
34
- * - `email` - Access to user's email address
35
- * - `guilds` - Access to user's guilds (servers)
36
- * - `guilds.join` - Ability to join user to guilds
37
- * - `gdm.join` - Ability to join user to group DMs
38
- * - `connections` - Access to user's connections (Steam, YouTube, etc.)
39
- * - `guilds.members.read` - Read guild member information
40
- * - `bot` - For bot applications (requires additional setup)
41
- *
42
- * ## User Data Access
43
- *
44
- * ```ts
45
- * success: async (ctx, value) => {
46
- * if (value.provider === "discord") {
47
- * const accessToken = value.tokenset.access
48
- *
49
- * // Fetch user information
50
- * const userResponse = await fetch('https://discord.com/api/users/@me', {
51
- * headers: { Authorization: `Bearer ${accessToken}` }
52
- * })
53
- * const user = await userResponse.json()
54
- *
55
- * // Fetch user guilds (requires guilds scope)
56
- * const guildsResponse = await fetch('https://discord.com/api/users/@me/guilds', {
57
- * headers: { Authorization: `Bearer ${accessToken}` }
58
- * })
59
- * const guilds = await guildsResponse.json()
60
- *
61
- * // User info: user.username + user.discriminator
62
- * // Avatar: `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png`
63
- * }
64
- * }
65
- * ```
66
- *
67
- * @packageDocumentation
68
- */
69
- /**
70
- * Creates a Discord OAuth 2.0 authentication provider.
71
- * Use this when you need access tokens to call Discord APIs on behalf of the user.
72
- *
73
- * @param config - Discord OAuth 2.0 configuration
74
- * @returns OAuth 2.0 provider configured for Discord
75
- *
76
- * @example
77
- * ```ts
78
- * // Basic Discord authentication
79
- * const basicDiscord = DiscordProvider({
80
- * clientID: process.env.DISCORD_CLIENT_ID,
81
- * clientSecret: process.env.DISCORD_CLIENT_SECRET
82
- * })
83
- *
84
- * // Discord with specific scopes
85
- * const discordWithScopes = DiscordProvider({
86
- * clientID: process.env.DISCORD_CLIENT_ID,
87
- * clientSecret: process.env.DISCORD_CLIENT_SECRET,
88
- * scopes: [
89
- * "identify",
90
- * "email",
91
- * "guilds",
92
- * "connections"
93
- * ]
94
- * })
95
- *
96
- * // Discord bot integration
97
- * const discordBot = DiscordProvider({
98
- * clientID: process.env.DISCORD_CLIENT_ID,
99
- * clientSecret: process.env.DISCORD_CLIENT_SECRET,
100
- * scopes: ["bot", "guilds"],
101
- * query: {
102
- * permissions: "2048" // Send Messages permission
103
- * }
104
- * })
105
- *
106
- * // Using the access token to fetch data
107
- * export default issuer({
108
- * providers: { discord: discordWithScopes },
109
- * success: async (ctx, value) => {
110
- * if (value.provider === "discord") {
111
- * const token = value.tokenset.access
112
- *
113
- * // Get user profile
114
- * const userRes = await fetch('https://discord.com/api/users/@me', {
115
- * headers: { Authorization: `Bearer ${token}` }
116
- * })
117
- * const user = await userRes.json()
118
- *
119
- * // Get user guilds (if guilds scope granted)
120
- * const guildsRes = await fetch('https://discord.com/api/users/@me/guilds', {
121
- * headers: { Authorization: `Bearer ${token}` }
122
- * })
123
- * const guilds = await guildsRes.json()
124
- *
125
- * return ctx.subject("user", {
126
- * discordId: user.id,
127
- * username: user.username,
128
- * discriminator: user.discriminator,
129
- * email: user.email,
130
- * avatar: user.avatar ? `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png` : null,
131
- * guildCount: guilds.length
132
- * })
133
- * }
134
- * }
135
- * })
136
- * ```
137
- *
138
- * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
139
- * - Development: `http://localhost:3000/auth/discord/callback`
140
- * - Production: `https://yourapp.com/auth/discord/callback`
141
- *
142
- * Register this URL in your Discord Developer Portal.
143
- */
144
- const DiscordProvider = (config) => {
145
- return Oauth2Provider({
146
- ...config,
147
- type: "discord",
148
- endpoint: {
149
- authorization: "https://discord.com/oauth2/authorize",
150
- token: "https://discord.com/api/oauth2/token"
151
- }
152
- });
153
- };
154
-
155
- //#endregion
156
- export { DiscordProvider };
@@ -1,141 +0,0 @@
1
- import { Provider } from "./provider.mjs";
2
- import { Oauth2UserData, Oauth2WrappedConfig } from "./oauth2.mjs";
3
-
4
- //#region src/provider/facebook.d.ts
5
- /**
6
- * Configuration options for Facebook OAuth 2.0 provider.
7
- * Extends the base OAuth 2.0 configuration with Facebook-specific documentation.
8
- */
9
- interface FacebookConfig extends Oauth2WrappedConfig {
10
- /**
11
- * Facebook App ID from your Facebook App Dashboard.
12
- * This is the public identifier for your Facebook application.
13
- *
14
- * @example
15
- * ```ts
16
- * {
17
- * clientID: "1234567890123456"
18
- * }
19
- * ```
20
- */
21
- readonly clientID: string;
22
- /**
23
- * Facebook App Secret from your Facebook App Dashboard.
24
- * Keep this secure and never expose it to client-side code.
25
- *
26
- * @example
27
- * ```ts
28
- * {
29
- * clientSecret: process.env.FACEBOOK_APP_SECRET
30
- * }
31
- * ```
32
- */
33
- readonly clientSecret: string;
34
- /**
35
- * Facebook permissions to request during login.
36
- * Determines what data your app can access from the user's Facebook account.
37
- *
38
- * @example
39
- * ```ts
40
- * {
41
- * scopes: [
42
- * "email", // User's email address
43
- * "public_profile", // Basic profile info
44
- * "user_friends", // User's friends list
45
- * "user_posts" // User's timeline posts
46
- * ]
47
- * }
48
- * ```
49
- */
50
- readonly scopes: string[];
51
- /**
52
- * Additional query parameters for Facebook OAuth authorization.
53
- * Useful for Facebook-specific options like response type or display mode.
54
- *
55
- * @example
56
- * ```ts
57
- * {
58
- * query: {
59
- * display: "popup", // Show login in popup
60
- * auth_type: "rerequest", // Force permission re-request
61
- * state: "custom-state" // Custom state parameter
62
- * }
63
- * }
64
- * ```
65
- */
66
- readonly query?: Record<string, string>;
67
- }
68
- /**
69
- * Creates a Facebook OAuth 2.0 authentication provider.
70
- * Use this when you need access tokens to call Facebook Graph API on behalf of the user.
71
- *
72
- * @param config - Facebook OAuth 2.0 configuration
73
- * @returns OAuth 2.0 provider configured for Facebook
74
- *
75
- * @example
76
- * ```ts
77
- * // Basic Facebook authentication
78
- * const basicFacebook = FacebookProvider({
79
- * clientID: process.env.FACEBOOK_APP_ID,
80
- * clientSecret: process.env.FACEBOOK_APP_SECRET,
81
- * scopes: ["email", "public_profile"]
82
- * })
83
- *
84
- * // Facebook with extended permissions
85
- * const extendedFacebook = FacebookProvider({
86
- * clientID: process.env.FACEBOOK_APP_ID,
87
- * clientSecret: process.env.FACEBOOK_APP_SECRET,
88
- * scopes: [
89
- * "email",
90
- * "public_profile",
91
- * "user_friends",
92
- * "user_posts",
93
- * "user_photos"
94
- * ],
95
- * query: {
96
- * display: "popup",
97
- * auth_type: "rerequest" // Force permission approval
98
- * }
99
- * })
100
- *
101
- * // Using the access token for Graph API calls
102
- * export default issuer({
103
- * providers: { facebook: extendedFacebook },
104
- * success: async (ctx, value) => {
105
- * if (value.provider === "facebook") {
106
- * const token = value.tokenset.access
107
- *
108
- * // Get user profile with custom fields
109
- * const profileRes = await fetch(
110
- * `https://graph.facebook.com/me?fields=id,name,email,picture.width(200),friends&access_token=${token}`
111
- * )
112
- * const profile = await profileRes.json()
113
- *
114
- * // Get user's posts (if permission granted)
115
- * const postsRes = await fetch(
116
- * `https://graph.facebook.com/me/posts?access_token=${token}`
117
- * )
118
- * const posts = await postsRes.json()
119
- *
120
- * return ctx.subject("user", {
121
- * facebookId: profile.id,
122
- * name: profile.name,
123
- * email: profile.email,
124
- * picture: profile.picture?.data?.url,
125
- * friendsCount: profile.friends?.summary?.total_count || 0,
126
- * postsCount: posts.data?.length || 0
127
- * })
128
- * }
129
- * }
130
- * })
131
- * ```
132
- *
133
- * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
134
- * - Development: `http://localhost:3000/auth/facebook/callback`
135
- * - Production: `https://yourapp.com/auth/facebook/callback`
136
- *
137
- * Register this URL in your Facebook App Dashboard.
138
- */
139
- declare const FacebookProvider: (config: FacebookConfig) => Provider<Oauth2UserData>;
140
- //#endregion
141
- export { FacebookConfig, FacebookProvider };