@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,852 @@
1
+ /**
2
+ * Backend-for-Frontend (BFF) adapter for Hono.
3
+ *
4
+ * Wraps a {@link DirectClient} configured with a client secret
5
+ * and exposes the session endpoints a browser SPA talks to:
6
+ *
7
+ * - `POST /auth/login` — redirects the browser to the authorize endpoint,
8
+ * persisting a per-request state/verifier record and binding its `state` to
9
+ * this browser with a short-lived cookie.
10
+ * - `GET /auth/callback` — requires the browser to present that binding
11
+ * cookie, exchanges the code, opens a session (or, in
12
+ * `sessionMode: "shared"`, attaches the tokens to the app's existing
13
+ * session), and redirects to the app's `return_to` path.
14
+ * - `GET|POST /auth/logout` — destroys the session and (best-effort) revokes
15
+ * the refresh token upstream. Registered for both methods because the
16
+ * shipped React client navigates the browser here (a GET).
17
+ * - `GET /auth/session` — returns `{ isAuthenticated, user }` from the
18
+ * session. **Never** exposes tokens to the browser.
19
+ * - `POST /auth/backchannel` — OIDC Back-Channel Logout receiver, mounted only
20
+ * when `backchannelLogout` is configured. A server-to-server call from the OP
21
+ * that ends the matching server-side session(s).
22
+ *
23
+ * A companion {@link HonoBff.attachToken} middleware reads the session
24
+ * cookie, looks up / refreshes the access token, and sets
25
+ * `Authorization: Bearer <token>` on the inbound request so a co-located
26
+ * resource-server adapter can validate it normally — all in-process, no
27
+ * outbound HTTP.
28
+ *
29
+ * The credentialed surface is **CSRF-protected by default**: a request that
30
+ * carries the session cookie must also carry a custom `x-csrf` header (the
31
+ * shipped `BffClient` and React adapter send it automatically), and the
32
+ * `GET /auth/logout` navigation — which cannot carry one, and is what the
33
+ * shipped client uses — is guarded by a same-origin check that fails closed.
34
+ * `POST /auth/logout` is the stronger path to adopt. See
35
+ * {@link HonoBffCsrfOptions}; pass `csrf: false` to disable.
36
+ *
37
+ * Sign-in itself is bound to the browser that started it, and that binding is
38
+ * **not** configurable: `/auth/login` records the `state` it minted in a
39
+ * short-lived `HttpOnly` `SameSite=Lax` cookie, and `/auth/callback` refuses
40
+ * any authorization response whose `state` that cookie does not vouch for. A
41
+ * pending authorization is therefore never completable from a browser other
42
+ * than the one that began it, whatever
43
+ * {@link HonoBffOptions.authRequestStorage} it is kept in — without it an
44
+ * attacker could start a sign-in and hand the victim the callback URL to log
45
+ * the victim into the attacker's account.
46
+ *
47
+ * @module
48
+ */
49
+ import { Hono } from "hono";
50
+ import type { Context, Handler, MiddlewareHandler } from "hono";
51
+ import type { DirectClient, TokenBundle, UserInfoClaims } from "../../../client/mod.js";
52
+ import type { ClientInterface } from "../../../models/client.js";
53
+ import type { AbstractScope, BasicScope } from "../../../models/scope.js";
54
+ import type { HonoAuthorizationServer } from "../authorization-server.js";
55
+ import type { HonoResourceServer } from "../resource-server.js";
56
+ import type { AuthRequestStorageFactory } from "./auth-request-store.js";
57
+ import { type SessionStore } from "./session-store.js";
58
+ import { type HonoBffProxyOptions } from "./proxy.js";
59
+ /**
60
+ * A resource server the BFF can compose with `attachToken()` to expose a
61
+ * single `bff.protect()` middleware.
62
+ *
63
+ * Accepted in two shapes so both deployment topologies stay symmetric:
64
+ *
65
+ * - **Own-issuer** (the Udibo case): pass a {@link HonoAuthorizationServer}.
66
+ * `protect()` validates against the same in-process token service the
67
+ * issuer uses — no introspection round-trip.
68
+ * - **Third-party-issuer**: pass a {@link HonoResourceServer} configured
69
+ * with `IntrospectionTokenReader`. `protect()` validates via RFC 7662
70
+ * against the upstream.
71
+ */
72
+ export type HonoBffResourceServer<Client extends ClientInterface = any, User = any, S extends AbstractScope = BasicScope> = HonoResourceServer<Client, User, S> | HonoAuthorizationServer<Client, User, S>;
73
+ /**
74
+ * Cookie settings for the BFF session cookie. Defaults follow the IETF
75
+ * "OAuth 2.0 for Browser-Based Apps" BCP §6.1.3.2: `Secure`, `HttpOnly`,
76
+ * `SameSite=Strict`, `Path=/`, no `Domain`, and the `__Host-` name prefix.
77
+ *
78
+ * The **default** name is prefix-aware: it carries `__Host-` only when every
79
+ * attribute that prefix requires holds, and falls back to the bare name
80
+ * otherwise. An **explicit** {@link name} whose prefix contradicts the other
81
+ * attributes throws from the {@link HonoBff} constructor instead of emitting a
82
+ * cookie every browser silently drops.
83
+ */
84
+ export interface HonoBffCookieOptions {
85
+ /**
86
+ * Cookie name. Defaults to `"__Host-oauth2_session"` (the BCP `__Host-`
87
+ * prefix) when the other options satisfy that prefix — {@link secure} on,
88
+ * {@link path} `"/"`, and no {@link domain} — and to `"oauth2_session"`
89
+ * otherwise, because a browser rejects a `__Host-` cookie that breaks any of
90
+ * them.
91
+ *
92
+ * Setting this explicitly to a `__Host-` or `__Secure-` prefixed name throws
93
+ * from the {@link HonoBff} constructor when the other options contradict the
94
+ * prefix. Prefixes are matched case-insensitively, as browsers match them.
95
+ */
96
+ name?: string;
97
+ /**
98
+ * Cookie path. Defaults to `"/"`. Any other value drops the default
99
+ * `__Host-` prefix, which requires `Path=/`.
100
+ */
101
+ path?: string;
102
+ /**
103
+ * Marks the cookie Secure. Defaults to `true`. Turning it off drops the
104
+ * default `__Host-` prefix, which requires `Secure`.
105
+ */
106
+ secure?: boolean;
107
+ /** Marks the cookie HttpOnly. Defaults to `true`. */
108
+ httpOnly?: boolean;
109
+ /**
110
+ * SameSite attribute. Defaults to `"Strict"` (per the BCP). Use `"Lax"` if
111
+ * you run `sessionMode: "shared"` with a cross-origin IDP, so the cookie
112
+ * survives the cross-site callback return.
113
+ *
114
+ * `"None"` requires {@linkcode HonoBffCookieOptions.secure}; the constructor
115
+ * throws on the combination rather than emitting a cookie every modern
116
+ * browser silently drops.
117
+ */
118
+ sameSite?: "Lax" | "Strict" | "None";
119
+ /**
120
+ * Optional cookie domain. The BCP recommends omitting it (host-bound).
121
+ * Setting it drops the default `__Host-` prefix, which forbids `Domain`.
122
+ */
123
+ domain?: string;
124
+ /**
125
+ * `Max-Age` in seconds, for the **cookie only**. Defaults to
126
+ * {@linkcode HonoBffOptions.sessionMaxAgeMs}, so the browser keeps the
127
+ * cookie exactly as long as the session behind it is honored.
128
+ *
129
+ * Set it to lengthen the cookie past the session (harmless: the session ends
130
+ * first and the stale cookie is cleared). Setting it **shorter** than the
131
+ * session lifetime throws from the {@link HonoBff} constructor — that is the
132
+ * pairing where the browser drops the cookie while the session stays active
133
+ * and listed.
134
+ *
135
+ * Pass `"session"` for a true session cookie (no `Max-Age`, gone when the
136
+ * browser closes). The server-side bound still applies, so the two agree:
137
+ * an ephemeral cookie shortens the window, it never unbounds the session.
138
+ */
139
+ maxAge?: number | "session";
140
+ }
141
+ /**
142
+ * CSRF defense for the BFF's credentialed surface.
143
+ *
144
+ * The BFF's session cookie is an ambient credential the browser attaches
145
+ * automatically, so a cross-site page can trigger credentialed requests
146
+ * (classic CSRF). The defense (as used by Duende.BFF's `X-CSRF` and Curity's
147
+ * `token-handler-version` headers) requires a **custom request header** on the
148
+ * fetch-driven surface: a custom header makes the request "non-simple", forcing
149
+ * a CORS preflight that an untrusted origin cannot satisfy, so the browser never
150
+ * attaches the cookie. The shipped `BffClient` (and therefore the React
151
+ * adapter) sends this header automatically.
152
+ *
153
+ * Enforced only when the session cookie is actually present (an anonymous
154
+ * request has nothing to abuse). Applies to `GET /auth/session`, the
155
+ * `POST /auth/logout` path, and {@link HonoBff.protect} / {@link HonoBff.attachToken}'s
156
+ * cookie path.
157
+ *
158
+ * `POST /auth/logout` is the **preferred** sign-out path because it is covered
159
+ * by that header check. The `GET /auth/logout` navigation cannot carry a custom
160
+ * header, so it is guarded instead by a same-origin check that reads
161
+ * `Sec-Fetch-Site` (accepting only `same-origin` and `none`) and falls back to
162
+ * comparing `Origin`, else `Referer`, for clients that send no fetch metadata.
163
+ * `same-site` is rejected along with `cross-site`, so a `GET` logout link
164
+ * followed from a sibling subdomain does not pass. That check **fails closed**:
165
+ * a request carrying none of the three signals is rejected. Two residuals come
166
+ * with it. A `GET` logout link followed from a no-referrer page on a browser too
167
+ * old to send `Sec-Fetch-Site` stops working. And because
168
+ * `Sec-Fetch-Site: none` survives redirects by design (W3C Fetch Metadata §4.1),
169
+ * a navigation with no browser initiator — the address bar, a bookmark, or a
170
+ * link opened from a native app such as an email client — that redirects into
171
+ * the `GET` route still passes.
172
+ *
173
+ * **Both residuals apply to the shipped client today**, which signs out by
174
+ * navigating the browser to `GET /auth/logout` (`BffClient.logout()` returns
175
+ * the URL and the React adapter assigns it to `location`). `POST` is the path
176
+ * to **adopt**, not one you already get: wire your sign-out control to post to
177
+ * this route with the `x-csrf` header if a forgeable `GET` sign-out matters to
178
+ * you.
179
+ *
180
+ * Pass `csrf: false` to disable (e.g. an example whose page uses hand-written
181
+ * `fetch` for readability, or an app that has not yet migrated its call sites).
182
+ */
183
+ export interface HonoBffCsrfOptions {
184
+ /**
185
+ * Header name required on credentialed fetch requests. Defaults to `"x-csrf"`.
186
+ * Matched case-insensitively.
187
+ */
188
+ headerName?: string;
189
+ /**
190
+ * If set, the header must equal this value. Otherwise any non-empty value is
191
+ * accepted — presence is what forces the CORS preflight. Defaults to presence.
192
+ */
193
+ headerValue?: string;
194
+ }
195
+ /** Paths for the session endpoints mounted by {@link HonoBff.routes}. */
196
+ export interface HonoBffPaths {
197
+ /**
198
+ * The base the caller mounts {@link HonoBff.routes} under — stripped from
199
+ * the paths below so each handler registers at the right sub-path. Defaults
200
+ * to `/auth`, matching the default paths and the documented
201
+ * `app.route("/auth", bff.routes())`.
202
+ *
203
+ * Set it whenever you move the surface: with
204
+ * `basePath: "/session", login: "/session/login"` the router registers
205
+ * `/login`, so `app.route("/session", bff.routes())` serves
206
+ * `/session/login`. Pass `""` to mount the paths verbatim at the app root.
207
+ *
208
+ * A trailing slash is ignored. Unless it is `""`, **every path that gets
209
+ * mounted must sit strictly under it** (`${basePath}/…`) — the constructor
210
+ * throws otherwise, because `routes()` strips the base to mount each handler
211
+ * while {@link HonoBff.loginContinuation} and the session probe's `logoutUrl`
212
+ * hand out the unstripped paths, so a stray path would be served at one URL
213
+ * and advertised at another. {@link HonoBffPaths.backchannel} is exempt
214
+ * unless {@link HonoBffOptions.backchannelLogout} is configured, since
215
+ * `routes()` mounts it only then.
216
+ */
217
+ basePath?: string;
218
+ /** Where the browser is sent to begin sign-in. Defaults to `/auth/login`. */
219
+ login?: string;
220
+ /** Redirect target the IDP returns to after authorization. Defaults to `/auth/callback`. */
221
+ callback?: string;
222
+ /** Ends the session and clears the cookie. Defaults to `/auth/logout`. */
223
+ logout?: string;
224
+ /** Probed by the SPA for `{ isAuthenticated, user }`. Defaults to `/auth/session`. */
225
+ session?: string;
226
+ /** OIDC Back-Channel Logout receiver. Defaults to `/auth/backchannel`. */
227
+ backchannel?: string;
228
+ }
229
+ /**
230
+ * The subject / OP-session-id a validated OIDC `logout_token` says to log out.
231
+ * Returned by {@link HonoBffBackchannelOptions.verifyLogoutToken}.
232
+ */
233
+ export interface BackchannelLogoutSubject {
234
+ /** The `sub` claim — log out all of the subject's sessions when no `sid`. */
235
+ sub?: string;
236
+ /** The `sid` claim — log out only the session with this OP session id. */
237
+ sid?: string;
238
+ }
239
+ /**
240
+ * OIDC Back-Channel Logout configuration. When set, {@link HonoBff.routes}
241
+ * mounts a `POST /auth/backchannel` receiver.
242
+ *
243
+ * **Signature verification is yours.** The package stays dependency-free, so you
244
+ * supply `verifyLogoutToken`: verify the JWT's signature (against the OP's JWKS,
245
+ * e.g. with `jose`, or in-process for a co-located IDP) **and** its claims
246
+ * (`iss`, `aud`, `iat`, `exp`, the required `events` member
247
+ * `http://schemas.openid.net/event/backchannel-logout`, `sub`/`sid` presence,
248
+ * `nonce` absence, and `jti` replay), then return the `{ sub, sid }` to log out.
249
+ * Throw or return `null` to reject (the receiver responds `400`).
250
+ *
251
+ * Requires a {@link SessionStore} that implements `destroyByLogout`
252
+ * (the in-memory and DB-backed stateful stores do; the stateless encrypted
253
+ * cookie store cannot — construction throws if the store can't support it).
254
+ */
255
+ export interface HonoBffBackchannelOptions {
256
+ /**
257
+ * Verifies a raw `logout_token` JWT (signature and claims) and returns the
258
+ * `{ sub, sid }` to log out. Throw or return `null` to reject the request.
259
+ */
260
+ verifyLogoutToken: (logoutToken: string) => Promise<BackchannelLogoutSubject | null> | BackchannelLogoutSubject | null;
261
+ }
262
+ /**
263
+ * Why `/auth/callback` could not complete a sign-in. Passed to
264
+ * {@link HonoBffOptions.onCallbackError} so the app can render or redirect to a
265
+ * friendly page instead of the default JSON.
266
+ */
267
+ export interface BffCallbackError {
268
+ /**
269
+ * OAuth2-style error code: the IDP's `error` (e.g. `access_denied`),
270
+ * `invalid_request` (missing `code`/`state`, or a `state` this browser never
271
+ * started — see {@link HonoBffOptions.loginStateTtlMs}), or `invalid_grant`
272
+ * (the code exchange failed — expired/replayed code, unknown `state`).
273
+ */
274
+ error: string;
275
+ /** Human-readable description; never contains secrets. */
276
+ error_description: string;
277
+ /** The thrown cause for the `invalid_grant` (exchange) case; otherwise `undefined`. */
278
+ cause?: unknown;
279
+ }
280
+ /** Options accepted by the {@link HonoBff} constructor. */
281
+ export interface HonoBffOptions {
282
+ /**
283
+ * OAuth2 client for the authorization server, constructed with a
284
+ * `clientSecret`. The BFF drives the flows through its
285
+ * `exchangeAuthorizationCode` / `exchangeRefreshToken` primitives; tokens
286
+ * are stored in {@link HonoBffOptions.sessionStore} — **not** in the
287
+ * client's token storage.
288
+ */
289
+ client: DirectClient;
290
+ /**
291
+ * Where session data lives. Defaults to {@link MemorySessionStore},
292
+ * which is fine for dev and tests but must be replaced for production.
293
+ */
294
+ sessionStore?: SessionStore;
295
+ /**
296
+ * How long a BFF session is meant to live, in milliseconds. Defaults to 14
297
+ * days ({@link DEFAULT_SESSION_MAX_AGE_MS}). Milliseconds match the store's
298
+ * `maxAgeMs` and `loginStateTtlMs`; `cookie.maxAge` stays in seconds because
299
+ * that is the unit of the HTTP `Max-Age` attribute it sets.
300
+ *
301
+ * This is the **one** place the lifetime is stated. It sets the session
302
+ * cookie's `Max-Age` (see {@linkcode HonoBffCookieOptions.maxAge}) and, in
303
+ * the default `sessionMode: "own"`, it is enforced on every read: a session
304
+ * older than this is destroyed and its cookie cleared, so the cookie and the
305
+ * record behind it can never disagree about whether the user is signed in.
306
+ * Measured from `createdAt`, so it caps the session absolutely rather than
307
+ * rolling forward with each token refresh. A store that does not persist
308
+ * `createdAt` therefore opts its sessions out of this cap entirely — they
309
+ * never age out. `runSessionStoreContractTests` pins that round-trip, so run
310
+ * it against any store you write.
311
+ *
312
+ * Applies in the default `sessionMode: "own"` only. In
313
+ * `sessionMode: "shared"` the app owns the session record and its cookie's
314
+ * lifetime — often per session (remember-me vs ephemeral) — so this value is
315
+ * ignored there: the BFF writes only an explicit {@linkcode
316
+ * HonoBffCookieOptions.maxAge}, or an ephemeral cookie the app re-stamps.
317
+ *
318
+ * A store that advertises its own bound (see `BoundedSessionStore`, which
319
+ * {@linkcode EncryptedCookieSessionStore} implements) is cross-checked at
320
+ * construction: if the cookie would die before that store stops honoring the
321
+ * session, the constructor throws instead of shipping the mismatch.
322
+ */
323
+ sessionMaxAgeMs?: number;
324
+ /**
325
+ * Where the pending authorization request (`state` → PKCE verifier,
326
+ * return-to) lives, resolved per request. Defaults to the client's
327
+ * configured `authRequestStorage`, which is in-memory unless the client was
328
+ * given something else — fine for a single long-lived process, wrong for any
329
+ * platform that can serve `/auth/login` and `/auth/callback` from different
330
+ * isolates. Pass an {@link EncryptedCookieAuthRequestStorage} to carry the
331
+ * record in an encrypted cookie instead, or implement
332
+ * {@link AuthRequestStorageFactory} over storage of your own.
333
+ *
334
+ * Whatever this resolves to, the pending request is **also** bound to the
335
+ * browser that started it by the login-state cookie, which no option turns
336
+ * off. See {@link loginStateTtlMs}.
337
+ */
338
+ authRequestStorage?: AuthRequestStorageFactory;
339
+ /**
340
+ * How long, in ms, the browser keeps the login-state cookie `/auth/login`
341
+ * sets and `/auth/callback` requires — the `Max-Age` on that cookie, and so
342
+ * the window a started sign-in can still be completed in. Defaults to 10
343
+ * minutes, matching `DirectClient`'s `authRequestTtlMs` default; raise both
344
+ * together, since whichever expires first ends the pending sign-in.
345
+ *
346
+ * The cookie holds only SHA-256 hashes of the `state` values (the three most
347
+ * recent, so parallel sign-ins in several tabs all stay completable), is
348
+ * `HttpOnly`, `SameSite=Lax` — the strictest value that survives the
349
+ * identity provider's redirect back — and inherits {@link cookie}'s
350
+ * `secure` / `path` / `domain` so plain-HTTP local development works.
351
+ */
352
+ loginStateTtlMs?: number;
353
+ /**
354
+ * Who owns the BFF's session record. Defaults to `"own"`.
355
+ *
356
+ * - `"own"` (default): the BFF creates and owns its session at
357
+ * `/auth/callback` — it always mints a fresh id (`sessionStore.create`)
358
+ * and ignores any inbound cookie. Use when the app has no session here
359
+ * until the OAuth flow completes: standalone BFFs, or apps whose login
360
+ * lives on a separate / external IDP.
361
+ * - `"shared"`: the app already created the session at its own login step,
362
+ * and the BFF **attaches** tokens to that existing session at
363
+ * `/auth/callback` (via `sessionStore.update`) instead of creating its
364
+ * own. Set {@link HonoBffCookieOptions.name} to the app's session-cookie
365
+ * name and back `sessionStore` with the app's session record. Use for a
366
+ * colocated first-party SPA that is also its own IDP, so the user has
367
+ * **one** session (login + tokens on one record), not two. If no session
368
+ * cookie is present at the callback the BFF falls back to creating one.
369
+ * `/auth/logout` destroys the whole shared session (a full sign-out).
370
+ * The app's cookie stays the app's: the BFF emits `Set-Cookie` only when
371
+ * the store hands back a **different** value (a stateless store does on
372
+ * every write), never to re-stamp an unchanged one — re-stamping would
373
+ * replace the attributes the app chose, turning a remember-me cookie
374
+ * with a `Max-Age` into a session cookie the browser drops on exit.
375
+ *
376
+ * Note on session fixation: this is the standard "renew the session id on
377
+ * authentication" control. In `"own"` mode the BFF performs the renewal
378
+ * (fresh id at the callback). In `"shared"` mode that responsibility sits
379
+ * with your login step — use a login that mints a fresh session id on
380
+ * success (the typical behavior, e.g. a session service that generates a
381
+ * new id per login) so a pre-planted cookie can't survive authentication.
382
+ */
383
+ sessionMode?: "own" | "shared";
384
+ /** Cookie attribute tweaks. */
385
+ cookie?: HonoBffCookieOptions;
386
+ /**
387
+ * CSRF defense for the credentialed surface. Enabled by default with a
388
+ * `"x-csrf"` header requirement; pass `false` to disable, or an object to
389
+ * customize the header. See {@link HonoBffCsrfOptions}.
390
+ */
391
+ csrf?: HonoBffCsrfOptions | false;
392
+ /**
393
+ * OIDC RP-Initiated Logout. When `true` **and** the configured client knows
394
+ * an end-session endpoint (`endpoints.endSession`, or via discovery),
395
+ * `/auth/logout` — after destroying the local session — additionally
396
+ * redirects the browser to the OP's `end_session_endpoint` with
397
+ * `id_token_hint` (the session's id_token, if any) and a
398
+ * `post_logout_redirect_uri` built from the resolved origin + the
399
+ * open-redirect-guarded `return_to`. This ends the upstream IDP SSO session,
400
+ * not just the local BFF session.
401
+ *
402
+ * Defaults to `false` (local logout only): not every IDP supports it, and it
403
+ * adds a redirect hop. When enabled but no end-session endpoint is known,
404
+ * logout falls back to the plain local redirect and warns once via
405
+ * `console.warn` — a client built from an explicit `endpoints` object with no
406
+ * `endSession` and no `issuer` can never learn one by discovery, so the
407
+ * feature would otherwise no-op silently.
408
+ */
409
+ rpInitiatedLogout?: boolean;
410
+ /**
411
+ * OIDC Back-Channel Logout. When set, `routes()` mounts a
412
+ * `POST /auth/backchannel` receiver that ends the matching server-side
413
+ * session(s) when the OP notifies it. See {@link HonoBffBackchannelOptions}.
414
+ */
415
+ backchannelLogout?: HonoBffBackchannelOptions;
416
+ /** Endpoint paths (within whatever base the caller mounts this under). */
417
+ paths?: HonoBffPaths;
418
+ /**
419
+ * Scope string requested at `/auth/login`, and the scope the login flow
420
+ * records for the authorization request it started.
421
+ *
422
+ * Server-chosen: a browser cannot change it by putting `scope` on the login
423
+ * URL. An application that wants the browser to choose lists `scope` in
424
+ * {@link forwardedParams}, and a forwarded value then **replaces** this one
425
+ * rather than narrowing it. An empty forwarded value counts as none
426
+ * supplied, so this value stands: a login link ending `?scope=` would
427
+ * otherwise send no `scope` at all, leaving an authorization server that
428
+ * defaults an absent scope to pick the grant instead.
429
+ */
430
+ scope?: string;
431
+ /**
432
+ * Extra parameters added to every authorize request `/auth/login` builds —
433
+ * `login_hint`, `ui_locales`, `acr_values`, or whatever else the
434
+ * authorization server accepts, such as a parameter naming the organization
435
+ * a sign-in should land in.
436
+ *
437
+ * Server-chosen: these values are fixed when the BFF is constructed, so they
438
+ * carry the same trust as {@link scope} and nothing a browser sends can
439
+ * change them. When the browser is the one that should choose a parameter's
440
+ * value, name it in {@link forwardedParams} instead.
441
+ *
442
+ * `prompt` is an ordinary name here — pin `{ prompt: "login" }` to make
443
+ * every sign-in re-authenticate. A pinned `scope` is accepted only when
444
+ * {@link scope} is unset; setting both would leave which one applies
445
+ * ambiguous. Either configuration supplies the scope the login flow records
446
+ * for its authorization request.
447
+ *
448
+ * A name the login flow reserves is refused at construction rather than
449
+ * quietly dropped — {@link forwardedParams} carries the list and the reason.
450
+ *
451
+ * @example Pin every sign-in to one organization
452
+ * ```ts
453
+ * declare const client: DirectClient;
454
+ *
455
+ * const bff = new HonoBff({ client, extraParams: { organization: "acme" } });
456
+ * ```
457
+ */
458
+ extraParams?: Record<string, string>;
459
+ /**
460
+ * Names of extra authorize parameters `/auth/login` may take off its own
461
+ * query string. Empty by default, so a parameter that is not listed here is
462
+ * not forwarded no matter who puts it on the login URL — `scope` and
463
+ * `prompt` included. `routes()` serves login at `GET` and `POST` alike, and
464
+ * both read the query string only, never a request body.
465
+ *
466
+ * Browser-chosen, and so untrusted: whatever a browser puts in
467
+ * `/auth/login?<name>=…` reaches the authorization server verbatim, and the
468
+ * BFF checks nothing but the name. The test to apply is not "does the
469
+ * authorization server validate this parameter" but **"would I accept every
470
+ * value it could carry"** — the two are different properties, and a
471
+ * parameter can pass the first and fail the second. `acr_values` and
472
+ * `max_age` are refused here, case-insensitively, because browser choices
473
+ * could weaken assurance or lengthen the re-authentication window. Pin these
474
+ * controls in {@link extraParams}, which no browser can change.
475
+ *
476
+ * A parameter already baked into the configured authorization endpoint's
477
+ * own query string is overridable this way too, and silently: the client
478
+ * keeps that query string and then sets each extra parameter over it. The
479
+ * reserved list below cannot know a name a deployment baked into its
480
+ * endpoint URL, so check that URL before listing anything here.
481
+ *
482
+ * Reserved on this option and on {@link extraParams} alike, and refused when
483
+ * the BFF is constructed — matched case-insensitively, since an
484
+ * authorization server that folds parameter-name case would otherwise make
485
+ * `Client_Id` a way around the list:
486
+ *
487
+ * - `response_type`, `client_id`, `redirect_uri`, `state`,
488
+ * `code_challenge`, `code_challenge_method` — the client mints or derives
489
+ * each one for the single sign-in in progress, and a supplied value
490
+ * replaces it, which variously redirects the authorization code, breaks
491
+ * the PKCE binding the token exchange depends on, or unpicks the `state`
492
+ * the login-state cookie commits to.
493
+ * - `response_mode` — moves the authorization response out of the callback
494
+ * URL's query string, the only place `/auth/callback` reads it from.
495
+ * - `nonce` — this client neither sends nor verifies one, so a supplied
496
+ * value would look like replay protection that nothing checks.
497
+ * - `request`, `request_uri` — a request object supersedes the parameters
498
+ * beside it at an authorization server implementing RFC 9101, which puts
499
+ * every name above back within reach.
500
+ *
501
+ * Naming the same parameter both here and in {@link extraParams} is refused
502
+ * as well: one pins the value every sign-in carries and the other lets the
503
+ * browser choose it, so which one applies would be ambiguous.
504
+ *
505
+ * `scope` and `prompt` are ordinary names on this option, and the two worth
506
+ * the most thought before listing. Listing `scope` lets whoever writes the
507
+ * login link choose the breadth of the grant the session is minted with:
508
+ * the value replaces {@link scope} rather than narrowing it, bounded only
509
+ * by what the authorization server will grant this client. An empty `scope`
510
+ * is the one exception, and counts as absent so {@link scope} stands.
511
+ * Listing `prompt` hands over the authentication ceremony instead of the
512
+ * grant — it is what a SPA needs to start a silent renew with
513
+ * `/auth/login?prompt=none`, and the same entry lets a link suppress a
514
+ * re-authentication the application meant to force. Where the deployment should decide either one, use
515
+ * {@link scope} or a pinned {@link extraParams} entry, which no browser can
516
+ * reach.
517
+ *
518
+ * @example Let a sign-in link choose the organization
519
+ * ```ts
520
+ * declare const client: DirectClient;
521
+ *
522
+ * const bff = new HonoBff({ client, forwardedParams: ["organization"] });
523
+ * ```
524
+ *
525
+ * A link to `/auth/login?organization=acme&return_to=/dashboard` then
526
+ * reaches the authorization server as `…&organization=acme`.
527
+ */
528
+ forwardedParams?: readonly string[];
529
+ /** Default `return_to` applied when the browser doesn't pass one. */
530
+ defaultReturnTo?: string;
531
+ /**
532
+ * Optional hook run after the authorization code is exchanged. Lets
533
+ * apps enrich the session with database-backed user info before the
534
+ * session cookie is set.
535
+ */
536
+ resolveUser?: (tokens: TokenBundle, idTokenClaims: UserInfoClaims | null) => Promise<UserInfoClaims | null> | UserInfoClaims | null;
537
+ /**
538
+ * Optional hook invoked when `/auth/callback` cannot complete the sign-in
539
+ * (see {@link BffCallbackError} for the cases). The browser reaches the
540
+ * callback via a full-page navigation, so the default JSON `400` is not
541
+ * user-friendly — return a redirect to a sign-in/error page instead, e.g.
542
+ * `c.redirect(`/sign-in?error=${err.error}`)`. When omitted, the BFF responds
543
+ * with a `400` JSON body `{ error, error_description }`.
544
+ */
545
+ onCallbackError?: (c: Context, error: BffCallbackError) => Response | Promise<Response>;
546
+ /**
547
+ * Clock skew (seconds) applied when deciding whether the access token
548
+ * is close enough to expiry that {@link HonoBff.attachToken} should
549
+ * refresh proactively. Defaults to 30s.
550
+ */
551
+ refreshSkewSeconds?: number;
552
+ /**
553
+ * Optional resource server. When provided, {@link HonoBff.protect}
554
+ * becomes available — a single middleware that composes
555
+ * {@link HonoBff.attachToken} with `resourceServer.protect(scope)`.
556
+ *
557
+ * Pass a {@link HonoAuthorizationServer} for own-issuer co-located
558
+ * deployments (validation happens against the in-process token service)
559
+ * or a {@link HonoResourceServer} for third-party-issuer deployments
560
+ * (validation goes through `IntrospectionTokenReader`).
561
+ */
562
+ resourceServer?: HonoBffResourceServer;
563
+ /**
564
+ * Resolves the per-request origin (scheme + host) used to build the
565
+ * browser-facing authorize URL and `redirect_uri`. Lets ONE build-once BFF
566
+ * serve every deployment host (preview URLs, multi-tenant subdomains): the
567
+ * configured client's authorize/redirect paths are retargeted at this
568
+ * origin per request. Return only allowlisted/trusted origins (never a raw
569
+ * forged `Host`). When omitted, the client's configured origin is used.
570
+ */
571
+ resolveOrigin?: (c: Context) => string;
572
+ /**
573
+ * Derive the OAuth2 `redirect_uri` from the mounted callback path instead of
574
+ * requiring it in the client config. When `true`, every login/callback uses
575
+ * `redirect_uri = <origin><callback path>` (origin from {@link resolveOrigin},
576
+ * else the request's). The same value is sent at authorize and at the token
577
+ * exchange (RFC 6749 §4.1.3), re-derived from the request each time. Pairs
578
+ * with an `issuer`-configured client (discovery) for a BFF you configure by
579
+ * issuer alone — no restated endpoints or redirect URI. Defaults to `false`
580
+ * (use the client's configured `redirectUri`).
581
+ */
582
+ deriveRedirectUri?: boolean;
583
+ }
584
+ /**
585
+ * Backend-for-Frontend adapter for Hono. Construct once per app, mount
586
+ * `routes()` under `/auth`, and use `attachToken()` as middleware on
587
+ * protected API routes. Apps that own their login surface (a custom sign-in
588
+ * form, create-account, forgot-password) call `loginContinuation()` to hand
589
+ * back to the OAuth2 flow after authenticating a user.
590
+ */
591
+ export declare class HonoBff {
592
+ #private;
593
+ /**
594
+ * Defaults are applied for the session store ({@linkcode MemorySessionStore}),
595
+ * session mode (`"own"`), cookie name, and CSRF.
596
+ *
597
+ * @throws {Error} When {@linkcode HonoBffOptions.backchannelLogout} is
598
+ * configured against a store that cannot enumerate sessions (e.g.
599
+ * {@linkcode EncryptedCookieSessionStore}), when an explicit
600
+ * {@linkcode HonoBffCookieOptions.name} carries a `__Host-`/`__Secure-`
601
+ * prefix the other cookie options contradict, when
602
+ * {@linkcode HonoBffCookieOptions.sameSite} is `"None"` without
603
+ * {@linkcode HonoBffCookieOptions.secure}, when any
604
+ * {@linkcode HonoBffPaths} entry falls outside a non-empty
605
+ * {@linkcode HonoBffPaths.basePath}, when the session cookie would die
606
+ * before the session behind it (see
607
+ * {@linkcode HonoBffOptions.sessionMaxAgeMs}), or when
608
+ * {@linkcode HonoBffOptions.extraParams} or
609
+ * {@linkcode HonoBffOptions.forwardedParams} names a reserved authorize
610
+ * parameter, gives one a name that is empty or not equal to its trimmed
611
+ * form (`" state"` and `"organization "` are refused rather than trimmed),
612
+ * names the same parameter in both, or pins `scope` in
613
+ * {@linkcode HonoBffOptions.extraParams} while
614
+ * {@linkcode HonoBffOptions.scope} is also set.
615
+ */
616
+ constructor(options: HonoBffOptions);
617
+ /**
618
+ * Cookie name used for the session cookie. Read-only; configured via
619
+ * {@link HonoBffOptions.cookie}.
620
+ */
621
+ get cookieName(): string;
622
+ /**
623
+ * Name of the cookie `/auth/login` binds the pending sign-in's `state` to
624
+ * and `/auth/callback` requires. Read-only; derived from
625
+ * {@link HonoBffOptions.cookie}'s `secure` / `path` / `domain` (it carries
626
+ * the `__Host-` prefix whenever they allow it). A test that drives the
627
+ * login flow by hand must carry this cookie from the login response into
628
+ * the callback request, exactly as a browser would.
629
+ */
630
+ get loginStateCookieName(): string;
631
+ /**
632
+ * The CSRF header name required on credentialed requests, or `undefined`
633
+ * when CSRF is disabled. Useful in tests that seed a session and then call a
634
+ * protected route — they must send `{ [bff.csrfHeaderName!]: "1" }` alongside
635
+ * the cookie. The shipped `BffClient` / React adapter send it
636
+ * automatically in real apps.
637
+ */
638
+ get csrfHeaderName(): string | undefined;
639
+ /**
640
+ * The underlying session store. Exposed primarily for testing helpers
641
+ * (e.g. seeding a session directly without driving the login flow);
642
+ * production code should not reach in here.
643
+ */
644
+ get sessionStore(): SessionStore;
645
+ /**
646
+ * Returns a Hono app with all session endpoints mounted, each registered
647
+ * relative to {@link HonoBffPaths.basePath} (default `/auth`). Mount it under
648
+ * that same base — `app.route("/auth", bff.routes())` — so the served URLs
649
+ * are the configured {@link HonoBffPaths}. To mount at the app root instead,
650
+ * set `paths.basePath` to `""`.
651
+ */
652
+ routes(): Hono;
653
+ /**
654
+ * Builds the URL that (re)starts sign-in toward `returnTo`, for an app that
655
+ * owns its login surface (a custom sign-in form, create-account,
656
+ * forgot-password) and needs to hand back to the OAuth2/BFF flow after it
657
+ * authenticates the user.
658
+ *
659
+ * - When `returnTo` is an **in-flight authorize URL** — its path matches the
660
+ * client's authorization endpoint, i.e. the user was bounced to your login
661
+ * surface mid-authorize with the PKCE `state` already minted — it is
662
+ * returned unchanged so the flow **resumes** without a redundant
663
+ * `/auth/login` hop.
664
+ * - Otherwise it returns `${login}?return_to=<returnTo>` so the BFF **starts**
665
+ * a fresh login (mints `state` at the login endpoint, attaches tokens to the
666
+ * session at the callback).
667
+ *
668
+ * `returnTo` is open-redirect-guarded (`safeReturnTo`), so the result is
669
+ * always a safe same-origin path. This is the mechanism of the own-auth + BFF
670
+ * topology; the credential form, validation, and copy stay in your app. It
671
+ * replaces hand-rolled helpers that hardcode the authorize + login paths —
672
+ * the BFF already knows both from its client config and `paths`.
673
+ *
674
+ * ```ts
675
+ * // after your sign-in / create-account action authenticates the user:
676
+ * return c.redirect(bff.loginContinuation(returnTo));
677
+ * ```
678
+ *
679
+ * Note: the in-flight-authorize check needs the client's authorization
680
+ * endpoint to be known synchronously (an explicit `endpoints.authorization`,
681
+ * or after `client.discover()` has run). For an issuer-only client that has
682
+ * not discovered yet, every `returnTo` is treated as "start a fresh login".
683
+ */
684
+ loginContinuation(returnTo: string | null | undefined): string;
685
+ /**
686
+ * Login handler — builds the authorize URL, binds the `state` it minted to
687
+ * this browser with the login-state cookie, and redirects the browser.
688
+ *
689
+ * The authorize request carries every {@link HonoBffOptions.extraParams}
690
+ * entry, plus each {@link HonoBffOptions.forwardedParams} name this
691
+ * request's query string supplies a value for. Nothing else off this
692
+ * request's query string reaches the authorize URL: `scope` falls back to
693
+ * {@link HonoBffOptions.scope} and `prompt` is sent only when one of those
694
+ * two options supplies it.
695
+ */
696
+ loginHandler(): Handler;
697
+ /**
698
+ * Callback handler — requires the login-state cookie to vouch for the
699
+ * returned `state`, then exchanges the code and opens a session.
700
+ */
701
+ callbackHandler(): Handler;
702
+ /** Logout handler — revokes the refresh token and clears the session cookie. */
703
+ logoutHandler(): Handler;
704
+ /** Session probe — returns `{ isAuthenticated, user }` without tokens. */
705
+ sessionHandler(): Handler;
706
+ /**
707
+ * OIDC Back-Channel Logout receiver. A server-to-server `POST` from the OP
708
+ * carrying a signed `logout_token`; the configured verifier validates it (and
709
+ * returns the subject / OP session id), then the matching server-side
710
+ * session(s) are destroyed. Responds `200` on success and `400` on a
711
+ * missing/invalid token, with `Cache-Control: no-store`, per the spec.
712
+ */
713
+ backchannelHandler(): Handler;
714
+ /**
715
+ * Middleware that reads the session cookie, refreshes the access token
716
+ * if it's near expiry, and sets `Authorization: Bearer <token>` on the
717
+ * inbound request so downstream middleware can read it from the
718
+ * standard header.
719
+ *
720
+ * Prefer {@link protect} for the common case — it authenticates against
721
+ * the configured `resourceServer` directly without mutating the
722
+ * request, so middleware ordering doesn't matter. Reach for
723
+ * `attachToken` only when composing with downstream middleware that
724
+ * expects a bearer token in the `Authorization` header (e.g. a custom
725
+ * resource-server-like guard, or an in-process proxy).
726
+ *
727
+ * **Ordering caveat**: mount `attachToken` *before* any middleware
728
+ * that reads the request body (CSRF parsers, validators, etc.).
729
+ * `attachToken` replaces `c.req.raw` with a clone that carries the
730
+ * Authorization header, which transfers the body stream from the
731
+ * original Request to the clone. Downstream middleware that reads
732
+ * through `c.req` is fine; middleware that captured a pre-clone
733
+ * reference to `c.req.raw` will see a "used" body on it.
734
+ *
735
+ * Unauthenticated requests fall through without a header — the
736
+ * downstream guard returns the proper 401 with `WWW-Authenticate`.
737
+ */
738
+ attachToken(): MiddlewareHandler;
739
+ /**
740
+ * Returns a Hono middleware that asserts an **already-authenticated**
741
+ * request (guarded upstream by {@link protect}) carries `requiredScope`,
742
+ * **without** re-validating the token — the per-route companion to
743
+ * `protect` for mounts whose routes need different scopes (e.g. `read` vs
744
+ * `write`). Delegates to the configured resource server's `requireScope`;
745
+ * see {@link HonoResourceServer.requireScope}.
746
+ *
747
+ * @throws {Error} When the BFF was constructed without a `resourceServer` —
748
+ * thrown when the middleware is built, not per request.
749
+ *
750
+ * @example
751
+ * ```ts
752
+ * app.use("/api/*", bff.protect()); // session cookie OR bearer
753
+ * app.get("/api/items", bff.requireScope("read"), list);
754
+ * app.post("/api/items", bff.requireScope("write"), create);
755
+ * ```
756
+ */
757
+ requireScope(requiredScope: string): MiddlewareHandler;
758
+ /**
759
+ * Middleware that authenticates the request against the configured
760
+ * `resourceServer`, accepting **either** auth style so one guard protects an
761
+ * API used by both the BFF's own frontend and machine-to-machine clients:
762
+ *
763
+ * - **Browser frontend** — no `Authorization` header; the access token is
764
+ * resolved from the BFF session cookie (refreshed if near expiry) and
765
+ * validated. Available only when the BFF was constructed with a
766
+ * `resourceServer` option.
767
+ * - **Machine-to-machine** — an inbound `Authorization: Bearer <token>` is
768
+ * validated directly (e.g. a `client_credentials` token), so direct API
769
+ * clients work without a session cookie.
770
+ *
771
+ * Unlike `attachToken + resourceServer.protect()`, this does **not**
772
+ * mutate `c.req.raw` for the session path — the token is read from the
773
+ * session and handed to `resourceServer.authenticate()` directly, so
774
+ * middleware ordering doesn't matter and earlier middleware that already
775
+ * touched the request body is unaffected.
776
+ *
777
+ * ```ts
778
+ * app.use("/api/*", bff.protect("read")); // session cookie OR bearer token
779
+ * ```
780
+ *
781
+ * Without `resourceServer` configured, throws an error with a hint to
782
+ * either pass `resourceServer` or compose the middleware chain manually
783
+ * (`app.use(bff.attachToken(), resourceServer.protect(scope))`).
784
+ */
785
+ protect(requiredScope?: string): MiddlewareHandler;
786
+ /**
787
+ * Handler that forwards the request to a **separate** resource server with
788
+ * the session's access token attached, and streams the response back — the
789
+ * full-proxy BFF of the IETF "OAuth 2.0 for Browser-Based Apps" BCP §6.1.1.
790
+ * Tokens stay server-side and the browser only ever talks to its own origin,
791
+ * so there is no CORS to configure.
792
+ *
793
+ * Reach for this when the API lives in another service. When the resource
794
+ * server is co-located in the same process, {@link protect} is faster and
795
+ * simpler — it validates in-process with no outbound HTTP.
796
+ *
797
+ * Mount it as a catch-all and strip the mount prefix:
798
+ *
799
+ * @example
800
+ * ```ts
801
+ * app.all(
802
+ * "/api/*",
803
+ * bff.proxy("https://api.example.com/v1", { stripPrefix: "/api" }),
804
+ * );
805
+ * ```
806
+ *
807
+ * Semantics:
808
+ *
809
+ * - **Session only.** The access token comes from the session cookie
810
+ * (refreshed when within {@link HonoBffOptions.refreshSkewSeconds} of
811
+ * expiry, exactly as {@link protect} does). An inbound `Authorization`
812
+ * header is *not* honored and never forwarded — point machine-to-machine
813
+ * clients at the resource server directly. No session is `401`
814
+ * `invalid_token`.
815
+ * - **CSRF.** The same custom-header check the rest of the credentialed BFF
816
+ * surface enforces, so mounting a proxy cannot reopen it. See
817
+ * {@link HonoBffCsrfOptions}.
818
+ * - **Retry.** An upstream `401` carrying `error="invalid_token"` triggers
819
+ * one refresh-and-retry, when the session has a refresh token. A refresh
820
+ * the authorization server rejects clears the session and answers `401`; a
821
+ * refresh that merely fails to complete (network error, 5xx, 429) leaves
822
+ * the session intact and answers `502` `temporarily_unavailable`. Bodied
823
+ * requests are not retried (the body was streamed). Disable with
824
+ * `retryOn401: false`.
825
+ * - **Headers.** Only {@link DEFAULT_PROXY_FORWARD_HEADERS} (or your
826
+ * `forwardHeaders`) travel upstream; the session cookie, inbound
827
+ * `Authorization`, and hop-by-hop headers never do. Coming back, upstream
828
+ * `Set-Cookie` and hop-by-hop headers are dropped and everything else —
829
+ * including problem-details error bodies and their status — is passed
830
+ * through verbatim.
831
+ * - **Bodies stream** in both directions; nothing is buffered. Upstream
832
+ * redirects are returned to the browser rather than followed, so the token
833
+ * is never replayed to a `Location` the BFF did not vet.
834
+ *
835
+ * A `502` with `temporarily_unavailable` is returned when the upstream
836
+ * cannot be reached, and a `400` `invalid_request` when a path segment has a
837
+ * malformed percent-escape or hides a `..`.
838
+ *
839
+ * **Ordering caveat**: mount this before any middleware that reads the
840
+ * request body — the proxy forwards `c.req.raw.body` as a stream, and a
841
+ * middleware that already consumed it leaves nothing to forward.
842
+ *
843
+ * @param target Upstream base URL. Fixed here, never derived from the
844
+ * request, so the proxy cannot be steered at another host. Query parameters
845
+ * pinned on it are merged into every proxied request and win over an inbound
846
+ * parameter of the same name.
847
+ * @param options Prefix stripping, header allowlist, retry, and `fetch`
848
+ * injection. See {@link HonoBffProxyOptions}.
849
+ * @returns A Hono handler to mount on a catch-all route.
850
+ */
851
+ proxy(target: string | URL, options?: HonoBffProxyOptions): Handler;
852
+ }