@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,168 +0,0 @@
1
- import { OAuthStrategy } from "./providers/strategy.mjs";
2
- import { AuthStorage } from "./storage.mjs";
3
-
4
- //#region src/toolkit/client.d.ts
5
- /**
6
- * Configuration for a single OAuth provider.
7
- */
8
- interface ProviderConfig<TStrategy extends OAuthStrategy> {
9
- /** OAuth strategy defining endpoints and defaults */
10
- readonly strategy: TStrategy;
11
- /** OAuth client ID from provider */
12
- readonly clientId: string;
13
- /** OAuth client secret from provider */
14
- readonly clientSecret: string;
15
- /** Redirect URI registered with provider */
16
- readonly redirectUri: string;
17
- /** Optional default scopes for this provider */
18
- readonly scopes?: string[];
19
- }
20
- /**
21
- * Options for initiating OAuth authorization flow.
22
- */
23
- interface AuthorizeOptions {
24
- /** Optional scopes to request (overrides provider defaults) */
25
- readonly scopes?: string[];
26
- /** Optional additional parameters to include in authorization URL */
27
- readonly params?: Record<string, string>;
28
- /** Optional nonce for additional security */
29
- readonly nonce?: string;
30
- }
31
- /**
32
- * Result of successful OAuth callback handling.
33
- */
34
- interface CallbackResult {
35
- /** OAuth provider that was used */
36
- readonly provider: string;
37
- /** Access token from provider */
38
- readonly accessToken: string;
39
- /** Optional refresh token from provider */
40
- readonly refreshToken?: string;
41
- /** Token expiration time in seconds */
42
- readonly expiresIn?: number;
43
- /** Token type (usually "Bearer") */
44
- readonly tokenType?: string;
45
- /** Optional ID token (OpenID Connect) */
46
- readonly idToken?: string;
47
- }
48
- /**
49
- * OAuth 2.0 client configuration.
50
- */
51
- interface OAuthClientConfig<TProviders extends Record<string, ProviderConfig<OAuthStrategy>>> {
52
- /** Provider configurations keyed by provider name */
53
- readonly providers: TProviders;
54
- /** Storage adapter for PKCE state (defaults to sessionStorage in browser) */
55
- readonly storage?: AuthStorage;
56
- }
57
- /**
58
- * OAuth 2.0 client for managing authentication flows.
59
- */
60
- interface OAuthClient<TProviders extends Record<string, ProviderConfig<OAuthStrategy>>> {
61
- /**
62
- * Initiate OAuth authorization flow.
63
- *
64
- * @param provider - Provider name (key from providers config)
65
- * @param options - Authorization options
66
- * @returns Authorization URL to redirect user to
67
- *
68
- * @example
69
- * ```ts
70
- * // Basic usage
71
- * const { url } = await client.authorize('github')
72
- * window.location.href = url
73
- *
74
- * // With custom scopes
75
- * const { url } = await client.authorize('google', {
76
- * scopes: ['openid', 'email', 'profile']
77
- * })
78
- *
79
- * // With additional params
80
- * const { url } = await client.authorize('github', {
81
- * params: { prompt: 'consent' }
82
- * })
83
- * ```
84
- */
85
- authorize(provider: (string & {}) | keyof TProviders, options?: AuthorizeOptions): Promise<{
86
- url: string;
87
- state: string;
88
- }>;
89
- /**
90
- * Handle OAuth callback and exchange code for tokens.
91
- *
92
- * @param callbackUrl - Full callback URL with query parameters
93
- * @returns Token exchange result
94
- *
95
- * @throws {Error} If callback URL is invalid, state mismatch, or token exchange fails
96
- *
97
- * @example
98
- * ```ts
99
- * // Client-side
100
- * const result = await client.handleCallback(window.location.href)
101
- * console.log(result.accessToken, result.provider)
102
- *
103
- * // Server-side (Next.js)
104
- * export async function GET(req: Request) {
105
- * const result = await client.handleCallback(req.url)
106
- * // Store tokens, create session, etc.
107
- * return Response.redirect('/')
108
- * }
109
- * ```
110
- */
111
- handleCallback(callbackUrl: string): Promise<CallbackResult>;
112
- /**
113
- * Get user info from OAuth provider using access token.
114
- *
115
- * @param provider - Provider name
116
- * @param accessToken - Access token from provider
117
- * @returns User info from provider
118
- *
119
- * @example
120
- * ```ts
121
- * const userInfo = await client.getUserInfo('github', accessToken)
122
- * console.log(userInfo.email, userInfo.name)
123
- * ```
124
- */
125
- getUserInfo(provider: (string & {}) | keyof TProviders, accessToken: string): Promise<Record<string, unknown>>;
126
- }
127
- /**
128
- * Creates an OAuth 2.0 client for managing authentication flows.
129
- *
130
- * Supports PKCE (Proof Key for Code Exchange) for enhanced security.
131
- * Works in both client-side (browser) and server-side (Node.js) environments.
132
- *
133
- * @param config - OAuth client configuration
134
- * @returns OAuth client instance
135
- *
136
- * @example
137
- * ```ts
138
- * import { createOAuthClient } from '@draftlab/auth/toolkit/client'
139
- * import { GitHubStrategy, GoogleStrategy } from '@draftlab/auth/toolkit/providers'
140
- *
141
- * const client = createOAuthClient({
142
- * providers: {
143
- * github: {
144
- * strategy: GitHubStrategy,
145
- * clientId: 'YOUR_CLIENT_ID',
146
- * clientSecret: 'YOUR_CLIENT_SECRET',
147
- * redirectUri: 'http://localhost:3000/auth/callback'
148
- * },
149
- * google: {
150
- * strategy: GoogleStrategy,
151
- * clientId: 'YOUR_CLIENT_ID',
152
- * clientSecret: 'YOUR_CLIENT_SECRET',
153
- * redirectUri: 'http://localhost:3000/auth/callback',
154
- * scopes: ['openid', 'email', 'profile']
155
- * }
156
- * }
157
- * })
158
- *
159
- * // Initiate login
160
- * const { url } = await client.authorize('github')
161
- *
162
- * // Handle callback
163
- * const result = await client.handleCallback(callbackUrl)
164
- * ```
165
- */
166
- declare const createOAuthClient: <TProviders extends Record<string, ProviderConfig<OAuthStrategy>>>(config: OAuthClientConfig<TProviders>) => OAuthClient<TProviders>;
167
- //#endregion
168
- export { AuthorizeOptions, CallbackResult, OAuthClient, OAuthClientConfig, ProviderConfig, createOAuthClient };
@@ -1,209 +0,0 @@
1
- import { generatePKCE } from "../pkce.mjs";
2
- import { createSessionStorage } from "./storage.mjs";
3
- import { generateSecureRandom } from "./utils.mjs";
4
-
5
- //#region src/toolkit/client.ts
6
- /**
7
- * Lightweight OAuth 2.0 client toolkit for DraftAuth.
8
- *
9
- * Provides a simple, framework-agnostic way to implement OAuth 2.0 authentication
10
- * with PKCE support. Works in both client-side (SPA) and server-side (Next.js, Remix) environments.
11
- *
12
- * @example
13
- * ```ts
14
- * // Client-side SPA (React, Vue, Solid, etc.)
15
- * import { createOAuthClient } from '@draftlab/auth/toolkit/client'
16
- * import { GitHubStrategy, GoogleStrategy } from '@draftlab/auth/toolkit/providers'
17
- * import { createSessionStorage } from '@draftlab/auth/toolkit/storage'
18
- *
19
- * const client = createOAuthClient({
20
- * providers: {
21
- * github: {
22
- * strategy: GitHubStrategy,
23
- * clientId: 'YOUR_CLIENT_ID',
24
- * clientSecret: 'YOUR_CLIENT_SECRET',
25
- * redirectUri: 'http://localhost:3000/auth/callback'
26
- * },
27
- * google: {
28
- * strategy: GoogleStrategy,
29
- * clientId: 'YOUR_CLIENT_ID',
30
- * clientSecret: 'YOUR_CLIENT_SECRET',
31
- * redirectUri: 'http://localhost:3000/auth/callback'
32
- * }
33
- * },
34
- * storage: createSessionStorage()
35
- * })
36
- *
37
- * // Initiate login
38
- * const { url } = await client.authorize('github', { scopes: ['user:email'] })
39
- * window.location.href = url
40
- *
41
- * // Handle callback
42
- * const result = await client.handleCallback(window.location.href)
43
- * console.log(result.accessToken, result.provider)
44
- * ```
45
- *
46
- * @example
47
- * ```ts
48
- * // Server-side (Next.js App Router)
49
- * import { createOAuthClient } from '@draftlab/auth/toolkit/client'
50
- * import { GitHubStrategy } from '@draftlab/auth/toolkit/providers'
51
- * import { createCookieStorage } from '@draftlab/auth/toolkit/storage'
52
- * import { cookies } from 'next/headers'
53
- *
54
- * export async function GET(req: Request) {
55
- * const client = createOAuthClient({
56
- * providers: {
57
- * github: {
58
- * strategy: GitHubStrategy,
59
- * clientId: process.env.GITHUB_CLIENT_ID!,
60
- * clientSecret: process.env.GITHUB_CLIENT_SECRET!,
61
- * redirectUri: 'https://myapp.com/auth/callback'
62
- * }
63
- * },
64
- * storage: createCookieStorage({
65
- * getCookie: (name) => cookies().get(name)?.value ?? null,
66
- * setCookie: (name, value, opts) => cookies().set(name, value, opts),
67
- * deleteCookie: (name) => cookies().delete(name)
68
- * })
69
- * })
70
- *
71
- * const { url } = await client.authorize('github')
72
- * return Response.redirect(url)
73
- * }
74
- * ```
75
- */
76
- /**
77
- * Creates an OAuth 2.0 client for managing authentication flows.
78
- *
79
- * Supports PKCE (Proof Key for Code Exchange) for enhanced security.
80
- * Works in both client-side (browser) and server-side (Node.js) environments.
81
- *
82
- * @param config - OAuth client configuration
83
- * @returns OAuth client instance
84
- *
85
- * @example
86
- * ```ts
87
- * import { createOAuthClient } from '@draftlab/auth/toolkit/client'
88
- * import { GitHubStrategy, GoogleStrategy } from '@draftlab/auth/toolkit/providers'
89
- *
90
- * const client = createOAuthClient({
91
- * providers: {
92
- * github: {
93
- * strategy: GitHubStrategy,
94
- * clientId: 'YOUR_CLIENT_ID',
95
- * clientSecret: 'YOUR_CLIENT_SECRET',
96
- * redirectUri: 'http://localhost:3000/auth/callback'
97
- * },
98
- * google: {
99
- * strategy: GoogleStrategy,
100
- * clientId: 'YOUR_CLIENT_ID',
101
- * clientSecret: 'YOUR_CLIENT_SECRET',
102
- * redirectUri: 'http://localhost:3000/auth/callback',
103
- * scopes: ['openid', 'email', 'profile']
104
- * }
105
- * }
106
- * })
107
- *
108
- * // Initiate login
109
- * const { url } = await client.authorize('github')
110
- *
111
- * // Handle callback
112
- * const result = await client.handleCallback(callbackUrl)
113
- * ```
114
- */
115
- const createOAuthClient = (config) => {
116
- const storage = config.storage || (typeof sessionStorage !== "undefined" ? createSessionStorage() : null);
117
- if (!storage) throw new Error("No storage adapter provided. Please provide a storage adapter for server-side environments.");
118
- return {
119
- async authorize(provider, options) {
120
- const providerConfig = config.providers[provider];
121
- if (!providerConfig) throw new Error(`Provider '${String(provider)}' not configured`);
122
- const pkce = await generatePKCE();
123
- const state = generateSecureRandom(16);
124
- await storage.set({
125
- state,
126
- verifier: pkce.verifier,
127
- provider: String(provider),
128
- nonce: options?.nonce
129
- });
130
- const scopes = options?.scopes || providerConfig.scopes || providerConfig.strategy.scopes;
131
- const params = new URLSearchParams({
132
- client_id: providerConfig.clientId,
133
- redirect_uri: providerConfig.redirectUri,
134
- response_type: "code",
135
- scope: Array.isArray(scopes) ? scopes.join(" ") : scopes,
136
- state,
137
- code_challenge: pkce.challenge,
138
- code_challenge_method: pkce.method,
139
- ...options?.params
140
- });
141
- return {
142
- url: `${providerConfig.strategy.authorizationEndpoint}?${params.toString()}`,
143
- state
144
- };
145
- },
146
- async handleCallback(callbackUrl) {
147
- const url = new URL(callbackUrl);
148
- const code = url.searchParams.get("code");
149
- const state = url.searchParams.get("state");
150
- const error = url.searchParams.get("error");
151
- const errorDescription = url.searchParams.get("error_description");
152
- if (error) throw new Error(`OAuth error: ${error}${errorDescription ? ` - ${errorDescription}` : ""}`);
153
- if (!code || !state) throw new Error("Invalid callback URL: missing code or state parameter");
154
- const storedState = await storage.get();
155
- await storage.clear();
156
- if (!storedState) throw new Error("No stored PKCE state found. OAuth flow may have expired or been tampered with.");
157
- if (state !== storedState.state) throw new Error("State mismatch. Possible CSRF attack detected.");
158
- const providerConfig = config.providers[storedState.provider];
159
- if (!providerConfig) throw new Error(`Provider '${storedState.provider}' from callback not configured`);
160
- const tokenParams = new URLSearchParams({
161
- grant_type: "authorization_code",
162
- code,
163
- redirect_uri: providerConfig.redirectUri,
164
- client_id: providerConfig.clientId,
165
- client_secret: providerConfig.clientSecret,
166
- code_verifier: storedState.verifier
167
- });
168
- const tokenResponse = await fetch(providerConfig.strategy.tokenEndpoint, {
169
- method: "POST",
170
- headers: {
171
- "Content-Type": "application/x-www-form-urlencoded",
172
- Accept: "application/json"
173
- },
174
- body: tokenParams
175
- });
176
- if (!tokenResponse.ok) {
177
- const errorText = await tokenResponse.text();
178
- throw new Error(`Token exchange failed (${tokenResponse.status}): ${errorText}`);
179
- }
180
- const tokenData = await tokenResponse.json();
181
- if (!tokenData.access_token) throw new Error("No access token in provider response");
182
- return {
183
- provider: storedState.provider,
184
- accessToken: tokenData.access_token,
185
- refreshToken: tokenData.refresh_token,
186
- expiresIn: tokenData.expires_in,
187
- tokenType: tokenData.token_type,
188
- idToken: tokenData.id_token
189
- };
190
- },
191
- async getUserInfo(provider, accessToken) {
192
- const providerConfig = config.providers[provider];
193
- if (!providerConfig) throw new Error(`Provider '${String(provider)}' not configured`);
194
- if (!providerConfig.strategy.userInfoEndpoint) throw new Error(`Provider '${String(provider)}' does not support user info endpoint`);
195
- const response = await fetch(providerConfig.strategy.userInfoEndpoint, { headers: {
196
- Authorization: `Bearer ${accessToken}`,
197
- Accept: "application/json"
198
- } });
199
- if (!response.ok) {
200
- const errorText = await response.text();
201
- throw new Error(`Failed to fetch user info (${response.status}): ${errorText}`);
202
- }
203
- return response.json();
204
- }
205
- };
206
- };
207
-
208
- //#endregion
209
- export { createOAuthClient };
@@ -1,9 +0,0 @@
1
- import { generatePKCE } from "../pkce.mjs";
2
- import { OAuth2TokenResponse, OAuthStrategy } from "./providers/strategy.mjs";
3
- import { AuthStorage, PKCEState, createCookieStorage, createLocalStorage, createMemoryStorage, createSessionStorage } from "./storage.mjs";
4
- import { AuthorizeOptions, CallbackResult, OAuthClient, OAuthClientConfig, ProviderConfig, createOAuthClient } from "./client.mjs";
5
- import { FacebookStrategy } from "./providers/facebook.mjs";
6
- import { GitHubStrategy } from "./providers/github.mjs";
7
- import { GoogleStrategy } from "./providers/google.mjs";
8
- import { generateSecureRandom } from "./utils.mjs";
9
- export { type AuthStorage, type AuthorizeOptions, type CallbackResult, FacebookStrategy, GitHubStrategy, GoogleStrategy, type OAuth2TokenResponse, type OAuthClient, type OAuthClientConfig, type OAuthStrategy, type PKCEState, type ProviderConfig, createCookieStorage, createLocalStorage, createMemoryStorage, createOAuthClient, createSessionStorage, generatePKCE, generateSecureRandom };
@@ -1,9 +0,0 @@
1
- import { generatePKCE } from "../pkce.mjs";
2
- import { createCookieStorage, createLocalStorage, createMemoryStorage, createSessionStorage } from "./storage.mjs";
3
- import { generateSecureRandom } from "./utils.mjs";
4
- import { createOAuthClient } from "./client.mjs";
5
- import { FacebookStrategy } from "./providers/facebook.mjs";
6
- import { GitHubStrategy } from "./providers/github.mjs";
7
- import { GoogleStrategy } from "./providers/google.mjs";
8
-
9
- export { FacebookStrategy, GitHubStrategy, GoogleStrategy, createCookieStorage, createLocalStorage, createMemoryStorage, createOAuthClient, createSessionStorage, generatePKCE, generateSecureRandom };
@@ -1,11 +0,0 @@
1
- import { OAuthStrategy } from "./strategy.mjs";
2
-
3
- //#region src/toolkit/providers/facebook.d.ts
4
- /**
5
- * Facebook OAuth 2.0 strategy.
6
- *
7
- * @see https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow
8
- */
9
- declare const FacebookStrategy: OAuthStrategy;
10
- //#endregion
11
- export { FacebookStrategy };
@@ -1,16 +0,0 @@
1
- //#region src/toolkit/providers/facebook.ts
2
- /**
3
- * Facebook OAuth 2.0 strategy.
4
- *
5
- * @see https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow
6
- */
7
- const FacebookStrategy = {
8
- name: "facebook",
9
- authorizationEndpoint: "https://www.facebook.com/v23.0/dialog/oauth",
10
- tokenEndpoint: "https://graph.facebook.com/v23.0/oauth/access_token",
11
- userInfoEndpoint: "https://graph.facebook.com/me?fields=id,name,email",
12
- scopes: ["public_profile", "email"]
13
- };
14
-
15
- //#endregion
16
- export { FacebookStrategy };
@@ -1,11 +0,0 @@
1
- import { OAuthStrategy } from "./strategy.mjs";
2
-
3
- //#region src/toolkit/providers/github.d.ts
4
- /**
5
- * GitHub OAuth 2.0 strategy.
6
- *
7
- * @see https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps
8
- */
9
- declare const GitHubStrategy: OAuthStrategy;
10
- //#endregion
11
- export { GitHubStrategy };
@@ -1,16 +0,0 @@
1
- //#region src/toolkit/providers/github.ts
2
- /**
3
- * GitHub OAuth 2.0 strategy.
4
- *
5
- * @see https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps
6
- */
7
- const GitHubStrategy = {
8
- name: "github",
9
- authorizationEndpoint: "https://github.com/login/oauth/authorize",
10
- tokenEndpoint: "https://github.com/login/oauth/access_token",
11
- userInfoEndpoint: "https://api.github.com/user",
12
- scopes: ["read:user", "user:email"]
13
- };
14
-
15
- //#endregion
16
- export { GitHubStrategy };
@@ -1,11 +0,0 @@
1
- import { OAuthStrategy } from "./strategy.mjs";
2
-
3
- //#region src/toolkit/providers/google.d.ts
4
- /**
5
- * Google OAuth 2.0 / OpenID Connect strategy.
6
- *
7
- * @see https://developers.google.com/identity/protocols/oauth2
8
- */
9
- declare const GoogleStrategy: OAuthStrategy;
10
- //#endregion
11
- export { GoogleStrategy };
@@ -1,20 +0,0 @@
1
- //#region src/toolkit/providers/google.ts
2
- /**
3
- * Google OAuth 2.0 / OpenID Connect strategy.
4
- *
5
- * @see https://developers.google.com/identity/protocols/oauth2
6
- */
7
- const GoogleStrategy = {
8
- name: "google",
9
- authorizationEndpoint: "https://accounts.google.com/o/oauth2/v2/auth",
10
- tokenEndpoint: "https://oauth2.googleapis.com/token",
11
- userInfoEndpoint: "https://www.googleapis.com/oauth2/v3/userinfo",
12
- scopes: [
13
- "openid",
14
- "email",
15
- "profile"
16
- ]
17
- };
18
-
19
- //#endregion
20
- export { GoogleStrategy };
@@ -1,40 +0,0 @@
1
- //#region src/toolkit/providers/strategy.d.ts
2
- /**
3
- * OAuth 2.0 strategy interface and types for provider configurations.
4
- */
5
- /**
6
- * OAuth 2.0 token response from provider's token endpoint.
7
- * Based on RFC 6749 Section 5.1.
8
- */
9
- interface OAuth2TokenResponse {
10
- /** The access token issued by the authorization server */
11
- access_token: string;
12
- /** The type of token (usually "Bearer") */
13
- token_type?: string;
14
- /** The lifetime in seconds of the access token */
15
- expires_in?: number;
16
- /** The refresh token for obtaining new access tokens */
17
- refresh_token?: string;
18
- /** The scope of the access token (space-separated list) */
19
- scope?: string;
20
- /** OpenID Connect ID token (JWT) */
21
- id_token?: string;
22
- }
23
- /**
24
- * OAuth 2.0 provider strategy definition.
25
- * Defines the endpoints and default configuration for an OAuth provider.
26
- */
27
- interface OAuthStrategy {
28
- /** Provider name (e.g., "github", "google") */
29
- readonly name: string;
30
- /** OAuth authorization endpoint URL */
31
- readonly authorizationEndpoint: string;
32
- /** OAuth token exchange endpoint URL */
33
- readonly tokenEndpoint: string;
34
- /** Optional user info endpoint URL (for OpenID Connect) */
35
- readonly userInfoEndpoint?: string;
36
- /** Default scopes to request */
37
- readonly scopes: string[];
38
- }
39
- //#endregion
40
- export { OAuth2TokenResponse, OAuthStrategy };
@@ -1 +0,0 @@
1
- export { };