@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,143 +0,0 @@
1
- import { generateUnbiasedDigits, timingSafeCompare } from "../random.mjs";
2
-
3
- //#region src/provider/magiclink.ts
4
- /**
5
- * Magic Link authentication provider for Draft Auth.
6
- * Sends clickable links that authenticate users in one click.
7
- *
8
- * ## Quick Setup
9
- *
10
- * ```ts
11
- * import { MagicLinkUI } from "@draftlab/auth/ui/magiclink"
12
- * import { MagicLinkProvider } from "@draftlab/auth/provider/magiclink"
13
- *
14
- * export default issuer({
15
- * providers: {
16
- * magiclink: MagicLinkProvider(
17
- * MagicLinkUI({
18
- * sendLink: async (claims, magicUrl) => {
19
- * await emailService.send({
20
- * to: claims.email,
21
- * subject: "Sign in to your account",
22
- * html: `<a href="${magicUrl}">Sign In</a>`
23
- * })
24
- * }
25
- * })
26
- * )
27
- * }
28
- * })
29
- * ```
30
- *
31
- * ## Custom Configuration
32
- *
33
- * ```ts
34
- * const customMagicLink = MagicLinkProvider({
35
- * expiry: 600, // 10 minutes instead of default 15
36
- *
37
- * request: async (req, state, form, error) => {
38
- * return new Response(renderMagicLinkForm(state, form, error))
39
- * },
40
- *
41
- * sendLink: async (claims, magicUrl) => {
42
- * try {
43
- * if (claims.email) {
44
- * await emailService.send(claims.email, {
45
- * subject: "Your secure sign-in link",
46
- * template: "magic-link",
47
- * data: { magicUrl, userEmail: claims.email }
48
- * })
49
- * } else {
50
- * return { type: "invalid_claim", key: "email", value: "Email is required" }
51
- * }
52
- * } catch {
53
- * return { type: "invalid_claim", key: "delivery", value: "Failed to send magic link" }
54
- * }
55
- * }
56
- * })
57
- * ```
58
- *
59
- * @packageDocumentation
60
- */
61
- /**
62
- * Creates a Magic Link authentication provider.
63
- * Implements a flexible claim-based authentication flow with magic link verification.
64
- *
65
- * @template Claims - Type of claims to collect (email, phone, username, etc.)
66
- * @param config - Magic Link provider configuration
67
- * @returns Provider instance implementing magic link authentication
68
- */
69
- const MagicLinkProvider = (config) => {
70
- /**
71
- * Generates a cryptographically secure token.
72
- */
73
- const generateToken = () => {
74
- return generateUnbiasedDigits(32);
75
- };
76
- return {
77
- type: "magiclink",
78
- init(routes, ctx) {
79
- /**
80
- * Transitions between authentication states and renders the appropriate UI.
81
- */
82
- const transition = async (c, nextState, formData, error) => {
83
- await ctx.set(c, "provider", 3600 * 24, nextState);
84
- const response = await config.request(c.request, nextState, formData, error);
85
- return ctx.forward(c, response);
86
- };
87
- /**
88
- * GET /authorize - Display initial claim collection form
89
- */
90
- routes.get("/authorize", async (c) => {
91
- return transition(c, { type: "start" });
92
- });
93
- /**
94
- * POST /authorize - Handle form submissions and state transitions
95
- */
96
- routes.post("/authorize", async (c) => {
97
- const formData = await c.formData();
98
- const action = formData.get("action")?.toString();
99
- if (action === "request" || action === "resend") {
100
- const token = generateToken();
101
- const { action: _, ...claims } = Object.fromEntries(formData);
102
- const baseUrl = new URL(c.request.url).origin;
103
- const magicUrl = new URL(`/auth/${ctx.name}/verify`, baseUrl);
104
- magicUrl.searchParams.set("token", token);
105
- for (const [key, value] of Object.entries(claims)) if (typeof value === "string") magicUrl.searchParams.set(key, value);
106
- const sendError = await config.sendLink(claims, magicUrl.toString());
107
- if (sendError) return transition(c, { type: "start" }, formData, sendError);
108
- return transition(c, {
109
- type: "sent",
110
- resend: action === "resend",
111
- claims,
112
- token
113
- }, formData);
114
- }
115
- return transition(c, { type: "start" });
116
- });
117
- /**
118
- * GET /verify - Handle magic link clicks
119
- */
120
- routes.get("/verify", async (c) => {
121
- const url = new URL(c.request.url);
122
- const token = url.searchParams.get("token");
123
- const storedState = await ctx.get(c, "provider");
124
- if (!token || !storedState || storedState.type !== "sent") return transition(c, { type: "start" }, void 0, { type: "invalid_link" });
125
- if (!timingSafeCompare(storedState.token, token)) return transition(c, { type: "start" }, void 0, { type: "invalid_link" });
126
- const urlClaims = {};
127
- for (const [key, value] of url.searchParams) if (key !== "token" && value) urlClaims[key] = value;
128
- if (!Object.keys(storedState.claims).every((key) => {
129
- const urlValue = urlClaims[key];
130
- const storedValue = storedState.claims[key];
131
- if (!urlValue || !storedValue) return false;
132
- return timingSafeCompare(storedValue, urlValue);
133
- })) return transition(c, { type: "start" }, void 0, { type: "invalid_link" });
134
- if (!await ctx.get(c, "authorization")) return transition(c, { type: "start" }, void 0, { type: "invalid_link" });
135
- await ctx.unset(c, "provider");
136
- return await ctx.success(c, { claims: storedState.claims });
137
- });
138
- }
139
- };
140
- };
141
-
142
- //#endregion
143
- export { MagicLinkProvider };
@@ -1,178 +0,0 @@
1
- import { Provider } from "./provider.mjs";
2
- import { Oauth2UserData, Oauth2WrappedConfig } from "./oauth2.mjs";
3
-
4
- //#region src/provider/microsoft.d.ts
5
-
6
- /**
7
- * Configuration options for Microsoft OAuth 2.0 provider.
8
- * Extends the base OAuth 2.0 configuration with Microsoft-specific documentation.
9
- */
10
- interface MicrosoftConfig extends Oauth2WrappedConfig {
11
- /**
12
- * Microsoft Azure AD tenant ID or tenant type.
13
- * Determines which types of accounts can sign in.
14
- *
15
- * @example
16
- * ```ts
17
- * {
18
- * tenant: "common" // Personal + work/school accounts
19
- * // or
20
- * tenant: "organizations" // Work/school accounts only
21
- * // or
22
- * tenant: "consumers" // Personal accounts only
23
- * // or
24
- * tenant: "12345678-1234-1234-1234-123456789012" // Specific tenant
25
- * }
26
- * ```
27
- */
28
- readonly tenant: string;
29
- /**
30
- * Microsoft OAuth 2.0 client ID from Azure App Registration.
31
- * Found in your Azure portal app registration.
32
- *
33
- * @example
34
- * ```ts
35
- * {
36
- * clientID: "12345678-1234-1234-1234-123456789012"
37
- * }
38
- * ```
39
- */
40
- readonly clientID: string;
41
- /**
42
- * Microsoft OAuth 2.0 client secret from Azure App Registration.
43
- * Keep this secure and never expose it to client-side code.
44
- *
45
- * @example
46
- * ```ts
47
- * {
48
- * clientSecret: process.env.MICROSOFT_CLIENT_SECRET
49
- * }
50
- * ```
51
- */
52
- readonly clientSecret: string;
53
- /**
54
- * Microsoft OAuth scopes to request access for.
55
- * Determines what data and actions your app can access via Microsoft Graph.
56
- *
57
- * @example
58
- * ```ts
59
- * {
60
- * scopes: [
61
- * "openid", // OpenID Connect sign-in
62
- * "profile", // Basic profile
63
- * "email", // Email address
64
- * "User.Read", // Read user profile
65
- * "Mail.Read", // Read user mail
66
- * "Calendars.Read" // Read user calendars
67
- * ]
68
- * }
69
- * ```
70
- */
71
- readonly scopes: string[];
72
- /**
73
- * Additional query parameters for Microsoft OAuth authorization.
74
- * Useful for Microsoft-specific options like domain hints.
75
- *
76
- * @example
77
- * ```ts
78
- * {
79
- * query: {
80
- * domain_hint: "contoso.com", // Pre-fill domain
81
- * login_hint: "user@contoso.com", // Pre-fill username
82
- * prompt: "consent" // Force consent screen
83
- * }
84
- * }
85
- * ```
86
- */
87
- readonly query?: Record<string, string>;
88
- }
89
- /**
90
- * Creates a Microsoft OAuth 2.0 authentication provider.
91
- * Use this when you need access tokens to call Microsoft Graph APIs on behalf of the user.
92
- *
93
- * @param config - Microsoft OAuth 2.0 configuration
94
- * @returns OAuth 2.0 provider configured for Microsoft
95
- *
96
- * @example
97
- * ```ts
98
- * // Basic Microsoft authentication (all account types)
99
- * const basicMicrosoft = MicrosoftProvider({
100
- * tenant: "common",
101
- * clientID: process.env.MICROSOFT_CLIENT_ID,
102
- * clientSecret: process.env.MICROSOFT_CLIENT_SECRET
103
- * })
104
- *
105
- * // Work/school accounts only
106
- * const workMicrosoft = MicrosoftProvider({
107
- * tenant: "organizations",
108
- * clientID: process.env.MICROSOFT_CLIENT_ID,
109
- * clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
110
- * scopes: [
111
- * "openid",
112
- * "profile",
113
- * "email",
114
- * "User.Read",
115
- * "Mail.Read"
116
- * ]
117
- * })
118
- *
119
- * // Specific tenant with advanced scopes
120
- * const enterpriseMicrosoft = MicrosoftProvider({
121
- * tenant: "12345678-1234-1234-1234-123456789012",
122
- * clientID: process.env.MICROSOFT_CLIENT_ID,
123
- * clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
124
- * scopes: [
125
- * "openid",
126
- * "profile",
127
- * "email",
128
- * "User.Read",
129
- * "Directory.Read.All",
130
- * "Sites.Read.All"
131
- * ],
132
- * query: {
133
- * domain_hint: "contoso.com"
134
- * }
135
- * })
136
- *
137
- * // Using the access token to fetch data
138
- * export default issuer({
139
- * providers: { microsoft: workMicrosoft },
140
- * success: async (ctx, value) => {
141
- * if (value.provider === "microsoft") {
142
- * const token = value.tokenset.access
143
- *
144
- * // Get user profile from Microsoft Graph
145
- * const userRes = await fetch('https://graph.microsoft.com/v1.0/me', {
146
- * headers: { Authorization: `Bearer ${token}` }
147
- * })
148
- * const user = await userRes.json()
149
- *
150
- * // Get user's manager (if available)
151
- * const managerRes = await fetch('https://graph.microsoft.com/v1.0/me/manager', {
152
- * headers: { Authorization: `Bearer ${token}` }
153
- * })
154
- * const manager = await managerRes.json()
155
- *
156
- * return ctx.subject("user", {
157
- * microsoftId: user.id,
158
- * displayName: user.displayName,
159
- * email: user.mail || user.userPrincipalName,
160
- * jobTitle: user.jobTitle,
161
- * department: user.department,
162
- * officeLocation: user.officeLocation,
163
- * managerName: manager?.displayName
164
- * })
165
- * }
166
- * }
167
- * })
168
- * ```
169
- *
170
- * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
171
- * - Development: `http://localhost:3000/auth/microsoft/callback`
172
- * - Production: `https://yourapp.com/auth/microsoft/callback`
173
- *
174
- * Register this URL in your Azure Portal App Registration.
175
- */
176
- declare const MicrosoftProvider: (config: MicrosoftConfig) => Provider<Oauth2UserData>;
177
- //#endregion
178
- export { MicrosoftConfig, MicrosoftProvider };
@@ -1,177 +0,0 @@
1
- import { Oauth2Provider } from "./oauth2.mjs";
2
-
3
- //#region src/provider/microsoft.ts
4
- /**
5
- * Microsoft OAuth 2.0 authentication provider for Draft Auth.
6
- * Supports Microsoft personal accounts, work accounts, and Azure AD.
7
- * Provides access tokens for calling Microsoft Graph APIs on behalf of users.
8
- *
9
- * ## Quick Setup
10
- *
11
- * ```ts
12
- * import { MicrosoftProvider } from "@draftlab/auth/provider/microsoft"
13
- *
14
- * export default issuer({
15
- * basePath: "/auth", // Important for callback URL
16
- * providers: {
17
- * microsoft: MicrosoftProvider({
18
- * tenant: "common", // or specific tenant ID
19
- * clientID: process.env.MICROSOFT_CLIENT_ID,
20
- * clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
21
- * scopes: ["openid", "profile", "email", "User.Read"]
22
- * })
23
- * }
24
- * })
25
- * ```
26
- *
27
- * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
28
- * - Development: `http://localhost:3000/auth/microsoft/callback`
29
- * - Production: `https://yourapp.com/auth/microsoft/callback`
30
- *
31
- * Register this URL in your Azure Portal App Registration.
32
- *
33
- * ## Tenant Configuration
34
- *
35
- * - `common` - Both personal and work/school accounts
36
- * - `organizations` - Work/school accounts only
37
- * - `consumers` - Personal Microsoft accounts only
38
- * - `{tenant-id}` - Specific Azure AD tenant only
39
- *
40
- * ## Common Scopes
41
- *
42
- * - `openid` - Basic OpenID Connect sign-in
43
- * - `profile` - User's basic profile information
44
- * - `email` - User's email address
45
- * - `User.Read` - Read user's profile via Microsoft Graph
46
- * - `Mail.Read` - Read user's mail
47
- * - `Calendars.Read` - Read user's calendars
48
- * - `Files.Read` - Read user's files in OneDrive
49
- * - `Sites.Read.All` - Read SharePoint sites
50
- * - `Directory.Read.All` - Read directory data (requires admin consent)
51
- *
52
- * ## User Data Access
53
- *
54
- * ```ts
55
- * success: async (ctx, value) => {
56
- * if (value.provider === "microsoft") {
57
- * const accessToken = value.tokenset.access
58
- *
59
- * // Fetch user profile via Microsoft Graph
60
- * const userResponse = await fetch('https://graph.microsoft.com/v1.0/me', {
61
- * headers: { Authorization: `Bearer ${accessToken}` }
62
- * })
63
- * const user = await userResponse.json()
64
- *
65
- * // Fetch user photo (requires User.Read scope)
66
- * const photoResponse = await fetch('https://graph.microsoft.com/v1.0/me/photo/$value', {
67
- * headers: { Authorization: `Bearer ${accessToken}` }
68
- * })
69
- * const photoBlob = await photoResponse.blob()
70
- *
71
- * // User info: user.displayName, user.mail, user.userPrincipalName
72
- * }
73
- * }
74
- * ```
75
- *
76
- * @packageDocumentation
77
- */
78
- /**
79
- * Creates a Microsoft OAuth 2.0 authentication provider.
80
- * Use this when you need access tokens to call Microsoft Graph APIs on behalf of the user.
81
- *
82
- * @param config - Microsoft OAuth 2.0 configuration
83
- * @returns OAuth 2.0 provider configured for Microsoft
84
- *
85
- * @example
86
- * ```ts
87
- * // Basic Microsoft authentication (all account types)
88
- * const basicMicrosoft = MicrosoftProvider({
89
- * tenant: "common",
90
- * clientID: process.env.MICROSOFT_CLIENT_ID,
91
- * clientSecret: process.env.MICROSOFT_CLIENT_SECRET
92
- * })
93
- *
94
- * // Work/school accounts only
95
- * const workMicrosoft = MicrosoftProvider({
96
- * tenant: "organizations",
97
- * clientID: process.env.MICROSOFT_CLIENT_ID,
98
- * clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
99
- * scopes: [
100
- * "openid",
101
- * "profile",
102
- * "email",
103
- * "User.Read",
104
- * "Mail.Read"
105
- * ]
106
- * })
107
- *
108
- * // Specific tenant with advanced scopes
109
- * const enterpriseMicrosoft = MicrosoftProvider({
110
- * tenant: "12345678-1234-1234-1234-123456789012",
111
- * clientID: process.env.MICROSOFT_CLIENT_ID,
112
- * clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
113
- * scopes: [
114
- * "openid",
115
- * "profile",
116
- * "email",
117
- * "User.Read",
118
- * "Directory.Read.All",
119
- * "Sites.Read.All"
120
- * ],
121
- * query: {
122
- * domain_hint: "contoso.com"
123
- * }
124
- * })
125
- *
126
- * // Using the access token to fetch data
127
- * export default issuer({
128
- * providers: { microsoft: workMicrosoft },
129
- * success: async (ctx, value) => {
130
- * if (value.provider === "microsoft") {
131
- * const token = value.tokenset.access
132
- *
133
- * // Get user profile from Microsoft Graph
134
- * const userRes = await fetch('https://graph.microsoft.com/v1.0/me', {
135
- * headers: { Authorization: `Bearer ${token}` }
136
- * })
137
- * const user = await userRes.json()
138
- *
139
- * // Get user's manager (if available)
140
- * const managerRes = await fetch('https://graph.microsoft.com/v1.0/me/manager', {
141
- * headers: { Authorization: `Bearer ${token}` }
142
- * })
143
- * const manager = await managerRes.json()
144
- *
145
- * return ctx.subject("user", {
146
- * microsoftId: user.id,
147
- * displayName: user.displayName,
148
- * email: user.mail || user.userPrincipalName,
149
- * jobTitle: user.jobTitle,
150
- * department: user.department,
151
- * officeLocation: user.officeLocation,
152
- * managerName: manager?.displayName
153
- * })
154
- * }
155
- * }
156
- * })
157
- * ```
158
- *
159
- * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
160
- * - Development: `http://localhost:3000/auth/microsoft/callback`
161
- * - Production: `https://yourapp.com/auth/microsoft/callback`
162
- *
163
- * Register this URL in your Azure Portal App Registration.
164
- */
165
- const MicrosoftProvider = (config) => {
166
- return Oauth2Provider({
167
- ...config,
168
- type: "microsoft",
169
- endpoint: {
170
- authorization: `https://login.microsoftonline.com/${config.tenant}/oauth2/v2.0/authorize`,
171
- token: `https://login.microsoftonline.com/${config.tenant}/oauth2/v2.0/token`
172
- }
173
- });
174
- };
175
-
176
- //#endregion
177
- export { MicrosoftProvider };
@@ -1,176 +0,0 @@
1
- import { Provider } from "./provider.mjs";
2
-
3
- //#region src/provider/oauth2.d.ts
4
-
5
- /**
6
- * Configuration options for the OAuth 2.0 provider.
7
- */
8
- interface Oauth2Config {
9
- /**
10
- * Provider type identifier for internal use.
11
- * @internal
12
- * @default "oauth2"
13
- */
14
- readonly type?: string;
15
- /**
16
- * The client ID registered with the OAuth 2.0 provider.
17
- * This public identifier is used in authorization requests.
18
- *
19
- * @example
20
- * ```ts
21
- * {
22
- * clientID: "github-app-12345"
23
- * }
24
- * ```
25
- */
26
- readonly clientID: string;
27
- /**
28
- * The client secret for authenticating with the OAuth 2.0 provider.
29
- * This private credential must be kept secure and not exposed to clients.
30
- *
31
- * @example
32
- * ```ts
33
- * {
34
- * clientSecret: process.env.OAUTH_CLIENT_SECRET
35
- * }
36
- * ```
37
- */
38
- readonly clientSecret: string;
39
- /**
40
- * OAuth 2.0 endpoint URLs for the authorization and token flows.
41
- */
42
- readonly endpoint: {
43
- /**
44
- * The authorization endpoint where users are redirected for authentication.
45
- *
46
- * @example "https://github.com/login/oauth/authorize"
47
- */
48
- readonly authorization: string;
49
- /**
50
- * The token endpoint for exchanging authorization codes for access tokens.
51
- *
52
- * @example "https://github.com/login/oauth/access_token"
53
- */
54
- readonly token: string;
55
- /**
56
- * Optional JWKS endpoint for verifying ID tokens.
57
- * Required only if the provider returns ID tokens that need verification.
58
- *
59
- * @example "https://provider.com/.well-known/jwks.json"
60
- */
61
- readonly jwks?: string;
62
- };
63
- /**
64
- * OAuth 2.0 scopes to request during authorization.
65
- * Scopes define the level of access being requested.
66
- *
67
- * @example
68
- * ```ts
69
- * {
70
- * scopes: ["user:email", "read:user", "repo"]
71
- * }
72
- * ```
73
- */
74
- readonly scopes: string[];
75
- /**
76
- * Whether to use PKCE (Proof Key for Code Exchange) for enhanced security.
77
- * Recommended for public clients and required by some providers.
78
- *
79
- * @default false
80
- *
81
- * @example
82
- * ```ts
83
- * {
84
- * pkce: true // Required for Twitter/X, recommended for mobile apps
85
- * }
86
- * ```
87
- */
88
- readonly pkce?: boolean;
89
- /**
90
- * Additional query parameters to include in the authorization request.
91
- * Useful for provider-specific parameters or customizing the auth flow.
92
- *
93
- * @example
94
- * ```ts
95
- * {
96
- * query: {
97
- * access_type: "offline", // Request refresh token
98
- * prompt: "consent", // Force consent screen
99
- * hd: "mycompany.com" // Google Workspace domain
100
- * }
101
- * }
102
- * ```
103
- */
104
- readonly query?: Record<string, string>;
105
- }
106
- /**
107
- * OAuth 2.0 configuration without endpoint-specific fields.
108
- * Used internally for provider wrapping.
109
- * @internal
110
- */
111
- type Oauth2WrappedConfig = Omit<Oauth2Config, "endpoint" | "name">;
112
- /**
113
- * OAuth 2.0 token response containing access tokens and metadata.
114
- * Provides a structured interface for token data with lazy property access.
115
- * @internal
116
- */
117
- interface Oauth2Token {
118
- /** Access token for making authenticated API requests */
119
- readonly access: string;
120
- /** Refresh token for obtaining new access tokens (if provided) */
121
- readonly refresh: string;
122
- /** Token expiration time in seconds (if provided) */
123
- readonly expiry: number;
124
- /** Raw token response from the provider */
125
- readonly raw: Record<string, unknown>;
126
- }
127
- /**
128
- * User data returned by successful OAuth 2.0 authentication.
129
- */
130
- interface Oauth2UserData {
131
- /** Token set containing access token, refresh token, and metadata */
132
- readonly tokenset: Oauth2Token;
133
- /** Client ID used for this authentication */
134
- readonly clientID: string;
135
- }
136
- /**
137
- * Creates an OAuth 2.0 authentication provider.
138
- * Implements the Authorization Code Grant flow with optional PKCE support.
139
- *
140
- * @param config - OAuth 2.0 provider configuration
141
- * @returns Provider instance implementing OAuth 2.0 authentication
142
- *
143
- * @example
144
- * ```ts
145
- * // GitHub provider with basic configuration
146
- * const githubProvider = Oauth2Provider({
147
- * clientID: process.env.GITHUB_CLIENT_ID,
148
- * clientSecret: process.env.GITHUB_CLIENT_SECRET,
149
- * endpoint: {
150
- * authorization: "https://github.com/login/oauth/authorize",
151
- * token: "https://github.com/login/oauth/access_token"
152
- * },
153
- * scopes: ["user:email", "read:user"]
154
- * })
155
- *
156
- * // Provider with PKCE and custom parameters
157
- * const customProvider = Oauth2Provider({
158
- * clientID: "my-client-id",
159
- * clientSecret: "my-client-secret",
160
- * endpoint: {
161
- * authorization: "https://provider.com/oauth/authorize",
162
- * token: "https://provider.com/oauth/token",
163
- * jwks: "https://provider.com/.well-known/jwks.json"
164
- * },
165
- * scopes: ["read", "write"],
166
- * pkce: true,
167
- * query: {
168
- * prompt: "consent",
169
- * access_type: "offline"
170
- * }
171
- * })
172
- * ```
173
- */
174
- declare const Oauth2Provider: (config: Oauth2Config) => Provider<Oauth2UserData>;
175
- //#endregion
176
- export { Oauth2Config, Oauth2Provider, Oauth2Token, Oauth2UserData, Oauth2WrappedConfig };