@draftlab/auth 0.15.0 → 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 -24
  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 -21
  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 -8
  114. package/dist/types/storage/turso.d.ts.map +1 -0
  115. package/dist/{storage/unstorage.d.mts → types/storage/unstorage.d.ts} +12 -11
  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 -13
  154. package/dist/types/util.d.ts.map +1 -0
  155. package/package.json +10 -16
  156. package/dist/adapters/node.d.mts +0 -18
  157. package/dist/adapters/node.mjs +0 -69
  158. package/dist/allow.mjs +0 -63
  159. package/dist/client.d.mts +0 -456
  160. package/dist/client.mjs +0 -283
  161. package/dist/core.d.mts +0 -110
  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 -111
  171. package/dist/provider/apple.mjs +0 -164
  172. package/dist/provider/code.d.mts +0 -228
  173. package/dist/provider/code.mjs +0 -246
  174. package/dist/provider/discord.d.mts +0 -146
  175. package/dist/provider/discord.mjs +0 -156
  176. package/dist/provider/facebook.d.mts +0 -142
  177. package/dist/provider/facebook.mjs +0 -150
  178. package/dist/provider/github.d.mts +0 -140
  179. package/dist/provider/github.mjs +0 -169
  180. package/dist/provider/gitlab.d.mts +0 -106
  181. package/dist/provider/gitlab.mjs +0 -147
  182. package/dist/provider/google.d.mts +0 -112
  183. package/dist/provider/google.mjs +0 -109
  184. package/dist/provider/linkedin.d.mts +0 -132
  185. package/dist/provider/linkedin.mjs +0 -142
  186. package/dist/provider/magiclink.d.mts +0 -89
  187. package/dist/provider/magiclink.mjs +0 -143
  188. package/dist/provider/microsoft.d.mts +0 -178
  189. package/dist/provider/microsoft.mjs +0 -177
  190. package/dist/provider/oauth2.d.mts +0 -176
  191. package/dist/provider/oauth2.mjs +0 -222
  192. package/dist/provider/passkey.d.mts +0 -104
  193. package/dist/provider/passkey.mjs +0 -320
  194. package/dist/provider/password.d.mts +0 -412
  195. package/dist/provider/password.mjs +0 -363
  196. package/dist/provider/provider.d.mts +0 -227
  197. package/dist/provider/provider.mjs +0 -44
  198. package/dist/provider/reddit.d.mts +0 -107
  199. package/dist/provider/reddit.mjs +0 -127
  200. package/dist/provider/slack.d.mts +0 -114
  201. package/dist/provider/slack.mjs +0 -138
  202. package/dist/provider/spotify.d.mts +0 -113
  203. package/dist/provider/spotify.mjs +0 -135
  204. package/dist/provider/totp.d.mts +0 -112
  205. package/dist/provider/totp.mjs +0 -191
  206. package/dist/provider/twitch.d.mts +0 -108
  207. package/dist/provider/twitch.mjs +0 -131
  208. package/dist/provider/vercel.d.mts +0 -177
  209. package/dist/provider/vercel.mjs +0 -230
  210. package/dist/random.mjs +0 -86
  211. package/dist/revocation.d.mts +0 -55
  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 -62
  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 -169
  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 -12
  243. package/dist/toolkit/providers/facebook.mjs +0 -16
  244. package/dist/toolkit/providers/github.d.mts +0 -12
  245. package/dist/toolkit/providers/github.mjs +0 -16
  246. package/dist/toolkit/providers/google.d.mts +0 -12
  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 -30
  255. package/dist/ui/base.mjs +0 -407
  256. package/dist/ui/code.d.mts +0 -43
  257. package/dist/ui/code.mjs +0 -173
  258. package/dist/ui/form.d.mts +0 -32
  259. package/dist/ui/form.mjs +0 -49
  260. package/dist/ui/icon.d.mts +0 -58
  261. package/dist/ui/icon.mjs +0 -247
  262. package/dist/ui/magiclink.d.mts +0 -41
  263. package/dist/ui/magiclink.mjs +0 -152
  264. package/dist/ui/passkey.d.mts +0 -27
  265. package/dist/ui/passkey.mjs +0 -323
  266. package/dist/ui/password.d.mts +0 -42
  267. package/dist/ui/password.mjs +0 -402
  268. package/dist/ui/select.d.mts +0 -34
  269. package/dist/ui/select.mjs +0 -98
  270. package/dist/ui/totp.d.mts +0 -34
  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,146 +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
- /**
7
- * Configuration options for Discord OAuth 2.0 provider.
8
- * Extends the base OAuth 2.0 configuration with Discord-specific documentation.
9
- */
10
- interface DiscordConfig extends Oauth2WrappedConfig {
11
- /**
12
- * Discord OAuth 2.0 client ID from Discord Developer Portal.
13
- * Found in your Discord application settings.
14
- *
15
- * @example
16
- * ```ts
17
- * {
18
- * clientID: "1234567890123456789"
19
- * }
20
- * ```
21
- */
22
- readonly clientID: string;
23
- /**
24
- * Discord OAuth 2.0 client secret from Discord Developer Portal.
25
- * Keep this secure and never expose it to client-side code.
26
- *
27
- * @example
28
- * ```ts
29
- * {
30
- * clientSecret: process.env.DISCORD_CLIENT_SECRET
31
- * }
32
- * ```
33
- */
34
- readonly clientSecret: string;
35
- /**
36
- * Discord OAuth scopes to request access for.
37
- * Determines what data and actions your app can access.
38
- *
39
- * @example
40
- * ```ts
41
- * {
42
- * scopes: [
43
- * "identify", // Basic user information
44
- * "email", // Email address
45
- * "guilds", // User's Discord servers
46
- * "connections" // Connected accounts (Steam, etc.)
47
- * ]
48
- * }
49
- * ```
50
- */
51
- readonly scopes: string[];
52
- /**
53
- * Additional query parameters for Discord OAuth authorization.
54
- * Useful for Discord-specific options like permissions.
55
- *
56
- * @example
57
- * ```ts
58
- * {
59
- * query: {
60
- * permissions: "8", // Administrator permission
61
- * guild_id: "123456789", // Pre-select specific guild
62
- * disable_guild_select: "true" // Disable guild selection
63
- * }
64
- * }
65
- * ```
66
- */
67
- readonly query?: Record<string, string>;
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
- declare const DiscordProvider: (config: DiscordConfig) => Provider<Oauth2UserData>;
145
- //#endregion
146
- 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,142 +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
- /**
7
- * Configuration options for Facebook OAuth 2.0 provider.
8
- * Extends the base OAuth 2.0 configuration with Facebook-specific documentation.
9
- */
10
- interface FacebookConfig extends Oauth2WrappedConfig {
11
- /**
12
- * Facebook App ID from your Facebook App Dashboard.
13
- * This is the public identifier for your Facebook application.
14
- *
15
- * @example
16
- * ```ts
17
- * {
18
- * clientID: "1234567890123456"
19
- * }
20
- * ```
21
- */
22
- readonly clientID: string;
23
- /**
24
- * Facebook App Secret from your Facebook App Dashboard.
25
- * Keep this secure and never expose it to client-side code.
26
- *
27
- * @example
28
- * ```ts
29
- * {
30
- * clientSecret: process.env.FACEBOOK_APP_SECRET
31
- * }
32
- * ```
33
- */
34
- readonly clientSecret: string;
35
- /**
36
- * Facebook permissions to request during login.
37
- * Determines what data your app can access from the user's Facebook account.
38
- *
39
- * @example
40
- * ```ts
41
- * {
42
- * scopes: [
43
- * "email", // User's email address
44
- * "public_profile", // Basic profile info
45
- * "user_friends", // User's friends list
46
- * "user_posts" // User's timeline posts
47
- * ]
48
- * }
49
- * ```
50
- */
51
- readonly scopes: string[];
52
- /**
53
- * Additional query parameters for Facebook OAuth authorization.
54
- * Useful for Facebook-specific options like response type or display mode.
55
- *
56
- * @example
57
- * ```ts
58
- * {
59
- * query: {
60
- * display: "popup", // Show login in popup
61
- * auth_type: "rerequest", // Force permission re-request
62
- * state: "custom-state" // Custom state parameter
63
- * }
64
- * }
65
- * ```
66
- */
67
- readonly query?: Record<string, string>;
68
- }
69
- /**
70
- * Creates a Facebook OAuth 2.0 authentication provider.
71
- * Use this when you need access tokens to call Facebook Graph API on behalf of the user.
72
- *
73
- * @param config - Facebook OAuth 2.0 configuration
74
- * @returns OAuth 2.0 provider configured for Facebook
75
- *
76
- * @example
77
- * ```ts
78
- * // Basic Facebook authentication
79
- * const basicFacebook = FacebookProvider({
80
- * clientID: process.env.FACEBOOK_APP_ID,
81
- * clientSecret: process.env.FACEBOOK_APP_SECRET,
82
- * scopes: ["email", "public_profile"]
83
- * })
84
- *
85
- * // Facebook with extended permissions
86
- * const extendedFacebook = FacebookProvider({
87
- * clientID: process.env.FACEBOOK_APP_ID,
88
- * clientSecret: process.env.FACEBOOK_APP_SECRET,
89
- * scopes: [
90
- * "email",
91
- * "public_profile",
92
- * "user_friends",
93
- * "user_posts",
94
- * "user_photos"
95
- * ],
96
- * query: {
97
- * display: "popup",
98
- * auth_type: "rerequest" // Force permission approval
99
- * }
100
- * })
101
- *
102
- * // Using the access token for Graph API calls
103
- * export default issuer({
104
- * providers: { facebook: extendedFacebook },
105
- * success: async (ctx, value) => {
106
- * if (value.provider === "facebook") {
107
- * const token = value.tokenset.access
108
- *
109
- * // Get user profile with custom fields
110
- * const profileRes = await fetch(
111
- * `https://graph.facebook.com/me?fields=id,name,email,picture.width(200),friends&access_token=${token}`
112
- * )
113
- * const profile = await profileRes.json()
114
- *
115
- * // Get user's posts (if permission granted)
116
- * const postsRes = await fetch(
117
- * `https://graph.facebook.com/me/posts?access_token=${token}`
118
- * )
119
- * const posts = await postsRes.json()
120
- *
121
- * return ctx.subject("user", {
122
- * facebookId: profile.id,
123
- * name: profile.name,
124
- * email: profile.email,
125
- * picture: profile.picture?.data?.url,
126
- * friendsCount: profile.friends?.summary?.total_count || 0,
127
- * postsCount: posts.data?.length || 0
128
- * })
129
- * }
130
- * }
131
- * })
132
- * ```
133
- *
134
- * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
135
- * - Development: `http://localhost:3000/auth/facebook/callback`
136
- * - Production: `https://yourapp.com/auth/facebook/callback`
137
- *
138
- * Register this URL in your Facebook App Dashboard.
139
- */
140
- declare const FacebookProvider: (config: FacebookConfig) => Provider<Oauth2UserData>;
141
- //#endregion
142
- export { FacebookConfig, FacebookProvider };