@udibo/oauth2 0.1.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 (375) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +174 -0
  3. package/SECURITY.md +77 -0
  4. package/esm/_dnt.polyfills.d.ts +17 -0
  5. package/esm/_dnt.polyfills.js +15 -0
  6. package/esm/adapters/hono/_common.d.ts +66 -0
  7. package/esm/adapters/hono/_common.js +108 -0
  8. package/esm/adapters/hono/authorization-server.d.ts +211 -0
  9. package/esm/adapters/hono/authorization-server.js +214 -0
  10. package/esm/adapters/hono/bff/auth-request-store.d.ts +164 -0
  11. package/esm/adapters/hono/bff/auth-request-store.js +154 -0
  12. package/esm/adapters/hono/bff/bff.d.ts +852 -0
  13. package/esm/adapters/hono/bff/bff.js +1194 -0
  14. package/esm/adapters/hono/bff/cookie-prefix.d.ts +72 -0
  15. package/esm/adapters/hono/bff/cookie-prefix.js +85 -0
  16. package/esm/adapters/hono/bff/mod.d.ts +19 -0
  17. package/esm/adapters/hono/bff/mod.js +19 -0
  18. package/esm/adapters/hono/bff/proxy.d.ts +108 -0
  19. package/esm/adapters/hono/bff/proxy.js +314 -0
  20. package/esm/adapters/hono/bff/session-store.d.ts +250 -0
  21. package/esm/adapters/hono/bff/session-store.js +216 -0
  22. package/esm/adapters/hono/bff/testing.d.ts +165 -0
  23. package/esm/adapters/hono/bff/testing.js +254 -0
  24. package/esm/adapters/hono/identity.d.ts +117 -0
  25. package/esm/adapters/hono/identity.js +215 -0
  26. package/esm/adapters/hono/log.d.ts +49 -0
  27. package/esm/adapters/hono/log.js +66 -0
  28. package/esm/adapters/hono/resource-server.d.ts +101 -0
  29. package/esm/adapters/hono/resource-server.js +108 -0
  30. package/esm/client/_http.d.ts +91 -0
  31. package/esm/client/_http.js +303 -0
  32. package/esm/client/base.d.ts +184 -0
  33. package/esm/client/base.js +93 -0
  34. package/esm/client/bff-client.d.ts +235 -0
  35. package/esm/client/bff-client.js +280 -0
  36. package/esm/client/browser-storage.d.ts +152 -0
  37. package/esm/client/browser-storage.js +246 -0
  38. package/esm/client/check.d.ts +114 -0
  39. package/esm/client/check.js +97 -0
  40. package/esm/client/direct-client.d.ts +707 -0
  41. package/esm/client/direct-client.js +1237 -0
  42. package/esm/client/discovery-cache.d.ts +138 -0
  43. package/esm/client/discovery-cache.js +124 -0
  44. package/esm/client/events.d.ts +54 -0
  45. package/esm/client/events.js +37 -0
  46. package/esm/client/mod.d.ts +35 -0
  47. package/esm/client/mod.js +33 -0
  48. package/esm/client/storage.d.ts +127 -0
  49. package/esm/client/storage.js +81 -0
  50. package/esm/deps/jsr.io/@std/assert/1.0.19/almost_equals.d.ts +29 -0
  51. package/esm/deps/jsr.io/@std/assert/1.0.19/almost_equals.js +47 -0
  52. package/esm/deps/jsr.io/@std/assert/1.0.19/array_includes.d.ts +28 -0
  53. package/esm/deps/jsr.io/@std/assert/1.0.19/array_includes.js +65 -0
  54. package/esm/deps/jsr.io/@std/assert/1.0.19/assert.d.ts +16 -0
  55. package/esm/deps/jsr.io/@std/assert/1.0.19/assert.js +23 -0
  56. package/esm/deps/jsr.io/@std/assert/1.0.19/assertion_error.d.ts +25 -0
  57. package/esm/deps/jsr.io/@std/assert/1.0.19/assertion_error.js +30 -0
  58. package/esm/deps/jsr.io/@std/assert/1.0.19/equal.d.ts +24 -0
  59. package/esm/deps/jsr.io/@std/assert/1.0.19/equal.js +193 -0
  60. package/esm/deps/jsr.io/@std/assert/1.0.19/equals.d.ts +36 -0
  61. package/esm/deps/jsr.io/@std/assert/1.0.19/equals.js +61 -0
  62. package/esm/deps/jsr.io/@std/assert/1.0.19/exists.d.ts +17 -0
  63. package/esm/deps/jsr.io/@std/assert/1.0.19/exists.js +27 -0
  64. package/esm/deps/jsr.io/@std/assert/1.0.19/fail.d.ts +14 -0
  65. package/esm/deps/jsr.io/@std/assert/1.0.19/fail.js +20 -0
  66. package/esm/deps/jsr.io/@std/assert/1.0.19/false.d.ts +18 -0
  67. package/esm/deps/jsr.io/@std/assert/1.0.19/false.js +23 -0
  68. package/esm/deps/jsr.io/@std/assert/1.0.19/greater.d.ts +19 -0
  69. package/esm/deps/jsr.io/@std/assert/1.0.19/greater.js +29 -0
  70. package/esm/deps/jsr.io/@std/assert/1.0.19/greater_or_equal.d.ts +19 -0
  71. package/esm/deps/jsr.io/@std/assert/1.0.19/greater_or_equal.js +29 -0
  72. package/esm/deps/jsr.io/@std/assert/1.0.19/instance_of.d.ts +22 -0
  73. package/esm/deps/jsr.io/@std/assert/1.0.19/instance_of.js +52 -0
  74. package/esm/deps/jsr.io/@std/assert/1.0.19/is_error.d.ts +24 -0
  75. package/esm/deps/jsr.io/@std/assert/1.0.19/is_error.js +53 -0
  76. package/esm/deps/jsr.io/@std/assert/1.0.19/less.d.ts +18 -0
  77. package/esm/deps/jsr.io/@std/assert/1.0.19/less.js +28 -0
  78. package/esm/deps/jsr.io/@std/assert/1.0.19/less_or_equal.d.ts +19 -0
  79. package/esm/deps/jsr.io/@std/assert/1.0.19/less_or_equal.js +29 -0
  80. package/esm/deps/jsr.io/@std/assert/1.0.19/match.d.ts +17 -0
  81. package/esm/deps/jsr.io/@std/assert/1.0.19/match.js +26 -0
  82. package/esm/deps/jsr.io/@std/assert/1.0.19/mod.d.ts +43 -0
  83. package/esm/deps/jsr.io/@std/assert/1.0.19/mod.js +45 -0
  84. package/esm/deps/jsr.io/@std/assert/1.0.19/not_equals.d.ts +26 -0
  85. package/esm/deps/jsr.io/@std/assert/1.0.19/not_equals.js +39 -0
  86. package/esm/deps/jsr.io/@std/assert/1.0.19/not_instance_of.d.ts +19 -0
  87. package/esm/deps/jsr.io/@std/assert/1.0.19/not_instance_of.js +29 -0
  88. package/esm/deps/jsr.io/@std/assert/1.0.19/not_match.d.ts +17 -0
  89. package/esm/deps/jsr.io/@std/assert/1.0.19/not_match.js +26 -0
  90. package/esm/deps/jsr.io/@std/assert/1.0.19/not_strict_equals.d.ts +22 -0
  91. package/esm/deps/jsr.io/@std/assert/1.0.19/not_strict_equals.js +32 -0
  92. package/esm/deps/jsr.io/@std/assert/1.0.19/object_match.d.ts +28 -0
  93. package/esm/deps/jsr.io/@std/assert/1.0.19/object_match.js +177 -0
  94. package/esm/deps/jsr.io/@std/assert/1.0.19/rejects.d.ts +41 -0
  95. package/esm/deps/jsr.io/@std/assert/1.0.19/rejects.js +53 -0
  96. package/esm/deps/jsr.io/@std/assert/1.0.19/strict_equals.d.ts +23 -0
  97. package/esm/deps/jsr.io/@std/assert/1.0.19/strict_equals.js +58 -0
  98. package/esm/deps/jsr.io/@std/assert/1.0.19/string_includes.d.ts +17 -0
  99. package/esm/deps/jsr.io/@std/assert/1.0.19/string_includes.js +26 -0
  100. package/esm/deps/jsr.io/@std/assert/1.0.19/throws.d.ts +44 -0
  101. package/esm/deps/jsr.io/@std/assert/1.0.19/throws.js +44 -0
  102. package/esm/deps/jsr.io/@std/assert/1.0.19/unimplemented.d.ts +14 -0
  103. package/esm/deps/jsr.io/@std/assert/1.0.19/unimplemented.js +20 -0
  104. package/esm/deps/jsr.io/@std/assert/1.0.19/unreachable.d.ts +14 -0
  105. package/esm/deps/jsr.io/@std/assert/1.0.19/unreachable.js +20 -0
  106. package/esm/deps/jsr.io/@std/async/1.5.0/delay.d.ts +44 -0
  107. package/esm/deps/jsr.io/@std/async/1.5.0/delay.js +84 -0
  108. package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.d.ts +39 -0
  109. package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.js +61 -0
  110. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common16.d.ts +22 -0
  111. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common16.js +51 -0
  112. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common32.d.ts +34 -0
  113. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common32.js +192 -0
  114. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common64.d.ts +34 -0
  115. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common64.js +113 -0
  116. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common_detach.d.ts +3 -0
  117. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common_detach.js +13 -0
  118. package/esm/deps/jsr.io/@std/encoding/1.0.11/_types.d.ts +8 -0
  119. package/esm/deps/jsr.io/@std/encoding/1.0.11/_types.js +2 -0
  120. package/esm/deps/jsr.io/@std/encoding/1.0.11/_validate_binary_like.d.ts +1 -0
  121. package/esm/deps/jsr.io/@std/encoding/1.0.11/_validate_binary_like.js +26 -0
  122. package/esm/deps/jsr.io/@std/encoding/1.0.11/ascii85.d.ts +60 -0
  123. package/esm/deps/jsr.io/@std/encoding/1.0.11/ascii85.js +152 -0
  124. package/esm/deps/jsr.io/@std/encoding/1.0.11/base32.d.ts +39 -0
  125. package/esm/deps/jsr.io/@std/encoding/1.0.11/base32.js +87 -0
  126. package/esm/deps/jsr.io/@std/encoding/1.0.11/base58.d.ts +39 -0
  127. package/esm/deps/jsr.io/@std/encoding/1.0.11/base58.js +131 -0
  128. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64.d.ts +39 -0
  129. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64.js +82 -0
  130. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64url.d.ts +39 -0
  131. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64url.js +72 -0
  132. package/esm/deps/jsr.io/@std/encoding/1.0.11/hex.d.ts +38 -0
  133. package/esm/deps/jsr.io/@std/encoding/1.0.11/hex.js +87 -0
  134. package/esm/deps/jsr.io/@std/encoding/1.0.11/mod.d.ts +97 -0
  135. package/esm/deps/jsr.io/@std/encoding/1.0.11/mod.js +99 -0
  136. package/esm/deps/jsr.io/@std/encoding/1.0.11/varint.d.ts +119 -0
  137. package/esm/deps/jsr.io/@std/encoding/1.0.11/varint.js +209 -0
  138. package/esm/deps/jsr.io/@std/http/1.1.3/status.d.ts +343 -0
  139. package/esm/deps/jsr.io/@std/http/1.1.3/status.js +343 -0
  140. package/esm/deps/jsr.io/@std/internal/1.0.14/assertion_state.d.ts +159 -0
  141. package/esm/deps/jsr.io/@std/internal/1.0.14/assertion_state.js +223 -0
  142. package/esm/deps/jsr.io/@std/internal/1.0.14/build_message.d.ts +79 -0
  143. package/esm/deps/jsr.io/@std/internal/1.0.14/build_message.js +116 -0
  144. package/esm/deps/jsr.io/@std/internal/1.0.14/diff.d.ts +139 -0
  145. package/esm/deps/jsr.io/@std/internal/1.0.14/diff.js +277 -0
  146. package/esm/deps/jsr.io/@std/internal/1.0.14/diff_str.d.ts +98 -0
  147. package/esm/deps/jsr.io/@std/internal/1.0.14/diff_str.js +181 -0
  148. package/esm/deps/jsr.io/@std/internal/1.0.14/format.d.ts +29 -0
  149. package/esm/deps/jsr.io/@std/internal/1.0.14/format.js +68 -0
  150. package/esm/deps/jsr.io/@std/internal/1.0.14/styles.d.ts +158 -0
  151. package/esm/deps/jsr.io/@std/internal/1.0.14/styles.js +206 -0
  152. package/esm/deps/jsr.io/@std/internal/1.0.14/types.d.ts +24 -0
  153. package/esm/deps/jsr.io/@std/internal/1.0.14/types.js +3 -0
  154. package/esm/deps/jsr.io/@std/testing/1.0.20/_test_suite.d.ts +91 -0
  155. package/esm/deps/jsr.io/@std/testing/1.0.20/_test_suite.js +347 -0
  156. package/esm/deps/jsr.io/@std/testing/1.0.20/bdd.d.ts +382 -0
  157. package/esm/deps/jsr.io/@std/testing/1.0.20/bdd.js +1110 -0
  158. package/esm/deps/jsr.io/@udibo/http-error/0.11.1/mod.d.ts +363 -0
  159. package/esm/deps/jsr.io/@udibo/http-error/0.11.1/mod.js +616 -0
  160. package/esm/errors.d.ts +203 -0
  161. package/esm/errors.js +287 -0
  162. package/esm/identity/captcha.d.ts +147 -0
  163. package/esm/identity/captcha.js +64 -0
  164. package/esm/identity/delivery.d.ts +96 -0
  165. package/esm/identity/delivery.js +41 -0
  166. package/esm/identity/errors.d.ts +39 -0
  167. package/esm/identity/errors.js +46 -0
  168. package/esm/identity/events.d.ts +242 -0
  169. package/esm/identity/events.js +39 -0
  170. package/esm/identity/external/_shared.d.ts +86 -0
  171. package/esm/identity/external/_shared.js +107 -0
  172. package/esm/identity/external/_token-exchange.d.ts +61 -0
  173. package/esm/identity/external/_token-exchange.js +179 -0
  174. package/esm/identity/external/apple-client-secret.d.ts +82 -0
  175. package/esm/identity/external/apple-client-secret.js +133 -0
  176. package/esm/identity/external/apple.d.ts +64 -0
  177. package/esm/identity/external/apple.js +248 -0
  178. package/esm/identity/external/discord.d.ts +38 -0
  179. package/esm/identity/external/discord.js +62 -0
  180. package/esm/identity/external/errors.d.ts +48 -0
  181. package/esm/identity/external/errors.js +36 -0
  182. package/esm/identity/external/flow.d.ts +107 -0
  183. package/esm/identity/external/flow.js +158 -0
  184. package/esm/identity/external/github.d.ts +42 -0
  185. package/esm/identity/external/github.js +164 -0
  186. package/esm/identity/external/google.d.ts +52 -0
  187. package/esm/identity/external/google.js +38 -0
  188. package/esm/identity/external/mod.d.ts +63 -0
  189. package/esm/identity/external/mod.js +61 -0
  190. package/esm/identity/external/oauth2.d.ts +110 -0
  191. package/esm/identity/external/oauth2.js +158 -0
  192. package/esm/identity/external/oidc.d.ts +81 -0
  193. package/esm/identity/external/oidc.js +250 -0
  194. package/esm/identity/external/provider.d.ts +132 -0
  195. package/esm/identity/external/provider.js +12 -0
  196. package/esm/identity/hibp.d.ts +67 -0
  197. package/esm/identity/hibp.js +87 -0
  198. package/esm/identity/identifier.d.ts +44 -0
  199. package/esm/identity/identifier.js +47 -0
  200. package/esm/identity/lockout.d.ts +155 -0
  201. package/esm/identity/lockout.js +117 -0
  202. package/esm/identity/mfa/mod.d.ts +42 -0
  203. package/esm/identity/mfa/mod.js +42 -0
  204. package/esm/identity/mfa/recovery-codes.d.ts +96 -0
  205. package/esm/identity/mfa/recovery-codes.js +80 -0
  206. package/esm/identity/mfa/service.d.ts +338 -0
  207. package/esm/identity/mfa/service.js +351 -0
  208. package/esm/identity/mfa/totp.d.ts +186 -0
  209. package/esm/identity/mfa/totp.js +194 -0
  210. package/esm/identity/migration.d.ts +155 -0
  211. package/esm/identity/migration.js +243 -0
  212. package/esm/identity/mod.d.ts +65 -0
  213. package/esm/identity/mod.js +64 -0
  214. package/esm/identity/otp.d.ts +255 -0
  215. package/esm/identity/otp.js +245 -0
  216. package/esm/identity/password-policy.d.ts +45 -0
  217. package/esm/identity/password-policy.js +60 -0
  218. package/esm/identity/password.d.ts +171 -0
  219. package/esm/identity/password.js +160 -0
  220. package/esm/identity/rate-limit.d.ts +192 -0
  221. package/esm/identity/rate-limit.js +168 -0
  222. package/esm/identity/service.d.ts +579 -0
  223. package/esm/identity/service.js +835 -0
  224. package/esm/identity/session.d.ts +122 -0
  225. package/esm/identity/session.js +48 -0
  226. package/esm/identity/token-flow.d.ts +214 -0
  227. package/esm/identity/token-flow.js +173 -0
  228. package/esm/models/authentication.d.ts +24 -0
  229. package/esm/models/authentication.js +1 -0
  230. package/esm/models/authorization-code.d.ts +63 -0
  231. package/esm/models/authorization-code.js +1 -0
  232. package/esm/models/authorization.d.ts +165 -0
  233. package/esm/models/authorization.js +160 -0
  234. package/esm/models/client.d.ts +78 -0
  235. package/esm/models/client.js +1 -0
  236. package/esm/models/device-authorization.d.ts +30 -0
  237. package/esm/models/device-authorization.js +1 -0
  238. package/esm/models/responses.d.ts +93 -0
  239. package/esm/models/responses.js +1 -0
  240. package/esm/models/scope.d.ts +81 -0
  241. package/esm/models/scope.js +125 -0
  242. package/esm/models/token.d.ts +135 -0
  243. package/esm/models/token.js +1 -0
  244. package/esm/package.json +3 -0
  245. package/esm/react/callback.d.ts +52 -0
  246. package/esm/react/callback.js +71 -0
  247. package/esm/react/components/class-names.d.ts +91 -0
  248. package/esm/react/components/class-names.js +118 -0
  249. package/esm/react/components/internal.d.ts +62 -0
  250. package/esm/react/components/internal.js +102 -0
  251. package/esm/react/components/mfa-challenge-form.d.ts +66 -0
  252. package/esm/react/components/mfa-challenge-form.js +46 -0
  253. package/esm/react/components/mfa-enrollment-form.d.ts +83 -0
  254. package/esm/react/components/mfa-enrollment-form.js +41 -0
  255. package/esm/react/components/mod.d.ts +103 -0
  256. package/esm/react/components/mod.js +93 -0
  257. package/esm/react/components/request-password-reset-form.d.ts +61 -0
  258. package/esm/react/components/request-password-reset-form.js +41 -0
  259. package/esm/react/components/reset-password-form.d.ts +66 -0
  260. package/esm/react/components/reset-password-form.js +56 -0
  261. package/esm/react/components/sign-in-form.d.ts +74 -0
  262. package/esm/react/components/sign-in-form.js +43 -0
  263. package/esm/react/components/sign-up-form.d.ts +85 -0
  264. package/esm/react/components/sign-up-form.js +57 -0
  265. package/esm/react/components/types.d.ts +208 -0
  266. package/esm/react/components/types.js +14 -0
  267. package/esm/react/components/use-auth-form.d.ts +118 -0
  268. package/esm/react/components/use-auth-form.js +172 -0
  269. package/esm/react/components/user-menu.d.ts +79 -0
  270. package/esm/react/components/user-menu.js +73 -0
  271. package/esm/react/context.d.ts +51 -0
  272. package/esm/react/context.js +16 -0
  273. package/esm/react/mod.d.ts +26 -0
  274. package/esm/react/mod.js +26 -0
  275. package/esm/react/provider.d.ts +40 -0
  276. package/esm/react/provider.js +189 -0
  277. package/esm/react/require-auth.d.ts +31 -0
  278. package/esm/react/require-auth.js +37 -0
  279. package/esm/react/testing.d.ts +322 -0
  280. package/esm/react/testing.js +461 -0
  281. package/esm/react/use-authorization.d.ts +31 -0
  282. package/esm/react/use-authorization.js +36 -0
  283. package/esm/react/use-oauth2.d.ts +112 -0
  284. package/esm/react/use-oauth2.js +127 -0
  285. package/esm/server/authorization-server.d.ts +736 -0
  286. package/esm/server/authorization-server.js +1304 -0
  287. package/esm/server/client-authentication.d.ts +28 -0
  288. package/esm/server/client-authentication.js +51 -0
  289. package/esm/server/grants/authorization-code.d.ts +179 -0
  290. package/esm/server/grants/authorization-code.js +232 -0
  291. package/esm/server/grants/client-credentials.d.ts +52 -0
  292. package/esm/server/grants/client-credentials.js +53 -0
  293. package/esm/server/grants/device-authorization.d.ts +103 -0
  294. package/esm/server/grants/device-authorization.js +156 -0
  295. package/esm/server/grants/grant.d.ts +165 -0
  296. package/esm/server/grants/grant.js +173 -0
  297. package/esm/server/grants/password.d.ts +80 -0
  298. package/esm/server/grants/password.js +92 -0
  299. package/esm/server/grants/refresh-token.d.ts +80 -0
  300. package/esm/server/grants/refresh-token.js +136 -0
  301. package/esm/server/introspection-token-reader.d.ts +153 -0
  302. package/esm/server/introspection-token-reader.js +164 -0
  303. package/esm/server/jwks-token-reader.d.ts +263 -0
  304. package/esm/server/jwks-token-reader.js +508 -0
  305. package/esm/server/mod.d.ts +23 -0
  306. package/esm/server/mod.js +15 -0
  307. package/esm/server/public-suffix/mod.d.ts +62 -0
  308. package/esm/server/public-suffix/mod.js +103 -0
  309. package/esm/server/public-suffix/rules.d.ts +23 -0
  310. package/esm/server/public-suffix/rules.js +23 -0
  311. package/esm/server/redirect-uri.d.ts +187 -0
  312. package/esm/server/redirect-uri.js +331 -0
  313. package/esm/server/resource-server.d.ts +286 -0
  314. package/esm/server/resource-server.js +365 -0
  315. package/esm/server/services/authorization-code.d.ts +84 -0
  316. package/esm/server/services/authorization-code.js +35 -0
  317. package/esm/server/services/client.d.ts +35 -0
  318. package/esm/server/services/client.js +1 -0
  319. package/esm/server/services/device-authorization.d.ts +134 -0
  320. package/esm/server/services/device-authorization.js +7 -0
  321. package/esm/server/services/token.d.ts +242 -0
  322. package/esm/server/services/token.js +78 -0
  323. package/esm/server/services/user.d.ts +29 -0
  324. package/esm/server/services/user.js +7 -0
  325. package/esm/server/signing-keys.d.ts +201 -0
  326. package/esm/server/signing-keys.js +225 -0
  327. package/esm/server/utils/hash.d.ts +6 -0
  328. package/esm/server/utils/hash.js +11 -0
  329. package/esm/testing/contract/authorization-code.d.ts +37 -0
  330. package/esm/testing/contract/authorization-code.js +93 -0
  331. package/esm/testing/contract/client.d.ts +85 -0
  332. package/esm/testing/contract/client.js +126 -0
  333. package/esm/testing/contract/device-authorization.d.ts +37 -0
  334. package/esm/testing/contract/device-authorization.js +193 -0
  335. package/esm/testing/contract/lockout-store.d.ts +47 -0
  336. package/esm/testing/contract/lockout-store.js +122 -0
  337. package/esm/testing/contract/mfa-store.d.ts +50 -0
  338. package/esm/testing/contract/mfa-store.js +226 -0
  339. package/esm/testing/contract/mod.d.ts +39 -0
  340. package/esm/testing/contract/mod.js +39 -0
  341. package/esm/testing/contract/otp-store.d.ts +48 -0
  342. package/esm/testing/contract/otp-store.js +197 -0
  343. package/esm/testing/contract/rate-limit-store.d.ts +52 -0
  344. package/esm/testing/contract/rate-limit-store.js +105 -0
  345. package/esm/testing/contract/token-flow-store.d.ts +54 -0
  346. package/esm/testing/contract/token-flow-store.js +179 -0
  347. package/esm/testing/contract/token-reader.d.ts +77 -0
  348. package/esm/testing/contract/token-reader.js +78 -0
  349. package/esm/testing/contract/token.d.ts +61 -0
  350. package/esm/testing/contract/token.js +287 -0
  351. package/esm/testing/contract/user.d.ts +63 -0
  352. package/esm/testing/contract/user.js +75 -0
  353. package/esm/testing/mod.d.ts +34 -0
  354. package/esm/testing/mod.js +34 -0
  355. package/esm/testing/server.d.ts +197 -0
  356. package/esm/testing/server.js +193 -0
  357. package/esm/testing/services.d.ts +373 -0
  358. package/esm/testing/services.js +703 -0
  359. package/esm/utils/_buffer.d.ts +10 -0
  360. package/esm/utils/_buffer.js +12 -0
  361. package/esm/utils/_timing-safe.d.ts +13 -0
  362. package/esm/utils/_timing-safe.js +22 -0
  363. package/esm/utils/authentication-context.d.ts +3 -0
  364. package/esm/utils/authentication-context.js +14 -0
  365. package/esm/utils/basic-auth.d.ts +50 -0
  366. package/esm/utils/basic-auth.js +106 -0
  367. package/esm/utils/crypto.d.ts +97 -0
  368. package/esm/utils/crypto.js +162 -0
  369. package/esm/utils/pkce.d.ts +151 -0
  370. package/esm/utils/pkce.js +179 -0
  371. package/esm/utils/text.d.ts +24 -0
  372. package/esm/utils/text.js +28 -0
  373. package/esm/utils/url.d.ts +66 -0
  374. package/esm/utils/url.js +90 -0
  375. package/package.json +92 -0
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Sign in with Apple connector. Apple is OpenID-Connect-shaped but does not fit
3
+ * {@link oidcProvider}: its client secret is a signed ES256 JWT rather than a
4
+ * static string (see {@link generateAppleClientSecret}), it authenticates the
5
+ * client in the token body (`client_secret_post`), and it requires
6
+ * `response_mode=form_post` whenever profile scopes are requested. This is a
7
+ * dedicated {@link ExternalProvider} that exchanges the code, then verifies the
8
+ * `id_token` signature against Apple's JWKS.
9
+ *
10
+ * The user's name is returned by Apple **only** on the first authorization, in
11
+ * the `form_post` body's `user` field — never in the `id_token`. This connector
12
+ * returns what the `id_token` carries (stable subject, email); capturing the
13
+ * first-authorization name is the callback route's responsibility, since only
14
+ * it sees the form body.
15
+ *
16
+ * @module
17
+ */
18
+ import { toArrayBuffer } from "../../utils/_buffer.js";
19
+ import { base64urlDecode } from "../../utils/crypto.js";
20
+ import { assertIdTokenClaims, describeError } from "./_shared.js";
21
+ import { runTokenExchange } from "./_token-exchange.js";
22
+ import { createAppleClientSecretFactory, } from "./apple-client-secret.js";
23
+ import { ExternalAuthError } from "./errors.js";
24
+ const APPLE_ISSUER = "https://appleid.apple.com";
25
+ const APPLE_AUTHORIZE_URL = "https://appleid.apple.com/auth/authorize";
26
+ const APPLE_TOKEN_URL = "https://appleid.apple.com/auth/token";
27
+ const APPLE_JWKS_URL = "https://appleid.apple.com/auth/keys";
28
+ const encoder = new TextEncoder();
29
+ const decoder = new TextDecoder();
30
+ const JWKS_CACHE_TTL_MS = 60 * 60 * 1000;
31
+ const SIGNATURE_NOT_VERIFIED = `Apple id_token signature did not verify against Apple's JWKS — the ` +
32
+ `token is forged, corrupted, or signed by an unpublished key.`;
33
+ /**
34
+ * Creates a Sign in with Apple connector with id `"apple"`.
35
+ *
36
+ * The flow requests `response_mode=form_post` (Apple's requirement when `name`
37
+ * or `email` scope is present), exchanges the code at Apple's token endpoint
38
+ * with a freshly-signed client-secret JWT, and verifies the returned
39
+ * `id_token`'s RS256 signature against Apple's published keys before trusting
40
+ * its claims (`iss`, `aud`, `azp`, `exp`, and the `nonce` when one was sent,
41
+ * checked exactly as {@link oidcProvider} checks them). Apple's
42
+ * private-relay addresses (`@privaterelay.appleid.com`) are ordinary verified
43
+ * emails and are returned as-is. The raw `id_token` claims — including
44
+ * `is_private_email` — stay on {@link ExternalProfile.raw}.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * const flow = new ExternalAuthFlow({
49
+ * provider: appleProvider({
50
+ * clientId: "com.example.web",
51
+ * teamId: Deno.env.get("APPLE_TEAM_ID")!,
52
+ * keyId: Deno.env.get("APPLE_KEY_ID")!,
53
+ * privateKey: Deno.env.get("APPLE_PRIVATE_KEY")!,
54
+ * }),
55
+ * });
56
+ * ```
57
+ */
58
+ export function appleProvider(options) {
59
+ const id = "apple";
60
+ const fetchImpl = (input, init) => (options.fetch ?? globalThis.fetch)(input, init);
61
+ const clientSecretFactory = options.clientSecret ??
62
+ createAppleClientSecretFactory({
63
+ providerId: id,
64
+ teamId: options.teamId,
65
+ keyId: options.keyId,
66
+ clientId: options.clientId,
67
+ privateKey: options.privateKey,
68
+ expiresInSeconds: options.expiresInSeconds,
69
+ });
70
+ let jwksCache = null;
71
+ async function exchangeCode(input) {
72
+ const clientSecret = await clientSecretFactory();
73
+ const { value } = await runTokenExchange({
74
+ provider: id,
75
+ displayName: "Apple",
76
+ endpoint: APPLE_TOKEN_URL,
77
+ body: new URLSearchParams({
78
+ grant_type: "authorization_code",
79
+ code: input.code,
80
+ redirect_uri: input.redirectUri,
81
+ client_id: options.clientId,
82
+ client_secret: clientSecret,
83
+ }),
84
+ requiredField: "id_token",
85
+ fetch: fetchImpl,
86
+ httpErrorHint: `An "invalid_client" here means the client-secret JWT ` +
87
+ `is wrong — check the team id, key id, and Services ID (client id).`,
88
+ tokenErrorHint: appleTokenErrorHint,
89
+ });
90
+ return value;
91
+ }
92
+ async function loadJwks() {
93
+ if (jwksCache && Date.now() - jwksCache.fetchedAt < JWKS_CACHE_TTL_MS) {
94
+ return jwksCache.keys;
95
+ }
96
+ let res;
97
+ try {
98
+ res = await fetchImpl(APPLE_JWKS_URL, {
99
+ headers: { Accept: "application/json" },
100
+ });
101
+ }
102
+ catch (error) {
103
+ throw new ExternalAuthError(id, "provider_error", `could not reach Apple's JWKS endpoint (${describeError(error)}).`, { cause: error });
104
+ }
105
+ if (!res.ok) {
106
+ await res.body?.cancel();
107
+ throw new ExternalAuthError(id, "provider_error", `Apple's JWKS endpoint responded with HTTP ${res.status}.`);
108
+ }
109
+ let doc;
110
+ try {
111
+ doc = (await res.json());
112
+ }
113
+ catch (error) {
114
+ throw new ExternalAuthError(id, "provider_error", `Apple's JWKS endpoint returned invalid JSON (${describeError(error)}).`, { cause: error });
115
+ }
116
+ if (!Array.isArray(doc.keys)) {
117
+ throw new ExternalAuthError(id, "provider_error", `Apple's JWKS endpoint returned no "keys" array.`);
118
+ }
119
+ const keys = doc.keys;
120
+ jwksCache = { keys, fetchedAt: Date.now() };
121
+ return keys;
122
+ }
123
+ async function verifyIdToken(idToken, expectedNonce) {
124
+ const parts = idToken.split(".");
125
+ if (parts.length !== 3) {
126
+ throw new ExternalAuthError(id, "provider_error", `Apple returned a malformed id_token (expected three segments).`);
127
+ }
128
+ const header = decodeJson(id, parts[0], "id_token header");
129
+ const kid = typeof header.kid === "string" ? header.kid : undefined;
130
+ if (header.alg !== "RS256") {
131
+ throw new ExternalAuthError(id, "provider_error", `Apple id_token is signed with "${String(header.alg)}", expected ` +
132
+ `RS256.`);
133
+ }
134
+ if (!kid) {
135
+ throw new ExternalAuthError(id, "provider_error", `Apple id_token header has no "kid" — refusing to bind it to an ` +
136
+ `arbitrary JWKS key. Apple always sets "kid" on a real token.`);
137
+ }
138
+ const jwk = await resolveVerificationKey(kid);
139
+ let key;
140
+ try {
141
+ key = await crypto.subtle.importKey("jwk", jwk, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["verify"]);
142
+ }
143
+ catch (error) {
144
+ throw new ExternalAuthError(id, "provider_error", `Apple's signing key could not be imported (${describeError(error)}).`, { cause: error });
145
+ }
146
+ let signature;
147
+ try {
148
+ signature = base64urlDecode(parts[2]);
149
+ }
150
+ catch (error) {
151
+ throw new ExternalAuthError(id, "provider_error", SIGNATURE_NOT_VERIFIED, {
152
+ cause: error,
153
+ });
154
+ }
155
+ const valid = await crypto.subtle.verify({ name: "RSASSA-PKCS1-v1_5" }, key, toArrayBuffer(signature), encoder.encode(`${parts[0]}.${parts[1]}`));
156
+ if (!valid) {
157
+ throw new ExternalAuthError(id, "provider_error", SIGNATURE_NOT_VERIFIED);
158
+ }
159
+ const claims = decodeJson(id, parts[1], "id_token payload");
160
+ assertIdTokenClaims({
161
+ provider: id,
162
+ claims,
163
+ issuer: APPLE_ISSUER,
164
+ clientId: options.clientId,
165
+ expectedNonce,
166
+ });
167
+ return claims;
168
+ }
169
+ async function resolveVerificationKey(kid) {
170
+ const pick = (keys) => keys.find((key) => key.kid === kid);
171
+ let match = pick(await loadJwks());
172
+ if (!match) {
173
+ jwksCache = null;
174
+ match = pick(await loadJwks());
175
+ }
176
+ if (!match) {
177
+ throw new ExternalAuthError(id, "provider_error", `Apple's JWKS has no key with kid "${String(kid)}" — the id_token was ` +
178
+ `signed by a key Apple no longer publishes.`);
179
+ }
180
+ return match;
181
+ }
182
+ return {
183
+ id,
184
+ displayName: "Apple",
185
+ defaultScopes: options.scopes ?? ["name", "email"],
186
+ usesPkce: false,
187
+ usesNonce: true,
188
+ buildAuthorizationUrl(input) {
189
+ const url = new URL(APPLE_AUTHORIZE_URL);
190
+ url.searchParams.set("response_type", "code");
191
+ url.searchParams.set("client_id", options.clientId);
192
+ url.searchParams.set("redirect_uri", input.redirectUri);
193
+ url.searchParams.set("scope", input.scopes.join(" "));
194
+ url.searchParams.set("state", input.state);
195
+ if (input.nonce)
196
+ url.searchParams.set("nonce", input.nonce);
197
+ if (input.scopes.length > 0) {
198
+ url.searchParams.set("response_mode", "form_post");
199
+ }
200
+ return Promise.resolve(url.toString());
201
+ },
202
+ async fetchProfile(input) {
203
+ const idToken = await exchangeCode(input);
204
+ const claims = await verifyIdToken(idToken, input.nonce);
205
+ return profileFromClaims(claims);
206
+ },
207
+ };
208
+ }
209
+ function profileFromClaims(claims) {
210
+ const subject = claims.sub;
211
+ if (typeof subject !== "string" || subject.length === 0) {
212
+ throw new ExternalAuthError("apple", "provider_error", `Apple id_token is missing the required "sub" claim.`);
213
+ }
214
+ return {
215
+ provider: "apple",
216
+ subject,
217
+ email: typeof claims.email === "string" ? claims.email : undefined,
218
+ emailVerified: isAppleTrue(claims.email_verified),
219
+ raw: claims,
220
+ };
221
+ }
222
+ function isAppleTrue(value) {
223
+ return value === true || value === "true";
224
+ }
225
+ function appleTokenErrorHint(error) {
226
+ if (error === undefined) {
227
+ return `Ensure the sign-in requested the "openid" flow scopes.`;
228
+ }
229
+ if (error === "invalid_client") {
230
+ return `The client-secret JWT is wrong — check the team id, key id, and ` +
231
+ `Services ID (client id).`;
232
+ }
233
+ if (error === "invalid_grant") {
234
+ return `Apple rejected the code — it expired, was already used, or the ` +
235
+ `redirect URI does not match the Services ID configuration. Ask the ` +
236
+ `user to start again.`;
237
+ }
238
+ return `See Apple's "Generate and validate tokens" documentation for the ` +
239
+ `error's meaning.`;
240
+ }
241
+ function decodeJson(providerId, segment, what) {
242
+ try {
243
+ return JSON.parse(decoder.decode(base64urlDecode(segment)));
244
+ }
245
+ catch (error) {
246
+ throw new ExternalAuthError(providerId, "provider_error", `Apple ${what} was not valid base64url JSON (${describeError(error)}).`, { cause: error });
247
+ }
248
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Discord sign-in preset over the generic {@link oauth2Provider} connector.
3
+ *
4
+ * @module
5
+ */
6
+ import type { ExternalProvider } from "./provider.js";
7
+ /** Options for {@link discordProvider}. */
8
+ export interface DiscordProviderOptions {
9
+ /** Client ID of the Discord application (OAuth2 tab). */
10
+ clientId: string;
11
+ /** The matching client secret. */
12
+ clientSecret: string;
13
+ /** Scopes requested by default. Defaults to `["identify", "email"]`. */
14
+ scopes?: string[];
15
+ /** Fetch implementation for all provider traffic. Defaults to `globalThis.fetch`. */
16
+ fetch?: typeof fetch;
17
+ }
18
+ /**
19
+ * Creates a Discord connector with id `"discord"`.
20
+ *
21
+ * Discord speaks plain OAuth2 (no discovery, no id_token), so this is a preset
22
+ * over {@link oauth2Provider} pinned to Discord's fixed endpoints. The profile
23
+ * is read from `GET /users/@me`: the subject is the Discord user id,
24
+ * `emailVerified` reflects Discord's `verified` flag for the account email, and
25
+ * the display name prefers the global display name over the legacy username.
26
+ * The `/users/@me` payload is available on {@link ExternalProfile.raw}.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const flow = new ExternalAuthFlow({
31
+ * provider: discordProvider({
32
+ * clientId: Deno.env.get("DISCORD_CLIENT_ID")!,
33
+ * clientSecret: Deno.env.get("DISCORD_CLIENT_SECRET")!,
34
+ * }),
35
+ * });
36
+ * ```
37
+ */
38
+ export declare function discordProvider(options: DiscordProviderOptions): ExternalProvider;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Discord sign-in preset over the generic {@link oauth2Provider} connector.
3
+ *
4
+ * @module
5
+ */
6
+ import { oauth2Provider } from "./oauth2.js";
7
+ const DISCORD_AUTHORIZE_URL = "https://discord.com/oauth2/authorize";
8
+ const DISCORD_TOKEN_URL = "https://discord.com/api/oauth2/token";
9
+ const DISCORD_USER_URL = "https://discord.com/api/users/@me";
10
+ function avatarUrl(user) {
11
+ const id = user.id;
12
+ const avatar = user.avatar;
13
+ if (typeof id === "string" && typeof avatar === "string" && avatar) {
14
+ const ext = avatar.startsWith("a_") ? "gif" : "png";
15
+ return `https://cdn.discordapp.com/avatars/${id}/${avatar}.${ext}`;
16
+ }
17
+ return undefined;
18
+ }
19
+ /**
20
+ * Creates a Discord connector with id `"discord"`.
21
+ *
22
+ * Discord speaks plain OAuth2 (no discovery, no id_token), so this is a preset
23
+ * over {@link oauth2Provider} pinned to Discord's fixed endpoints. The profile
24
+ * is read from `GET /users/@me`: the subject is the Discord user id,
25
+ * `emailVerified` reflects Discord's `verified` flag for the account email, and
26
+ * the display name prefers the global display name over the legacy username.
27
+ * The `/users/@me` payload is available on {@link ExternalProfile.raw}.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const flow = new ExternalAuthFlow({
32
+ * provider: discordProvider({
33
+ * clientId: Deno.env.get("DISCORD_CLIENT_ID")!,
34
+ * clientSecret: Deno.env.get("DISCORD_CLIENT_SECRET")!,
35
+ * }),
36
+ * });
37
+ * ```
38
+ */
39
+ export function discordProvider(options) {
40
+ return oauth2Provider({
41
+ id: "discord",
42
+ displayName: "Discord",
43
+ authorizationEndpoint: DISCORD_AUTHORIZE_URL,
44
+ tokenEndpoint: DISCORD_TOKEN_URL,
45
+ userInfoEndpoint: DISCORD_USER_URL,
46
+ clientId: options.clientId,
47
+ clientSecret: options.clientSecret,
48
+ defaultScopes: options.scopes ?? ["identify", "email"],
49
+ fetch: options.fetch,
50
+ mapProfile: ({ profile }) => ({
51
+ subject: typeof profile.id === "string" ? profile.id : "",
52
+ email: typeof profile.email === "string" ? profile.email : undefined,
53
+ emailVerified: profile.verified === true,
54
+ name: typeof profile.global_name === "string" && profile.global_name
55
+ ? profile.global_name
56
+ : typeof profile.username === "string"
57
+ ? profile.username
58
+ : undefined,
59
+ picture: avatarUrl(profile),
60
+ }),
61
+ });
62
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The error contract for external-provider (social login) flows.
3
+ *
4
+ * Every failure in the external connector layer is thrown as an
5
+ * {@link ExternalAuthError} whose message names the provider, what failed, and
6
+ * the likely fix — misconfiguration is meant to be diagnosable from the
7
+ * message alone. The {@link ExternalAuthErrorCode} tells app code how to
8
+ * respond: `configuration` is a deploy-time bug to fix, everything else is a
9
+ * per-attempt failure to surface to the user (usually "sign in again").
10
+ *
11
+ * @module
12
+ */
13
+ /**
14
+ * Machine-readable causes for an {@link ExternalAuthError}.
15
+ *
16
+ * - `configuration` — the connector is miswired (bad issuer, failed
17
+ * discovery, missing endpoint, provider/transient mismatch). Fix the
18
+ * deployment; retrying the sign-in will not help.
19
+ * - `provider_error` — the provider rejected the request (callback `error`
20
+ * param, token-endpoint error, profile-endpoint failure, malformed
21
+ * response). The message carries the provider's error code/description.
22
+ * - `invalid_callback` — the callback URL is missing `code` or `state`.
23
+ * - `state_mismatch` — the callback `state` does not match the transient
24
+ * (possible CSRF or a stale/mixed-up sign-in attempt).
25
+ * - `transient_expired` — the sign-in attempt outlived the configured max
26
+ * transient age; the user should start again.
27
+ * - `nonce_mismatch` — the id_token `nonce` claim does not match the
28
+ * transient (possible token replay); the user should start again.
29
+ */
30
+ export type ExternalAuthErrorCode = "configuration" | "provider_error" | "invalid_callback" | "state_mismatch" | "transient_expired" | "nonce_mismatch";
31
+ /**
32
+ * A diagnosable error from an external-provider flow. The message is always
33
+ * prefixed with the provider id (e.g. `[google] …`) and states what failed
34
+ * plus the likely fix; switch on {@link ExternalAuthError.code} to decide
35
+ * whether to alert an operator (`configuration`) or restart the sign-in.
36
+ */
37
+ export declare class ExternalAuthError extends Error {
38
+ /** Always `"ExternalAuthError"`, so instances are recognizable across realms. */
39
+ readonly name = "ExternalAuthError";
40
+ /** The machine-readable failure cause. */
41
+ readonly code: ExternalAuthErrorCode;
42
+ /** The id of the provider the failure belongs to (e.g. `"google"`). */
43
+ readonly provider: string;
44
+ /** Builds the error; `message` is prefixed with `[provider]` automatically. */
45
+ constructor(provider: string, code: ExternalAuthErrorCode, message: string, options?: ErrorOptions);
46
+ }
47
+ /** Type guard for {@link ExternalAuthError}. */
48
+ export declare function isExternalAuthError(value: unknown): value is ExternalAuthError;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The error contract for external-provider (social login) flows.
3
+ *
4
+ * Every failure in the external connector layer is thrown as an
5
+ * {@link ExternalAuthError} whose message names the provider, what failed, and
6
+ * the likely fix — misconfiguration is meant to be diagnosable from the
7
+ * message alone. The {@link ExternalAuthErrorCode} tells app code how to
8
+ * respond: `configuration` is a deploy-time bug to fix, everything else is a
9
+ * per-attempt failure to surface to the user (usually "sign in again").
10
+ *
11
+ * @module
12
+ */
13
+ /**
14
+ * A diagnosable error from an external-provider flow. The message is always
15
+ * prefixed with the provider id (e.g. `[google] …`) and states what failed
16
+ * plus the likely fix; switch on {@link ExternalAuthError.code} to decide
17
+ * whether to alert an operator (`configuration`) or restart the sign-in.
18
+ */
19
+ export class ExternalAuthError extends Error {
20
+ /** Always `"ExternalAuthError"`, so instances are recognizable across realms. */
21
+ name = "ExternalAuthError";
22
+ /** The machine-readable failure cause. */
23
+ code;
24
+ /** The id of the provider the failure belongs to (e.g. `"google"`). */
25
+ provider;
26
+ /** Builds the error; `message` is prefixed with `[provider]` automatically. */
27
+ constructor(provider, code, message, options) {
28
+ super(`[${provider}] ${message}`, options);
29
+ this.provider = provider;
30
+ this.code = code;
31
+ }
32
+ }
33
+ /** Type guard for {@link ExternalAuthError}. */
34
+ export function isExternalAuthError(value) {
35
+ return value instanceof ExternalAuthError;
36
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * The provider-agnostic two-step flow for external (social) sign-in:
3
+ * {@link ExternalAuthFlow.start} builds the redirect and hands back a
4
+ * serializable transient; {@link ExternalAuthFlow.finish} verifies the
5
+ * callback and returns the normalized profile.
6
+ *
7
+ * @module
8
+ */
9
+ import type { ExternalAuthTransient, ExternalProfile, ExternalProvider } from "./provider.js";
10
+ /** Default {@link ExternalAuthFlowOptions.maxTransientAgeMs}: 10 minutes. */
11
+ export declare const DEFAULT_MAX_TRANSIENT_AGE_MS: number;
12
+ /** Options for {@link ExternalAuthFlow}. */
13
+ export interface ExternalAuthFlowOptions {
14
+ /** The connector to drive (e.g. `googleProvider(…)`). */
15
+ provider: ExternalProvider;
16
+ /**
17
+ * Max age of a transient before {@link ExternalAuthFlow.finish} rejects the
18
+ * attempt as expired, in ms. Bounds the window in which a stolen transient
19
+ * or callback URL stays usable. Defaults to
20
+ * {@link DEFAULT_MAX_TRANSIENT_AGE_MS}.
21
+ */
22
+ maxTransientAgeMs?: number;
23
+ }
24
+ /** Input to {@link ExternalAuthFlow.start}. */
25
+ export interface ExternalAuthStartInput {
26
+ /** The callback URL registered with the provider for this app. */
27
+ redirectUri: string;
28
+ /** Override the provider's default scopes. */
29
+ scopes?: string[];
30
+ /** OIDC `prompt` parameter (e.g. `"select_account"`). */
31
+ prompt?: string;
32
+ }
33
+ /** Result of {@link ExternalAuthFlow.start}. */
34
+ export interface ExternalAuthStartResult {
35
+ /** The provider authorization URL to redirect the user's browser to. */
36
+ url: string;
37
+ /**
38
+ * Per-attempt state to persist in a cookie/session and hand back to
39
+ * {@link ExternalAuthFlow.finish}. JSON-serializable; contains no tokens.
40
+ */
41
+ transient: ExternalAuthTransient;
42
+ }
43
+ /** Input to {@link ExternalAuthFlow.finish}. */
44
+ export interface ExternalAuthFinishInput {
45
+ /** The callback URL's search params (or the full URL / query string). */
46
+ params: URL | URLSearchParams | string;
47
+ /** The transient produced by the matching {@link ExternalAuthFlow.start}. */
48
+ transient: ExternalAuthTransient;
49
+ }
50
+ /**
51
+ * Drives one external provider through the authorization-code redirect dance
52
+ * without the library storing anything: {@link start} returns the redirect URL
53
+ * plus a JSON-serializable {@link ExternalAuthTransient} for the caller to keep
54
+ * (sealed cookie or session), and {@link finish} takes the callback params and
55
+ * that transient back and returns the verified {@link ExternalProfile}.
56
+ *
57
+ * The flow itself performs no network I/O — inject `fetch` on the provider to
58
+ * stub the network in tests. Create one flow per configured provider.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * const flow = new ExternalAuthFlow({
63
+ * provider: googleProvider({ clientId, clientSecret }),
64
+ * });
65
+ *
66
+ * // GET /auth/social/google — redirect to Google, transient into a cookie.
67
+ * const { url, transient } = await flow.start({
68
+ * redirectUri: "https://app.example.com/auth/social/google/callback",
69
+ * });
70
+ *
71
+ * // GET /auth/social/google/callback — verify and normalize.
72
+ * const profile = await flow.finish({
73
+ * params: new URL(request.url).searchParams,
74
+ * transient,
75
+ * });
76
+ * // App code decides: look up (profile.provider, profile.subject), create
77
+ * // or link a user, then start your own session.
78
+ * ```
79
+ */
80
+ export declare class ExternalAuthFlow {
81
+ #private;
82
+ /** The connector this flow drives. */
83
+ readonly provider: ExternalProvider;
84
+ /** Creates a flow for one configured provider. */
85
+ constructor(options: ExternalAuthFlowOptions);
86
+ /**
87
+ * Begins a sign-in attempt: generates the per-attempt `state` (plus a PKCE
88
+ * verifier and OIDC nonce when the provider uses them), builds the
89
+ * provider's authorization URL, and returns both. Persist the transient
90
+ * (e.g. sealed cookie) and redirect the browser to `url`.
91
+ *
92
+ * @throws {ExternalAuthError} `configuration` when the provider cannot
93
+ * resolve its endpoints (e.g. OIDC discovery failed).
94
+ */
95
+ start(input: ExternalAuthStartInput): Promise<ExternalAuthStartResult>;
96
+ /**
97
+ * Completes a sign-in attempt from the provider callback: enforces the max
98
+ * transient age, surfaces provider `error` callback params, verifies
99
+ * `state` with a timing-safe compare, exchanges the code, and (for OIDC
100
+ * providers) validates the id_token nonce — then returns the normalized
101
+ * profile.
102
+ *
103
+ * @throws {ExternalAuthError} with a code describing the failure — see
104
+ * {@link ExternalAuthErrorCode} for how app code should respond to each.
105
+ */
106
+ finish(input: ExternalAuthFinishInput): Promise<ExternalProfile>;
107
+ }