@better-auth/core 1.5.0-beta.2 → 1.5.0-beta.20

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 (331) hide show
  1. package/LICENSE.md +15 -12
  2. package/README.md +17 -0
  3. package/dist/api/index.d.mts +280 -2
  4. package/dist/api/index.mjs +4 -2
  5. package/dist/api/index.mjs.map +1 -0
  6. package/dist/async_hooks/index.d.mts +2 -1
  7. package/dist/async_hooks/index.mjs +2 -1
  8. package/dist/async_hooks/index.mjs.map +1 -0
  9. package/dist/async_hooks/pure.index.d.mts +2 -1
  10. package/dist/async_hooks/pure.index.mjs +2 -1
  11. package/dist/async_hooks/pure.index.mjs.map +1 -0
  12. package/dist/context/endpoint-context.d.mts +20 -0
  13. package/dist/context/endpoint-context.mjs +32 -0
  14. package/dist/context/endpoint-context.mjs.map +1 -0
  15. package/dist/context/global.d.mts +7 -0
  16. package/dist/context/global.mjs +38 -0
  17. package/dist/context/global.mjs.map +1 -0
  18. package/dist/context/index.d.mts +5 -53
  19. package/dist/context/index.mjs +5 -2
  20. package/dist/context/request-state.d.mts +28 -0
  21. package/dist/context/request-state.mjs +50 -0
  22. package/dist/context/request-state.mjs.map +1 -0
  23. package/dist/context/transaction.d.mts +25 -0
  24. package/dist/context/transaction.mjs +96 -0
  25. package/dist/context/transaction.mjs.map +1 -0
  26. package/dist/db/adapter/factory.d.mts +20 -0
  27. package/dist/db/adapter/factory.mjs +725 -0
  28. package/dist/db/adapter/factory.mjs.map +1 -0
  29. package/dist/db/adapter/get-default-field-name.d.mts +19 -0
  30. package/dist/db/adapter/get-default-field-name.mjs +39 -0
  31. package/dist/db/adapter/get-default-field-name.mjs.map +1 -0
  32. package/dist/db/adapter/get-default-model-name.d.mts +13 -0
  33. package/dist/db/adapter/get-default-model-name.mjs +33 -0
  34. package/dist/db/adapter/get-default-model-name.mjs.map +1 -0
  35. package/dist/db/adapter/get-field-attributes.d.mts +30 -0
  36. package/dist/db/adapter/get-field-attributes.mjs +40 -0
  37. package/dist/db/adapter/get-field-attributes.mjs.map +1 -0
  38. package/dist/db/adapter/get-field-name.d.mts +19 -0
  39. package/dist/db/adapter/get-field-name.mjs +34 -0
  40. package/dist/db/adapter/get-field-name.mjs.map +1 -0
  41. package/dist/db/adapter/get-id-field.d.mts +40 -0
  42. package/dist/db/adapter/get-id-field.mjs +68 -0
  43. package/dist/db/adapter/get-id-field.mjs.map +1 -0
  44. package/dist/db/adapter/get-model-name.d.mts +13 -0
  45. package/dist/db/adapter/get-model-name.mjs +24 -0
  46. package/dist/db/adapter/get-model-name.mjs.map +1 -0
  47. package/dist/db/adapter/index.d.mts +520 -2
  48. package/dist/db/adapter/index.mjs +27 -972
  49. package/dist/db/adapter/index.mjs.map +1 -0
  50. package/dist/db/adapter/types.d.mts +108 -0
  51. package/dist/db/adapter/utils.d.mts +8 -0
  52. package/dist/db/adapter/utils.mjs +39 -0
  53. package/dist/db/adapter/utils.mjs.map +1 -0
  54. package/dist/db/get-tables.d.mts +9 -0
  55. package/dist/{get-tables-CMc_Emww.mjs → db/get-tables.mjs} +52 -39
  56. package/dist/db/get-tables.mjs.map +1 -0
  57. package/dist/db/index.d.mts +10 -2
  58. package/dist/db/index.mjs +7 -60
  59. package/dist/db/plugin.d.mts +13 -0
  60. package/dist/db/schema/account.d.mts +30 -0
  61. package/dist/db/schema/account.mjs +20 -0
  62. package/dist/db/schema/account.mjs.map +1 -0
  63. package/dist/db/schema/rate-limit.d.mts +20 -0
  64. package/dist/db/schema/rate-limit.mjs +12 -0
  65. package/dist/db/schema/rate-limit.mjs.map +1 -0
  66. package/dist/db/schema/session.d.mts +25 -0
  67. package/dist/db/schema/session.mjs +15 -0
  68. package/dist/db/schema/session.mjs.map +1 -0
  69. package/dist/db/schema/shared.d.mts +11 -0
  70. package/dist/db/schema/shared.mjs +12 -0
  71. package/dist/db/schema/shared.mjs.map +1 -0
  72. package/dist/db/schema/user.d.mts +24 -0
  73. package/dist/db/schema/user.mjs +14 -0
  74. package/dist/db/schema/user.mjs.map +1 -0
  75. package/dist/db/schema/verification.d.mts +23 -0
  76. package/dist/db/schema/verification.mjs +13 -0
  77. package/dist/db/schema/verification.mjs.map +1 -0
  78. package/dist/db/type.d.mts +169 -0
  79. package/dist/env/color-depth.d.mts +5 -0
  80. package/dist/env/color-depth.mjs +89 -0
  81. package/dist/env/color-depth.mjs.map +1 -0
  82. package/dist/env/env-impl.d.mts +33 -0
  83. package/dist/env/env-impl.mjs +83 -0
  84. package/dist/env/env-impl.mjs.map +1 -0
  85. package/dist/env/index.d.mts +4 -2
  86. package/dist/env/index.mjs +3 -1
  87. package/dist/{index-BRBu0-5h.d.mts → env/logger.d.mts} +2 -35
  88. package/dist/env/logger.mjs +82 -0
  89. package/dist/env/logger.mjs.map +1 -0
  90. package/dist/error/codes.d.mts +69 -0
  91. package/dist/{error-C7mY-p0f.mjs → error/codes.mjs} +7 -30
  92. package/dist/error/codes.mjs.map +1 -0
  93. package/dist/error/index.d.mts +6 -187
  94. package/dist/error/index.mjs +29 -4
  95. package/dist/error/index.mjs.map +1 -0
  96. package/dist/index.d.mts +8 -2
  97. package/dist/oauth2/client-credentials-token.d.mts +58 -0
  98. package/dist/oauth2/client-credentials-token.mjs +67 -0
  99. package/dist/oauth2/client-credentials-token.mjs.map +1 -0
  100. package/dist/oauth2/create-authorization-url.d.mts +48 -0
  101. package/dist/oauth2/create-authorization-url.mjs +44 -0
  102. package/dist/oauth2/create-authorization-url.mjs.map +1 -0
  103. package/dist/oauth2/index.d.mts +8 -2
  104. package/dist/oauth2/index.mjs +7 -3
  105. package/dist/oauth2/oauth-provider.d.mts +195 -0
  106. package/dist/oauth2/refresh-access-token.d.mts +56 -0
  107. package/dist/oauth2/refresh-access-token.mjs +76 -0
  108. package/dist/oauth2/refresh-access-token.mjs.map +1 -0
  109. package/dist/oauth2/utils.d.mts +8 -0
  110. package/dist/oauth2/utils.mjs +28 -0
  111. package/dist/oauth2/utils.mjs.map +1 -0
  112. package/dist/oauth2/validate-authorization-code.d.mts +88 -0
  113. package/dist/oauth2/validate-authorization-code.mjs +83 -0
  114. package/dist/oauth2/validate-authorization-code.mjs.map +1 -0
  115. package/dist/oauth2/verify.d.mts +43 -0
  116. package/dist/oauth2/verify.mjs +96 -0
  117. package/dist/oauth2/verify.mjs.map +1 -0
  118. package/dist/social-providers/apple.d.mts +120 -0
  119. package/dist/social-providers/apple.mjs +105 -0
  120. package/dist/social-providers/apple.mjs.map +1 -0
  121. package/dist/social-providers/atlassian.d.mts +73 -0
  122. package/dist/social-providers/atlassian.mjs +84 -0
  123. package/dist/social-providers/atlassian.mjs.map +1 -0
  124. package/dist/social-providers/cognito.d.mts +88 -0
  125. package/dist/social-providers/cognito.mjs +166 -0
  126. package/dist/social-providers/cognito.mjs.map +1 -0
  127. package/dist/social-providers/discord.d.mts +127 -0
  128. package/dist/social-providers/discord.mjs +65 -0
  129. package/dist/social-providers/discord.mjs.map +1 -0
  130. package/dist/social-providers/dropbox.d.mts +72 -0
  131. package/dist/social-providers/dropbox.mjs +76 -0
  132. package/dist/social-providers/dropbox.mjs.map +1 -0
  133. package/dist/social-providers/facebook.d.mts +82 -0
  134. package/dist/social-providers/facebook.mjs +121 -0
  135. package/dist/social-providers/facebook.mjs.map +1 -0
  136. package/dist/social-providers/figma.d.mts +64 -0
  137. package/dist/social-providers/figma.mjs +87 -0
  138. package/dist/social-providers/figma.mjs.map +1 -0
  139. package/dist/social-providers/github.d.mts +105 -0
  140. package/dist/social-providers/github.mjs +97 -0
  141. package/dist/social-providers/github.mjs.map +1 -0
  142. package/dist/social-providers/gitlab.d.mts +126 -0
  143. package/dist/social-providers/gitlab.mjs +83 -0
  144. package/dist/social-providers/gitlab.mjs.map +1 -0
  145. package/dist/social-providers/google.d.mts +100 -0
  146. package/dist/social-providers/google.mjs +113 -0
  147. package/dist/social-providers/google.mjs.map +1 -0
  148. package/dist/social-providers/huggingface.d.mts +86 -0
  149. package/dist/social-providers/huggingface.mjs +76 -0
  150. package/dist/social-providers/huggingface.mjs.map +1 -0
  151. package/dist/social-providers/index.d.mts +1777 -2
  152. package/dist/social-providers/index.mjs +37 -2570
  153. package/dist/social-providers/index.mjs.map +1 -0
  154. package/dist/social-providers/kakao.d.mts +164 -0
  155. package/dist/social-providers/kakao.mjs +73 -0
  156. package/dist/social-providers/kakao.mjs.map +1 -0
  157. package/dist/social-providers/kick.d.mts +76 -0
  158. package/dist/social-providers/kick.mjs +72 -0
  159. package/dist/social-providers/kick.mjs.map +1 -0
  160. package/dist/social-providers/line.d.mts +108 -0
  161. package/dist/social-providers/line.mjs +114 -0
  162. package/dist/social-providers/line.mjs.map +1 -0
  163. package/dist/social-providers/linear.d.mts +71 -0
  164. package/dist/social-providers/linear.mjs +89 -0
  165. package/dist/social-providers/linear.mjs.map +1 -0
  166. package/dist/social-providers/linkedin.d.mts +70 -0
  167. package/dist/social-providers/linkedin.mjs +77 -0
  168. package/dist/social-providers/linkedin.mjs.map +1 -0
  169. package/dist/social-providers/microsoft-entra-id.d.mts +177 -0
  170. package/dist/social-providers/microsoft-entra-id.mjs +140 -0
  171. package/dist/social-providers/microsoft-entra-id.mjs.map +1 -0
  172. package/dist/social-providers/naver.d.mts +95 -0
  173. package/dist/social-providers/naver.mjs +68 -0
  174. package/dist/social-providers/naver.mjs.map +1 -0
  175. package/dist/social-providers/notion.d.mts +67 -0
  176. package/dist/social-providers/notion.mjs +76 -0
  177. package/dist/social-providers/notion.mjs.map +1 -0
  178. package/dist/social-providers/paybin.d.mts +74 -0
  179. package/dist/social-providers/paybin.mjs +86 -0
  180. package/dist/social-providers/paybin.mjs.map +1 -0
  181. package/dist/social-providers/paypal.d.mts +132 -0
  182. package/dist/social-providers/paypal.mjs +145 -0
  183. package/dist/social-providers/paypal.mjs.map +1 -0
  184. package/dist/social-providers/polar.d.mts +77 -0
  185. package/dist/social-providers/polar.mjs +74 -0
  186. package/dist/social-providers/polar.mjs.map +1 -0
  187. package/dist/social-providers/railway.d.mts +68 -0
  188. package/dist/social-providers/railway.mjs +78 -0
  189. package/dist/social-providers/railway.mjs.map +1 -0
  190. package/dist/social-providers/reddit.d.mts +65 -0
  191. package/dist/social-providers/reddit.mjs +84 -0
  192. package/dist/social-providers/reddit.mjs.map +1 -0
  193. package/dist/social-providers/roblox.d.mts +73 -0
  194. package/dist/social-providers/roblox.mjs +60 -0
  195. package/dist/social-providers/roblox.mjs.map +1 -0
  196. package/dist/social-providers/salesforce.d.mts +82 -0
  197. package/dist/social-providers/salesforce.mjs +92 -0
  198. package/dist/social-providers/salesforce.mjs.map +1 -0
  199. package/dist/social-providers/slack.d.mts +86 -0
  200. package/dist/social-providers/slack.mjs +69 -0
  201. package/dist/social-providers/slack.mjs.map +1 -0
  202. package/dist/social-providers/spotify.d.mts +66 -0
  203. package/dist/social-providers/spotify.mjs +72 -0
  204. package/dist/social-providers/spotify.mjs.map +1 -0
  205. package/dist/social-providers/tiktok.d.mts +171 -0
  206. package/dist/social-providers/tiktok.mjs +63 -0
  207. package/dist/social-providers/tiktok.mjs.map +1 -0
  208. package/dist/social-providers/twitch.d.mts +82 -0
  209. package/dist/social-providers/twitch.mjs +79 -0
  210. package/dist/social-providers/twitch.mjs.map +1 -0
  211. package/dist/social-providers/twitter.d.mts +129 -0
  212. package/dist/social-providers/twitter.mjs +88 -0
  213. package/dist/social-providers/twitter.mjs.map +1 -0
  214. package/dist/social-providers/vercel.d.mts +65 -0
  215. package/dist/social-providers/vercel.mjs +62 -0
  216. package/dist/social-providers/vercel.mjs.map +1 -0
  217. package/dist/social-providers/vk.d.mts +73 -0
  218. package/dist/social-providers/vk.mjs +84 -0
  219. package/dist/social-providers/vk.mjs.map +1 -0
  220. package/dist/social-providers/zoom.d.mts +166 -0
  221. package/dist/social-providers/zoom.mjs +73 -0
  222. package/dist/social-providers/zoom.mjs.map +1 -0
  223. package/dist/types/context.d.mts +274 -0
  224. package/dist/types/cookie.d.mts +16 -0
  225. package/dist/types/helper.d.mts +11 -0
  226. package/dist/types/index.d.mts +8 -0
  227. package/dist/types/init-options.d.mts +1298 -0
  228. package/dist/types/plugin-client.d.mts +113 -0
  229. package/dist/types/plugin.d.mts +125 -0
  230. package/dist/utils/db.d.mts +12 -0
  231. package/dist/utils/db.mjs +17 -0
  232. package/dist/utils/db.mjs.map +1 -0
  233. package/dist/utils/deprecate.d.mts +10 -0
  234. package/dist/utils/deprecate.mjs +18 -0
  235. package/dist/utils/deprecate.mjs.map +1 -0
  236. package/dist/utils/{index.d.mts → error-codes.d.mts} +9 -16
  237. package/dist/utils/error-codes.mjs +12 -0
  238. package/dist/utils/error-codes.mjs.map +1 -0
  239. package/dist/utils/id.d.mts +5 -0
  240. package/dist/utils/id.mjs +10 -0
  241. package/dist/utils/id.mjs.map +1 -0
  242. package/dist/utils/ip.d.mts +55 -0
  243. package/dist/utils/ip.mjs +119 -0
  244. package/dist/utils/ip.mjs.map +1 -0
  245. package/dist/utils/json.d.mts +5 -0
  246. package/dist/utils/json.mjs +26 -0
  247. package/dist/utils/json.mjs.map +1 -0
  248. package/dist/utils/string.d.mts +5 -0
  249. package/dist/utils/string.mjs +8 -0
  250. package/dist/utils/string.mjs.map +1 -0
  251. package/dist/utils/url.d.mts +21 -0
  252. package/dist/utils/url.mjs +33 -0
  253. package/dist/utils/url.mjs.map +1 -0
  254. package/package.json +36 -18
  255. package/src/context/endpoint-context.ts +7 -6
  256. package/src/context/global.ts +57 -0
  257. package/src/context/index.ts +2 -0
  258. package/src/context/request-state.ts +7 -6
  259. package/src/context/transaction.ts +77 -14
  260. package/src/db/adapter/factory.ts +54 -86
  261. package/src/db/adapter/get-default-model-name.ts +1 -1
  262. package/src/db/adapter/get-id-field.ts +4 -6
  263. package/src/db/adapter/index.ts +20 -15
  264. package/src/db/adapter/types.ts +2 -41
  265. package/src/db/get-tables.ts +54 -37
  266. package/src/db/index.ts +30 -5
  267. package/src/db/schema/account.ts +16 -3
  268. package/src/db/schema/rate-limit.ts +16 -1
  269. package/src/db/schema/session.ts +15 -3
  270. package/src/db/schema/user.ts +15 -3
  271. package/src/db/schema/verification.ts +16 -3
  272. package/src/db/test/get-tables.test.ts +33 -0
  273. package/src/db/type.ts +154 -1
  274. package/src/env/env-impl.ts +2 -2
  275. package/src/env/logger.ts +1 -1
  276. package/src/error/codes.ts +18 -1
  277. package/src/error/index.ts +2 -3
  278. package/src/oauth2/client-credentials-token.ts +26 -2
  279. package/src/oauth2/create-authorization-url.ts +4 -2
  280. package/src/oauth2/index.ts +3 -0
  281. package/src/oauth2/oauth-provider.ts +7 -1
  282. package/src/oauth2/refresh-access-token.test.ts +90 -0
  283. package/src/oauth2/refresh-access-token.ts +37 -4
  284. package/src/oauth2/validate-authorization-code.ts +55 -29
  285. package/src/oauth2/validate-token.test.ts +229 -0
  286. package/src/social-providers/apple.ts +38 -29
  287. package/src/social-providers/cognito.ts +6 -5
  288. package/src/social-providers/dropbox.ts +1 -1
  289. package/src/social-providers/facebook.ts +3 -3
  290. package/src/social-providers/figma.ts +5 -3
  291. package/src/social-providers/github.ts +26 -4
  292. package/src/social-providers/gitlab.ts +2 -2
  293. package/src/social-providers/google.ts +18 -14
  294. package/src/social-providers/huggingface.ts +1 -1
  295. package/src/social-providers/index.ts +9 -5
  296. package/src/social-providers/kakao.ts +1 -1
  297. package/src/social-providers/line.ts +1 -1
  298. package/src/social-providers/microsoft-entra-id.ts +84 -1
  299. package/src/social-providers/naver.ts +1 -1
  300. package/src/social-providers/notion.ts +1 -1
  301. package/src/social-providers/paybin.ts +1 -5
  302. package/src/social-providers/polar.ts +1 -1
  303. package/src/social-providers/railway.ts +100 -0
  304. package/src/social-providers/tiktok.ts +2 -1
  305. package/src/social-providers/vercel.ts +1 -1
  306. package/src/social-providers/zoom.ts +0 -8
  307. package/src/types/context.ts +241 -132
  308. package/src/types/cookie.ts +6 -4
  309. package/src/types/helper.ts +9 -0
  310. package/src/types/index.ts +19 -2
  311. package/src/types/init-options.ts +301 -186
  312. package/src/types/plugin-client.ts +1 -0
  313. package/src/types/plugin.ts +11 -6
  314. package/src/utils/db.ts +20 -0
  315. package/src/utils/deprecate.test.ts +71 -0
  316. package/src/utils/deprecate.ts +21 -0
  317. package/src/utils/error-codes.ts +12 -9
  318. package/src/utils/ip.test.ts +255 -0
  319. package/src/utils/ip.ts +211 -0
  320. package/src/utils/url.ts +43 -0
  321. package/.turbo/turbo-build.log +0 -43
  322. package/dist/context-DblZrIwO.mjs +0 -114
  323. package/dist/env-DbssmzoK.mjs +0 -245
  324. package/dist/index-BpRqx5_q.d.mts +0 -7833
  325. package/dist/oauth2-BjWM15hm.mjs +0 -326
  326. package/dist/utils/index.mjs +0 -4
  327. package/dist/utils-s65Fz0OM.mjs +0 -47
  328. package/src/utils/index.ts +0 -4
  329. package/tsconfig.json +0 -7
  330. package/tsdown.config.ts +0 -22
  331. package/vitest.config.ts +0 -3
@@ -81,7 +81,7 @@ export const google = (options: GoogleOptions) => {
81
81
  const url = await createAuthorizationURL({
82
82
  id: "google",
83
83
  options,
84
- authorizationEndpoint: "https://accounts.google.com/o/oauth2/auth",
84
+ authorizationEndpoint: "https://accounts.google.com/o/oauth2/v2/auth",
85
85
  scopes: _scopes,
86
86
  state,
87
87
  codeVerifier,
@@ -116,7 +116,7 @@ export const google = (options: GoogleOptions) => {
116
116
  clientKey: options.clientKey,
117
117
  clientSecret: options.clientSecret,
118
118
  },
119
- tokenEndpoint: "https://www.googleapis.com/oauth2/v4/token",
119
+ tokenEndpoint: "https://oauth2.googleapis.com/token",
120
120
  });
121
121
  },
122
122
  async verifyIdToken(token, nonce) {
@@ -130,22 +130,26 @@ export const google = (options: GoogleOptions) => {
130
130
  // Verify JWT integrity
131
131
  // See https://developers.google.com/identity/sign-in/web/backend-auth#verify-the-integrity-of-the-id-token
132
132
 
133
- const { kid, alg: jwtAlg } = decodeProtectedHeader(token);
134
- if (!kid || !jwtAlg) return false;
133
+ try {
134
+ const { kid, alg: jwtAlg } = decodeProtectedHeader(token);
135
+ if (!kid || !jwtAlg) return false;
135
136
 
136
- const publicKey = await getGooglePublicKey(kid);
137
- const { payload: jwtClaims } = await jwtVerify(token, publicKey, {
138
- algorithms: [jwtAlg],
139
- issuer: ["https://accounts.google.com", "accounts.google.com"],
140
- audience: options.clientId,
141
- maxTokenAge: "1h",
142
- });
137
+ const publicKey = await getGooglePublicKey(kid);
138
+ const { payload: jwtClaims } = await jwtVerify(token, publicKey, {
139
+ algorithms: [jwtAlg],
140
+ issuer: ["https://accounts.google.com", "accounts.google.com"],
141
+ audience: options.clientId,
142
+ maxTokenAge: "1h",
143
+ });
144
+
145
+ if (nonce && jwtClaims.nonce !== nonce) {
146
+ return false;
147
+ }
143
148
 
144
- if (nonce && jwtClaims.nonce !== nonce) {
149
+ return true;
150
+ } catch {
145
151
  return false;
146
152
  }
147
-
148
- return true;
149
153
  },
150
154
  async getUserInfo(token) {
151
155
  if (options.getUserInfo) {
@@ -104,7 +104,7 @@ export const huggingface = (options: HuggingFaceOptions) => {
104
104
  return {
105
105
  user: {
106
106
  id: profile.sub,
107
- name: profile.name || profile.preferred_username,
107
+ name: profile.name || profile.preferred_username || "",
108
108
  email: profile.email,
109
109
  image: profile.picture,
110
110
  emailVerified: profile.email_verified ?? false,
@@ -1,4 +1,5 @@
1
1
  import * as z from "zod";
2
+ import type { AwaitableFunction } from "../types";
2
3
  import { apple } from "./apple";
3
4
  import { atlassian } from "./atlassian";
4
5
  import { cognito } from "./cognito";
@@ -21,6 +22,7 @@ import { notion } from "./notion";
21
22
  import { paybin } from "./paybin";
22
23
  import { paypal } from "./paypal";
23
24
  import { polar } from "./polar";
25
+ import { railway } from "./railway";
24
26
  import { reddit } from "./reddit";
25
27
  import { roblox } from "./roblox";
26
28
  import { salesforce } from "./salesforce";
@@ -66,6 +68,7 @@ export const socialProviders = {
66
68
  paybin,
67
69
  paypal,
68
70
  polar,
71
+ railway,
69
72
  vercel,
70
73
  };
71
74
 
@@ -81,11 +84,11 @@ export const SocialProviderListEnum = z
81
84
  export type SocialProvider = z.infer<typeof SocialProviderListEnum>;
82
85
 
83
86
  export type SocialProviders = {
84
- [K in SocialProviderList[number]]?: Parameters<
85
- (typeof socialProviders)[K]
86
- >[0] & {
87
- enabled?: boolean | undefined;
88
- };
87
+ [K in SocialProviderList[number]]?: AwaitableFunction<
88
+ Parameters<(typeof socialProviders)[K]>[0] & {
89
+ enabled?: boolean | undefined;
90
+ }
91
+ >;
89
92
  };
90
93
 
91
94
  export * from "./apple";
@@ -112,6 +115,7 @@ export * from "./notion";
112
115
  export * from "./paybin";
113
116
  export * from "./paypal";
114
117
  export * from "./polar";
118
+ export * from "./railway";
115
119
  export * from "./reddit";
116
120
  export * from "./roblox";
117
121
  export * from "./salesforce";
@@ -161,7 +161,7 @@ export const kakao = (options: KakaoOptions) => {
161
161
  const kakaoProfile = account.profile || {};
162
162
  const user = {
163
163
  id: String(profile.id),
164
- name: kakaoProfile.nickname || account.name || undefined,
164
+ name: kakaoProfile.nickname || account.name || "",
165
165
  email: account.email,
166
166
  image:
167
167
  kakaoProfile.profile_image_url || kakaoProfile.thumbnail_image_url,
@@ -147,7 +147,7 @@ export const line = (options: LineOptions) => {
147
147
  const userMap = await options.mapProfileToUser?.(profile as any);
148
148
  // ID preference order
149
149
  const id = (profile as any).sub || (profile as any).userId;
150
- const name = (profile as any).name || (profile as any).displayName;
150
+ const name = (profile as any).name || (profile as any).displayName || "";
151
151
  const image =
152
152
  (profile as any).picture || (profile as any).pictureUrl || undefined;
153
153
  const email = (profile as any).email;
@@ -1,7 +1,8 @@
1
1
  import { base64 } from "@better-auth/utils/base64";
2
2
  import { betterFetch } from "@better-fetch/fetch";
3
- import { decodeJwt } from "jose";
3
+ import { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from "jose";
4
4
  import { logger } from "../env";
5
+ import { APIError } from "../error";
5
6
  import type { OAuthProvider, ProviderOptions } from "../oauth2";
6
7
  import {
7
8
  createAuthorizationURL,
@@ -174,6 +175,56 @@ export const microsoft = (options: MicrosoftOptions) => {
174
175
  tokenEndpoint,
175
176
  });
176
177
  },
178
+ async verifyIdToken(token, nonce) {
179
+ if (options.disableIdTokenSignIn) {
180
+ return false;
181
+ }
182
+ if (options.verifyIdToken) {
183
+ return options.verifyIdToken(token, nonce);
184
+ }
185
+
186
+ try {
187
+ const { kid, alg: jwtAlg } = decodeProtectedHeader(token);
188
+ if (!kid || !jwtAlg) return false;
189
+
190
+ const publicKey = await getMicrosoftPublicKey(kid, tenant, authority);
191
+ const verifyOptions: {
192
+ algorithms: [string];
193
+ audience: string;
194
+ maxTokenAge: string;
195
+ issuer?: string;
196
+ } = {
197
+ algorithms: [jwtAlg],
198
+ audience: options.clientId,
199
+ maxTokenAge: "1h",
200
+ };
201
+ /**
202
+ * Issuer varies per user's tenant for multi-tenant endpoints, so only validate for specific tenants.
203
+ * @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints
204
+ */
205
+ if (
206
+ tenant !== "common" &&
207
+ tenant !== "organizations" &&
208
+ tenant !== "consumers"
209
+ ) {
210
+ verifyOptions.issuer = `${authority}/${tenant}/v2.0`;
211
+ }
212
+ const { payload: jwtClaims } = await jwtVerify(
213
+ token,
214
+ publicKey,
215
+ verifyOptions,
216
+ );
217
+
218
+ if (nonce && jwtClaims.nonce !== nonce) {
219
+ return false;
220
+ }
221
+
222
+ return true;
223
+ } catch (error) {
224
+ logger.error("Failed to verify ID token:", error);
225
+ return false;
226
+ }
227
+ },
177
228
  async getUserInfo(token) {
178
229
  if (options.getUserInfo) {
179
230
  return options.getUserInfo(token);
@@ -257,3 +308,35 @@ export const microsoft = (options: MicrosoftOptions) => {
257
308
  options,
258
309
  } satisfies OAuthProvider;
259
310
  };
311
+
312
+ export const getMicrosoftPublicKey = async (
313
+ kid: string,
314
+ tenant: string,
315
+ authority: string,
316
+ ) => {
317
+ const { data } = await betterFetch<{
318
+ keys: Array<{
319
+ kid: string;
320
+ alg: string;
321
+ kty: string;
322
+ use: string;
323
+ n: string;
324
+ e: string;
325
+ x5c?: string[];
326
+ x5t?: string;
327
+ }>;
328
+ }>(`${authority}/${tenant}/discovery/v2.0/keys`);
329
+
330
+ if (!data?.keys) {
331
+ throw new APIError("BAD_REQUEST", {
332
+ message: "Keys not found",
333
+ });
334
+ }
335
+
336
+ const jwk = data.keys.find((key) => key.kid === kid);
337
+ if (!jwk) {
338
+ throw new Error(`JWK with kid ${kid} not found`);
339
+ }
340
+
341
+ return await importJWK(jwk, jwk.alg);
342
+ };
@@ -96,7 +96,7 @@ export const naver = (options: NaverOptions) => {
96
96
  const res = profile.response || {};
97
97
  const user = {
98
98
  id: res.id,
99
- name: res.name || res.nickname,
99
+ name: res.name || res.nickname || "",
100
100
  email: res.email,
101
101
  image: res.profile_image,
102
102
  emailVerified: false,
@@ -94,7 +94,7 @@ export const notion = (options: NotionOptions) => {
94
94
  return {
95
95
  user: {
96
96
  id: userProfile.id,
97
- name: userProfile.name || "Notion User",
97
+ name: userProfile.name || "",
98
98
  email: userProfile.person?.email || null,
99
99
  image: userProfile.avatar_url,
100
100
  emailVerified: false,
@@ -104,11 +104,7 @@ export const paybin = (options: PaybinOptions) => {
104
104
  return {
105
105
  user: {
106
106
  id: user.sub,
107
- name:
108
- user.name ||
109
- user.preferred_username ||
110
- (user.email ? user.email.split("@")[0] : "User") ||
111
- "User",
107
+ name: user.name || user.preferred_username || "",
112
108
  email: user.email,
113
109
  image: user.picture,
114
110
  emailVerified: user.email_verified || false,
@@ -96,7 +96,7 @@ export const polar = (options: PolarOptions) => {
96
96
  return {
97
97
  user: {
98
98
  id: profile.id,
99
- name: profile.public_name || profile.username,
99
+ name: profile.public_name || profile.username || "",
100
100
  email: profile.email,
101
101
  image: profile.avatar_url,
102
102
  emailVerified: profile.email_verified ?? false,
@@ -0,0 +1,100 @@
1
+ import { betterFetch } from "@better-fetch/fetch";
2
+ import type { OAuthProvider, ProviderOptions } from "../oauth2";
3
+ import {
4
+ createAuthorizationURL,
5
+ refreshAccessToken,
6
+ validateAuthorizationCode,
7
+ } from "../oauth2";
8
+
9
+ const authorizationEndpoint = "https://backboard.railway.com/oauth/auth";
10
+ const tokenEndpoint = "https://backboard.railway.com/oauth/token";
11
+ const userinfoEndpoint = "https://backboard.railway.com/oauth/me";
12
+
13
+ export interface RailwayProfile {
14
+ /** The user's unique ID (OAuth `sub` claim). */
15
+ sub: string;
16
+ /** The user's email address. */
17
+ email: string;
18
+ /** The user's display name. */
19
+ name: string;
20
+ /** URL of the user's profile picture. */
21
+ picture: string;
22
+ }
23
+
24
+ export interface RailwayOptions extends ProviderOptions<RailwayProfile> {
25
+ clientId: string;
26
+ }
27
+
28
+ export const railway = (options: RailwayOptions) => {
29
+ return {
30
+ id: "railway",
31
+ name: "Railway",
32
+ createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
33
+ const _scopes = options.disableDefaultScope
34
+ ? []
35
+ : ["openid", "email", "profile"];
36
+ if (options.scope) _scopes.push(...options.scope);
37
+ if (scopes) _scopes.push(...scopes);
38
+ return createAuthorizationURL({
39
+ id: "railway",
40
+ options,
41
+ authorizationEndpoint,
42
+ scopes: _scopes,
43
+ state,
44
+ codeVerifier,
45
+ redirectURI,
46
+ });
47
+ },
48
+ validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
49
+ return validateAuthorizationCode({
50
+ code,
51
+ codeVerifier,
52
+ redirectURI,
53
+ options,
54
+ tokenEndpoint,
55
+ authentication: "basic",
56
+ });
57
+ },
58
+ refreshAccessToken: options.refreshAccessToken
59
+ ? options.refreshAccessToken
60
+ : async (refreshToken) => {
61
+ return refreshAccessToken({
62
+ refreshToken,
63
+ options: {
64
+ clientId: options.clientId,
65
+ clientKey: options.clientKey,
66
+ clientSecret: options.clientSecret,
67
+ },
68
+ tokenEndpoint,
69
+ authentication: "basic",
70
+ });
71
+ },
72
+ async getUserInfo(token) {
73
+ if (options.getUserInfo) {
74
+ return options.getUserInfo(token);
75
+ }
76
+ const { data: profile, error } = await betterFetch<RailwayProfile>(
77
+ userinfoEndpoint,
78
+ { headers: { authorization: `Bearer ${token.accessToken}` } },
79
+ );
80
+ if (error || !profile) {
81
+ return null;
82
+ }
83
+ const userMap = await options.mapProfileToUser?.(profile);
84
+ // Railway does not provide an email_verified claim.
85
+ // We default to false for security consistency.
86
+ return {
87
+ user: {
88
+ id: profile.sub,
89
+ name: profile.name,
90
+ email: profile.email,
91
+ image: profile.picture,
92
+ emailVerified: false,
93
+ ...userMap,
94
+ },
95
+ data: profile,
96
+ };
97
+ },
98
+ options,
99
+ } satisfies OAuthProvider<RailwayProfile>;
100
+ };
@@ -197,7 +197,8 @@ export const tiktok = (options: TiktokOptions) => {
197
197
  user: {
198
198
  email: profile.data.user.email || profile.data.user.username,
199
199
  id: profile.data.user.open_id,
200
- name: profile.data.user.display_name || profile.data.user.username,
200
+ name:
201
+ profile.data.user.display_name || profile.data.user.username || "",
201
202
  image: profile.data.user.avatar_large_url,
202
203
  emailVerified: false,
203
204
  },
@@ -73,7 +73,7 @@ export const vercel = (options: VercelOptions) => {
73
73
  return {
74
74
  user: {
75
75
  id: profile.sub,
76
- name: profile.name ?? profile.preferred_username,
76
+ name: profile.name ?? profile.preferred_username ?? "",
77
77
  email: profile.email,
78
78
  image: profile.picture,
79
79
  emailVerified: profile.email_verified ?? false,
@@ -96,11 +96,6 @@ export interface ZoomProfile extends Record<string, any> {
96
96
  login_types: LoginType[];
97
97
  /** User's personal meeting URL (Example: "example.com") */
98
98
  personal_meeting_url: string;
99
- /** This field has been deprecated and will not be supported in the future.
100
- * Use the phone_numbers field instead of this field.
101
- * The user's phone number (Example: "+1 800000000") */
102
- // @deprecated true
103
- phone_number?: string | undefined;
104
99
  /** The URL for user's profile picture (Example: "example.com") */
105
100
  pic_url: string;
106
101
  /** Personal Meeting ID (PMI) (Example: 3542471135) */
@@ -131,9 +126,6 @@ export interface ZoomProfile extends Record<string, any> {
131
126
  employee_unique_id?: string | undefined;
132
127
  /** The manager for the user (Example: "thill@example.com") */
133
128
  manager?: string | undefined;
134
- /** The user's country for the company phone number (Example: "US")
135
- * @deprecated true */
136
- phone_country?: string | undefined;
137
129
  /** The phone number's ISO country code (Example: "+1") */
138
130
  phone_numbers?: PhoneNumber[] | undefined;
139
131
  /** The user's plan type (Example: "1") */