@atproto/oauth-provider 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 (631) hide show
  1. package/.postcssrc.yml +3 -0
  2. package/CHANGELOG.md +19 -0
  3. package/LICENSE.txt +7 -0
  4. package/dist/access-token/access-token-type.d.ts +6 -0
  5. package/dist/access-token/access-token-type.d.ts.map +1 -0
  6. package/dist/access-token/access-token-type.js +10 -0
  7. package/dist/access-token/access-token-type.js.map +1 -0
  8. package/dist/account/account-manager.d.ts +14 -0
  9. package/dist/account/account-manager.d.ts.map +1 -0
  10. package/dist/account/account-manager.js +39 -0
  11. package/dist/account/account-manager.js.map +1 -0
  12. package/dist/account/account-store.d.ts +39 -0
  13. package/dist/account/account-store.d.ts.map +1 -0
  14. package/dist/account/account-store.js +19 -0
  15. package/dist/account/account-store.js.map +1 -0
  16. package/dist/account/account.d.ts +8 -0
  17. package/dist/account/account.d.ts.map +1 -0
  18. package/dist/account/account.js +3 -0
  19. package/dist/account/account.js.map +1 -0
  20. package/dist/assets/app/bundle-manifest.json +22 -0
  21. package/dist/assets/app/main.css +3 -0
  22. package/dist/assets/app/main.js +20 -0
  23. package/dist/assets/app/main.js.map +1 -0
  24. package/dist/assets/asset.d.ts +9 -0
  25. package/dist/assets/asset.d.ts.map +1 -0
  26. package/dist/assets/asset.js +3 -0
  27. package/dist/assets/asset.js.map +1 -0
  28. package/dist/assets/assets-middleware.d.ts +2 -0
  29. package/dist/assets/assets-middleware.d.ts.map +1 -0
  30. package/dist/assets/assets-middleware.js +30 -0
  31. package/dist/assets/assets-middleware.js.map +1 -0
  32. package/dist/assets/index.d.ts +4 -0
  33. package/dist/assets/index.d.ts.map +1 -0
  34. package/dist/assets/index.js +65 -0
  35. package/dist/assets/index.js.map +1 -0
  36. package/dist/client/client-auth.d.ts +13 -0
  37. package/dist/client/client-auth.d.ts.map +1 -0
  38. package/dist/client/client-auth.js +35 -0
  39. package/dist/client/client-auth.js.map +1 -0
  40. package/dist/client/client-data.d.ts +8 -0
  41. package/dist/client/client-data.d.ts.map +1 -0
  42. package/dist/client/client-data.js +3 -0
  43. package/dist/client/client-data.js.map +1 -0
  44. package/dist/client/client-id.d.ts +4 -0
  45. package/dist/client/client-id.d.ts.map +1 -0
  46. package/dist/client/client-id.js +6 -0
  47. package/dist/client/client-id.js.map +1 -0
  48. package/dist/client/client-info.d.ts +13 -0
  49. package/dist/client/client-info.d.ts.map +1 -0
  50. package/dist/client/client-info.js +3 -0
  51. package/dist/client/client-info.js.map +1 -0
  52. package/dist/client/client-manager.d.ts +38 -0
  53. package/dist/client/client-manager.d.ts.map +1 -0
  54. package/dist/client/client-manager.js +534 -0
  55. package/dist/client/client-manager.js.map +1 -0
  56. package/dist/client/client-store.d.ts +13 -0
  57. package/dist/client/client-store.d.ts.map +1 -0
  58. package/dist/client/client-store.js +39 -0
  59. package/dist/client/client-store.js.map +1 -0
  60. package/dist/client/client-utils.d.ts +6 -0
  61. package/dist/client/client-utils.d.ts.map +1 -0
  62. package/dist/client/client-utils.js +40 -0
  63. package/dist/client/client-utils.js.map +1 -0
  64. package/dist/client/client.d.ts +41 -0
  65. package/dist/client/client.d.ts.map +1 -0
  66. package/dist/client/client.js +163 -0
  67. package/dist/client/client.js.map +1 -0
  68. package/dist/constants.d.ts +42 -0
  69. package/dist/constants.d.ts.map +1 -0
  70. package/dist/constants.js +53 -0
  71. package/dist/constants.js.map +1 -0
  72. package/dist/device/device-data.d.ts +20 -0
  73. package/dist/device/device-data.d.ts.map +1 -0
  74. package/dist/device/device-data.js +11 -0
  75. package/dist/device/device-data.js.map +1 -0
  76. package/dist/device/device-details.d.ts +17 -0
  77. package/dist/device/device-details.d.ts.map +1 -0
  78. package/dist/device/device-details.js +34 -0
  79. package/dist/device/device-details.js.map +1 -0
  80. package/dist/device/device-id.d.ts +6 -0
  81. package/dist/device/device-id.d.ts.map +1 -0
  82. package/dist/device/device-id.js +18 -0
  83. package/dist/device/device-id.js.map +1 -0
  84. package/dist/device/device-manager.d.ts +88 -0
  85. package/dist/device/device-manager.d.ts.map +1 -0
  86. package/dist/device/device-manager.js +206 -0
  87. package/dist/device/device-manager.js.map +1 -0
  88. package/dist/device/device-store.d.ts +15 -0
  89. package/dist/device/device-store.d.ts.map +1 -0
  90. package/dist/device/device-store.js +36 -0
  91. package/dist/device/device-store.js.map +1 -0
  92. package/dist/device/session-id.d.ts +6 -0
  93. package/dist/device/session-id.d.ts.map +1 -0
  94. package/dist/device/session-id.js +18 -0
  95. package/dist/device/session-id.js.map +1 -0
  96. package/dist/dpop/dpop-manager.d.ts +33 -0
  97. package/dist/dpop/dpop-manager.d.ts.map +1 -0
  98. package/dist/dpop/dpop-manager.js +115 -0
  99. package/dist/dpop/dpop-manager.js.map +1 -0
  100. package/dist/dpop/dpop-nonce.d.ts +13 -0
  101. package/dist/dpop/dpop-nonce.d.ts.map +1 -0
  102. package/dist/dpop/dpop-nonce.js +94 -0
  103. package/dist/dpop/dpop-nonce.js.map +1 -0
  104. package/dist/errors/access-denied-error.d.ts +8 -0
  105. package/dist/errors/access-denied-error.d.ts.map +1 -0
  106. package/dist/errors/access-denied-error.js +21 -0
  107. package/dist/errors/access-denied-error.js.map +1 -0
  108. package/dist/errors/account-selection-required-error.d.ts +6 -0
  109. package/dist/errors/account-selection-required-error.d.ts.map +1 -0
  110. package/dist/errors/account-selection-required-error.js +11 -0
  111. package/dist/errors/account-selection-required-error.js.map +1 -0
  112. package/dist/errors/consent-required-error.d.ts +6 -0
  113. package/dist/errors/consent-required-error.d.ts.map +1 -0
  114. package/dist/errors/consent-required-error.js +11 -0
  115. package/dist/errors/consent-required-error.js.map +1 -0
  116. package/dist/errors/invalid-authorization-details-error.d.ts +20 -0
  117. package/dist/errors/invalid-authorization-details-error.d.ts.map +1 -0
  118. package/dist/errors/invalid-authorization-details-error.js +26 -0
  119. package/dist/errors/invalid-authorization-details-error.js.map +1 -0
  120. package/dist/errors/invalid-client-error.d.ts +18 -0
  121. package/dist/errors/invalid-client-error.d.ts.map +1 -0
  122. package/dist/errors/invalid-client-error.js +24 -0
  123. package/dist/errors/invalid-client-error.js.map +1 -0
  124. package/dist/errors/invalid-client-id-error.d.ts +13 -0
  125. package/dist/errors/invalid-client-id-error.d.ts.map +1 -0
  126. package/dist/errors/invalid-client-id-error.js +25 -0
  127. package/dist/errors/invalid-client-id-error.js.map +1 -0
  128. package/dist/errors/invalid-client-metadata-error.d.ts +13 -0
  129. package/dist/errors/invalid-client-metadata-error.d.ts.map +1 -0
  130. package/dist/errors/invalid-client-metadata-error.js +23 -0
  131. package/dist/errors/invalid-client-metadata-error.js.map +1 -0
  132. package/dist/errors/invalid-dpop-key-binding-error.d.ts +12 -0
  133. package/dist/errors/invalid-dpop-key-binding-error.d.ts.map +1 -0
  134. package/dist/errors/invalid-dpop-key-binding-error.js +20 -0
  135. package/dist/errors/invalid-dpop-key-binding-error.js.map +1 -0
  136. package/dist/errors/invalid-dpop-proof-error.d.ts +5 -0
  137. package/dist/errors/invalid-dpop-proof-error.d.ts.map +1 -0
  138. package/dist/errors/invalid-dpop-proof-error.js +12 -0
  139. package/dist/errors/invalid-dpop-proof-error.js.map +1 -0
  140. package/dist/errors/invalid-grant-error.d.ts +14 -0
  141. package/dist/errors/invalid-grant-error.d.ts.map +1 -0
  142. package/dist/errors/invalid-grant-error.js +20 -0
  143. package/dist/errors/invalid-grant-error.js.map +1 -0
  144. package/dist/errors/invalid-parameters-error.d.ts +6 -0
  145. package/dist/errors/invalid-parameters-error.d.ts.map +1 -0
  146. package/dist/errors/invalid-parameters-error.js +11 -0
  147. package/dist/errors/invalid-parameters-error.js.map +1 -0
  148. package/dist/errors/invalid-redirect-uri-error.d.ts +11 -0
  149. package/dist/errors/invalid-redirect-uri-error.d.ts.map +1 -0
  150. package/dist/errors/invalid-redirect-uri-error.js +21 -0
  151. package/dist/errors/invalid-redirect-uri-error.js.map +1 -0
  152. package/dist/errors/invalid-request-error.d.ts +28 -0
  153. package/dist/errors/invalid-request-error.d.ts.map +1 -0
  154. package/dist/errors/invalid-request-error.js +34 -0
  155. package/dist/errors/invalid-request-error.js.map +1 -0
  156. package/dist/errors/invalid-token-error.d.ts +16 -0
  157. package/dist/errors/invalid-token-error.d.ts.map +1 -0
  158. package/dist/errors/invalid-token-error.js +45 -0
  159. package/dist/errors/invalid-token-error.js.map +1 -0
  160. package/dist/errors/login-required-error.d.ts +6 -0
  161. package/dist/errors/login-required-error.d.ts.map +1 -0
  162. package/dist/errors/login-required-error.js +11 -0
  163. package/dist/errors/login-required-error.js.map +1 -0
  164. package/dist/errors/oauth-error.d.ts +13 -0
  165. package/dist/errors/oauth-error.d.ts.map +1 -0
  166. package/dist/errors/oauth-error.js +29 -0
  167. package/dist/errors/oauth-error.js.map +1 -0
  168. package/dist/errors/unauthorized-client-error.d.ts +18 -0
  169. package/dist/errors/unauthorized-client-error.d.ts.map +1 -0
  170. package/dist/errors/unauthorized-client-error.js +24 -0
  171. package/dist/errors/unauthorized-client-error.js.map +1 -0
  172. package/dist/errors/use-dpop-nonce-error.d.ts +18 -0
  173. package/dist/errors/use-dpop-nonce-error.d.ts.map +1 -0
  174. package/dist/errors/use-dpop-nonce-error.js +27 -0
  175. package/dist/errors/use-dpop-nonce-error.js.map +1 -0
  176. package/dist/errors/www-authenticate-error.d.ts +9 -0
  177. package/dist/errors/www-authenticate-error.d.ts.map +1 -0
  178. package/dist/errors/www-authenticate-error.js +46 -0
  179. package/dist/errors/www-authenticate-error.js.map +1 -0
  180. package/dist/index.d.ts +14 -0
  181. package/dist/index.d.ts.map +1 -0
  182. package/dist/index.js +31 -0
  183. package/dist/index.js.map +1 -0
  184. package/dist/lib/html/build-document.d.ts +32 -0
  185. package/dist/lib/html/build-document.d.ts.map +1 -0
  186. package/dist/lib/html/build-document.js +61 -0
  187. package/dist/lib/html/build-document.js.map +1 -0
  188. package/dist/lib/html/escapers.d.ts +9 -0
  189. package/dist/lib/html/escapers.d.ts.map +1 -0
  190. package/dist/lib/html/escapers.js +66 -0
  191. package/dist/lib/html/escapers.js.map +1 -0
  192. package/dist/lib/html/html.d.ts +13 -0
  193. package/dist/lib/html/html.d.ts.map +1 -0
  194. package/dist/lib/html/html.js +53 -0
  195. package/dist/lib/html/html.js.map +1 -0
  196. package/dist/lib/html/index.d.ts +4 -0
  197. package/dist/lib/html/index.d.ts.map +1 -0
  198. package/dist/lib/html/index.js +21 -0
  199. package/dist/lib/html/index.js.map +1 -0
  200. package/dist/lib/html/tags.d.ts +34 -0
  201. package/dist/lib/html/tags.d.ts.map +1 -0
  202. package/dist/lib/html/tags.js +47 -0
  203. package/dist/lib/html/tags.js.map +1 -0
  204. package/dist/lib/html/util.d.ts +4 -0
  205. package/dist/lib/html/util.d.ts.map +1 -0
  206. package/dist/lib/html/util.js +20 -0
  207. package/dist/lib/html/util.js.map +1 -0
  208. package/dist/lib/http/accept.d.ts +29 -0
  209. package/dist/lib/http/accept.d.ts.map +1 -0
  210. package/dist/lib/http/accept.js +67 -0
  211. package/dist/lib/http/accept.js.map +1 -0
  212. package/dist/lib/http/context.d.ts +5 -0
  213. package/dist/lib/http/context.d.ts.map +1 -0
  214. package/dist/lib/http/context.js +10 -0
  215. package/dist/lib/http/context.js.map +1 -0
  216. package/dist/lib/http/index.d.ts +10 -0
  217. package/dist/lib/http/index.d.ts.map +1 -0
  218. package/dist/lib/http/index.js +26 -0
  219. package/dist/lib/http/index.js.map +1 -0
  220. package/dist/lib/http/method.d.ts +6 -0
  221. package/dist/lib/http/method.d.ts.map +1 -0
  222. package/dist/lib/http/method.js +19 -0
  223. package/dist/lib/http/method.js.map +1 -0
  224. package/dist/lib/http/middleware.d.ts +18 -0
  225. package/dist/lib/http/middleware.d.ts.map +1 -0
  226. package/dist/lib/http/middleware.js +118 -0
  227. package/dist/lib/http/middleware.js.map +1 -0
  228. package/dist/lib/http/parser.d.ts +33 -0
  229. package/dist/lib/http/parser.d.ts.map +1 -0
  230. package/dist/lib/http/parser.js +48 -0
  231. package/dist/lib/http/parser.js.map +1 -0
  232. package/dist/lib/http/path.d.ts +9 -0
  233. package/dist/lib/http/path.d.ts.map +1 -0
  234. package/dist/lib/http/path.js +54 -0
  235. package/dist/lib/http/path.js.map +1 -0
  236. package/dist/lib/http/request.d.ts +33 -0
  237. package/dist/lib/http/request.d.ts.map +1 -0
  238. package/dist/lib/http/request.js +86 -0
  239. package/dist/lib/http/request.js.map +1 -0
  240. package/dist/lib/http/response.d.ts +13 -0
  241. package/dist/lib/http/response.d.ts.map +1 -0
  242. package/dist/lib/http/response.js +98 -0
  243. package/dist/lib/http/response.js.map +1 -0
  244. package/dist/lib/http/route.d.ts +25 -0
  245. package/dist/lib/http/route.d.ts.map +1 -0
  246. package/dist/lib/http/route.js +39 -0
  247. package/dist/lib/http/route.js.map +1 -0
  248. package/dist/lib/http/router.d.ts +32 -0
  249. package/dist/lib/http/router.d.ts.map +1 -0
  250. package/dist/lib/http/router.js +74 -0
  251. package/dist/lib/http/router.js.map +1 -0
  252. package/dist/lib/http/stream.d.ts +13 -0
  253. package/dist/lib/http/stream.d.ts.map +1 -0
  254. package/dist/lib/http/stream.js +46 -0
  255. package/dist/lib/http/stream.js.map +1 -0
  256. package/dist/lib/http/types.d.ts +7 -0
  257. package/dist/lib/http/types.d.ts.map +1 -0
  258. package/dist/lib/http/types.js +3 -0
  259. package/dist/lib/http/types.js.map +1 -0
  260. package/dist/lib/http/url.d.ts +8 -0
  261. package/dist/lib/http/url.d.ts.map +1 -0
  262. package/dist/lib/http/url.js +22 -0
  263. package/dist/lib/http/url.js.map +1 -0
  264. package/dist/lib/redis.d.ts +5 -0
  265. package/dist/lib/redis.d.ts.map +1 -0
  266. package/dist/lib/redis.js +22 -0
  267. package/dist/lib/redis.js.map +1 -0
  268. package/dist/lib/util/authorization-header.d.ts +4 -0
  269. package/dist/lib/util/authorization-header.d.ts.map +1 -0
  270. package/dist/lib/util/authorization-header.js +23 -0
  271. package/dist/lib/util/authorization-header.js.map +1 -0
  272. package/dist/lib/util/cast.d.ts +2 -0
  273. package/dist/lib/util/cast.d.ts.map +1 -0
  274. package/dist/lib/util/cast.js +10 -0
  275. package/dist/lib/util/cast.js.map +1 -0
  276. package/dist/lib/util/crypto.d.ts +3 -0
  277. package/dist/lib/util/crypto.d.ts.map +1 -0
  278. package/dist/lib/util/crypto.js +29 -0
  279. package/dist/lib/util/crypto.js.map +1 -0
  280. package/dist/lib/util/date.d.ts +3 -0
  281. package/dist/lib/util/date.d.ts.map +1 -0
  282. package/dist/lib/util/date.js +12 -0
  283. package/dist/lib/util/date.js.map +1 -0
  284. package/dist/lib/util/hostname.d.ts +6 -0
  285. package/dist/lib/util/hostname.d.ts.map +1 -0
  286. package/dist/lib/util/hostname.js +24 -0
  287. package/dist/lib/util/hostname.js.map +1 -0
  288. package/dist/lib/util/redirect-uri.d.ts +7 -0
  289. package/dist/lib/util/redirect-uri.d.ts.map +1 -0
  290. package/dist/lib/util/redirect-uri.js +44 -0
  291. package/dist/lib/util/redirect-uri.js.map +1 -0
  292. package/dist/lib/util/time.d.ts +6 -0
  293. package/dist/lib/util/time.d.ts.map +1 -0
  294. package/dist/lib/util/time.js +28 -0
  295. package/dist/lib/util/time.js.map +1 -0
  296. package/dist/lib/util/type.d.ts +6 -0
  297. package/dist/lib/util/type.d.ts.map +1 -0
  298. package/dist/lib/util/type.js +3 -0
  299. package/dist/lib/util/type.js.map +1 -0
  300. package/dist/lib/util/well-known.d.ts +3 -0
  301. package/dist/lib/util/well-known.d.ts.map +1 -0
  302. package/dist/lib/util/well-known.js +11 -0
  303. package/dist/lib/util/well-known.js.map +1 -0
  304. package/dist/metadata/build-metadata.d.ts +14 -0
  305. package/dist/metadata/build-metadata.d.ts.map +1 -0
  306. package/dist/metadata/build-metadata.js +132 -0
  307. package/dist/metadata/build-metadata.js.map +1 -0
  308. package/dist/oauth-client.d.ts +4 -0
  309. package/dist/oauth-client.d.ts.map +1 -0
  310. package/dist/oauth-client.js +19 -0
  311. package/dist/oauth-client.js.map +1 -0
  312. package/dist/oauth-dpop.d.ts +3 -0
  313. package/dist/oauth-dpop.d.ts.map +1 -0
  314. package/dist/oauth-dpop.js +19 -0
  315. package/dist/oauth-dpop.js.map +1 -0
  316. package/dist/oauth-errors.d.ts +20 -0
  317. package/dist/oauth-errors.d.ts.map +1 -0
  318. package/dist/oauth-errors.js +43 -0
  319. package/dist/oauth-errors.js.map +1 -0
  320. package/dist/oauth-hooks.d.ts +42 -0
  321. package/dist/oauth-hooks.d.ts.map +1 -0
  322. package/dist/oauth-hooks.js +3 -0
  323. package/dist/oauth-hooks.js.map +1 -0
  324. package/dist/oauth-provider.d.ts +179 -0
  325. package/dist/oauth-provider.d.ts.map +1 -0
  326. package/dist/oauth-provider.js +748 -0
  327. package/dist/oauth-provider.js.map +1 -0
  328. package/dist/oauth-store.d.ts +11 -0
  329. package/dist/oauth-store.d.ts.map +1 -0
  330. package/dist/oauth-store.js +27 -0
  331. package/dist/oauth-store.js.map +1 -0
  332. package/dist/oauth-verifier.d.ts +66 -0
  333. package/dist/oauth-verifier.d.ts.map +1 -0
  334. package/dist/oauth-verifier.js +94 -0
  335. package/dist/oauth-verifier.js.map +1 -0
  336. package/dist/oidc/claims.d.ts +16 -0
  337. package/dist/oidc/claims.d.ts.map +1 -0
  338. package/dist/oidc/claims.js +29 -0
  339. package/dist/oidc/claims.js.map +1 -0
  340. package/dist/oidc/sub.d.ts +4 -0
  341. package/dist/oidc/sub.d.ts.map +1 -0
  342. package/dist/oidc/sub.js +6 -0
  343. package/dist/oidc/sub.js.map +1 -0
  344. package/dist/oidc/userinfo.d.ts +7 -0
  345. package/dist/oidc/userinfo.d.ts.map +1 -0
  346. package/dist/oidc/userinfo.js +3 -0
  347. package/dist/oidc/userinfo.js.map +1 -0
  348. package/dist/output/build-error-payload.d.ts +6 -0
  349. package/dist/output/build-error-payload.d.ts.map +1 -0
  350. package/dist/output/build-error-payload.js +108 -0
  351. package/dist/output/build-error-payload.js.map +1 -0
  352. package/dist/output/customization.d.ts +37 -0
  353. package/dist/output/customization.d.ts.map +1 -0
  354. package/dist/output/customization.js +62 -0
  355. package/dist/output/customization.js.map +1 -0
  356. package/dist/output/send-authorize-page.d.ts +43 -0
  357. package/dist/output/send-authorize-page.d.ts.map +1 -0
  358. package/dist/output/send-authorize-page.js +49 -0
  359. package/dist/output/send-authorize-page.js.map +1 -0
  360. package/dist/output/send-authorize-redirect.d.ts +25 -0
  361. package/dist/output/send-authorize-redirect.d.ts.map +1 -0
  362. package/dist/output/send-authorize-redirect.js +72 -0
  363. package/dist/output/send-authorize-redirect.js.map +1 -0
  364. package/dist/output/send-error-page.d.ts +5 -0
  365. package/dist/output/send-error-page.d.ts.map +1 -0
  366. package/dist/output/send-error-page.js +31 -0
  367. package/dist/output/send-error-page.js.map +1 -0
  368. package/dist/output/send-web-page.d.ts +8 -0
  369. package/dist/output/send-web-page.d.ts.map +1 -0
  370. package/dist/output/send-web-page.js +48 -0
  371. package/dist/output/send-web-page.js.map +1 -0
  372. package/dist/parameters/claims-requested.d.ts +3 -0
  373. package/dist/parameters/claims-requested.d.ts.map +1 -0
  374. package/dist/parameters/claims-requested.js +77 -0
  375. package/dist/parameters/claims-requested.js.map +1 -0
  376. package/dist/parameters/oidc-payload.d.ts +31 -0
  377. package/dist/parameters/oidc-payload.d.ts.map +1 -0
  378. package/dist/parameters/oidc-payload.js +25 -0
  379. package/dist/parameters/oidc-payload.js.map +1 -0
  380. package/dist/replay/replay-manager.d.ts +10 -0
  381. package/dist/replay/replay-manager.d.ts.map +1 -0
  382. package/dist/replay/replay-manager.js +23 -0
  383. package/dist/replay/replay-manager.js.map +1 -0
  384. package/dist/replay/replay-store-memory.d.ts +11 -0
  385. package/dist/replay/replay-store-memory.d.ts.map +1 -0
  386. package/dist/replay/replay-store-memory.js +30 -0
  387. package/dist/replay/replay-store-memory.js.map +1 -0
  388. package/dist/replay/replay-store-redis.d.ts +16 -0
  389. package/dist/replay/replay-store-redis.d.ts.map +1 -0
  390. package/dist/replay/replay-store-redis.js +20 -0
  391. package/dist/replay/replay-store-redis.js.map +1 -0
  392. package/dist/replay/replay-store.d.ts +16 -0
  393. package/dist/replay/replay-store.d.ts.map +1 -0
  394. package/dist/replay/replay-store.js +22 -0
  395. package/dist/replay/replay-store.js.map +1 -0
  396. package/dist/request/code.d.ts +7 -0
  397. package/dist/request/code.d.ts.map +1 -0
  398. package/dist/request/code.js +20 -0
  399. package/dist/request/code.js.map +1 -0
  400. package/dist/request/request-data.d.ts +21 -0
  401. package/dist/request/request-data.d.ts.map +1 -0
  402. package/dist/request/request-data.js +6 -0
  403. package/dist/request/request-data.js.map +1 -0
  404. package/dist/request/request-id.d.ts +6 -0
  405. package/dist/request/request-id.d.ts.map +1 -0
  406. package/dist/request/request-id.js +18 -0
  407. package/dist/request/request-id.js.map +1 -0
  408. package/dist/request/request-info.d.ts +12 -0
  409. package/dist/request/request-info.d.ts.map +1 -0
  410. package/dist/request/request-info.js +3 -0
  411. package/dist/request/request-info.js.map +1 -0
  412. package/dist/request/request-manager.d.ts +40 -0
  413. package/dist/request/request-manager.d.ts.map +1 -0
  414. package/dist/request/request-manager.js +310 -0
  415. package/dist/request/request-manager.js.map +1 -0
  416. package/dist/request/request-store-memory.d.ts +16 -0
  417. package/dist/request/request-store-memory.d.ts.map +1 -0
  418. package/dist/request/request-store-memory.js +31 -0
  419. package/dist/request/request-store-memory.js.map +1 -0
  420. package/dist/request/request-store-redis.d.ts +24 -0
  421. package/dist/request/request-store-redis.d.ts.map +1 -0
  422. package/dist/request/request-store-redis.js +58 -0
  423. package/dist/request/request-store-redis.js.map +1 -0
  424. package/dist/request/request-store.d.ts +27 -0
  425. package/dist/request/request-store.d.ts.map +1 -0
  426. package/dist/request/request-store.js +37 -0
  427. package/dist/request/request-store.js.map +1 -0
  428. package/dist/request/request-uri.d.ts +8 -0
  429. package/dist/request/request-uri.d.ts.map +1 -0
  430. package/dist/request/request-uri.js +24 -0
  431. package/dist/request/request-uri.js.map +1 -0
  432. package/dist/request/types.d.ts +328 -0
  433. package/dist/request/types.d.ts.map +1 -0
  434. package/dist/request/types.js +27 -0
  435. package/dist/request/types.js.map +1 -0
  436. package/dist/signer/signed-token-payload.d.ts +1694 -0
  437. package/dist/signer/signed-token-payload.d.ts.map +1 -0
  438. package/dist/signer/signed-token-payload.js +32 -0
  439. package/dist/signer/signed-token-payload.js.map +1 -0
  440. package/dist/signer/signer.d.ts +193 -0
  441. package/dist/signer/signer.d.ts.map +1 -0
  442. package/dist/signer/signer.js +101 -0
  443. package/dist/signer/signer.js.map +1 -0
  444. package/dist/token/refresh-token.d.ts +7 -0
  445. package/dist/token/refresh-token.d.ts.map +1 -0
  446. package/dist/token/refresh-token.js +20 -0
  447. package/dist/token/refresh-token.js.map +1 -0
  448. package/dist/token/token-claims.d.ts +1687 -0
  449. package/dist/token/token-claims.d.ts.map +1 -0
  450. package/dist/token/token-claims.js +30 -0
  451. package/dist/token/token-claims.js.map +1 -0
  452. package/dist/token/token-data.d.ts +20 -0
  453. package/dist/token/token-data.d.ts.map +1 -0
  454. package/dist/token/token-data.js +3 -0
  455. package/dist/token/token-data.js.map +1 -0
  456. package/dist/token/token-id.d.ts +7 -0
  457. package/dist/token/token-id.d.ts.map +1 -0
  458. package/dist/token/token-id.js +20 -0
  459. package/dist/token/token-id.js.map +1 -0
  460. package/dist/token/token-manager.d.ts +48 -0
  461. package/dist/token/token-manager.d.ts.map +1 -0
  462. package/dist/token/token-manager.js +421 -0
  463. package/dist/token/token-manager.js.map +1 -0
  464. package/dist/token/token-store.d.ts +35 -0
  465. package/dist/token/token-store.d.ts.map +1 -0
  466. package/dist/token/token-store.js +38 -0
  467. package/dist/token/token-store.js.map +1 -0
  468. package/dist/token/types.d.ts +250 -0
  469. package/dist/token/types.d.ts.map +1 -0
  470. package/dist/token/types.js +36 -0
  471. package/dist/token/types.js.map +1 -0
  472. package/dist/token/verify-token-claims.d.ts +17 -0
  473. package/dist/token/verify-token-claims.d.ts.map +1 -0
  474. package/dist/token/verify-token-claims.js +39 -0
  475. package/dist/token/verify-token-claims.js.map +1 -0
  476. package/package.json +83 -0
  477. package/rollup.config.js +55 -0
  478. package/src/access-token/access-token-type.ts +5 -0
  479. package/src/account/account-manager.ts +55 -0
  480. package/src/account/account-store.ts +74 -0
  481. package/src/account/account.ts +10 -0
  482. package/src/assets/app/app.tsx +28 -0
  483. package/src/assets/app/backend-data.ts +65 -0
  484. package/src/assets/app/components/accept-form.tsx +112 -0
  485. package/src/assets/app/components/account-identifier.tsx +18 -0
  486. package/src/assets/app/components/account-picker.tsx +108 -0
  487. package/src/assets/app/components/client-identifier.tsx +32 -0
  488. package/src/assets/app/components/client-name.tsx +30 -0
  489. package/src/assets/app/components/error-card.tsx +41 -0
  490. package/src/assets/app/components/help-card.tsx +42 -0
  491. package/src/assets/app/components/layout-title-page.tsx +43 -0
  492. package/src/assets/app/components/layout-welcome.tsx +58 -0
  493. package/src/assets/app/components/sign-in-form.tsx +290 -0
  494. package/src/assets/app/components/sign-up-account-form.tsx +210 -0
  495. package/src/assets/app/components/sign-up-disclaimer.tsx +44 -0
  496. package/src/assets/app/components/url-viewer.tsx +70 -0
  497. package/src/assets/app/cookies.ts +11 -0
  498. package/src/assets/app/hooks/use-api.ts +104 -0
  499. package/src/assets/app/hooks/use-bound-dispatch.ts +5 -0
  500. package/src/assets/app/hooks/use-csrf-token.ts +5 -0
  501. package/src/assets/app/lib/api.ts +64 -0
  502. package/src/assets/app/lib/clsx.ts +4 -0
  503. package/src/assets/app/lib/util.ts +10 -0
  504. package/src/assets/app/main.css +11 -0
  505. package/src/assets/app/main.tsx +28 -0
  506. package/src/assets/app/views/accept-view.tsx +51 -0
  507. package/src/assets/app/views/authorize-view.tsx +101 -0
  508. package/src/assets/app/views/error-view.tsx +27 -0
  509. package/src/assets/app/views/sign-in-view.tsx +121 -0
  510. package/src/assets/app/views/sign-up-view.tsx +93 -0
  511. package/src/assets/app/views/welcome-view.tsx +61 -0
  512. package/src/assets/asset.ts +8 -0
  513. package/src/assets/assets-middleware.ts +32 -0
  514. package/src/assets/index.ts +74 -0
  515. package/src/client/client-auth.ts +45 -0
  516. package/src/client/client-data.ts +9 -0
  517. package/src/client/client-id.ts +4 -0
  518. package/src/client/client-info.ts +13 -0
  519. package/src/client/client-manager.ts +818 -0
  520. package/src/client/client-store.ts +38 -0
  521. package/src/client/client-utils.ts +43 -0
  522. package/src/client/client.ts +231 -0
  523. package/src/constants.ts +69 -0
  524. package/src/device/device-data.ts +11 -0
  525. package/src/device/device-details.ts +43 -0
  526. package/src/device/device-id.ts +23 -0
  527. package/src/device/device-manager.ts +287 -0
  528. package/src/device/device-store.ts +35 -0
  529. package/src/device/session-id.ts +22 -0
  530. package/src/dpop/dpop-manager.ts +147 -0
  531. package/src/dpop/dpop-nonce.ts +104 -0
  532. package/src/errors/access-denied-error.ts +26 -0
  533. package/src/errors/account-selection-required-error.ts +12 -0
  534. package/src/errors/consent-required-error.ts +12 -0
  535. package/src/errors/invalid-authorization-details-error.ts +22 -0
  536. package/src/errors/invalid-client-error.ts +20 -0
  537. package/src/errors/invalid-client-id-error.ts +20 -0
  538. package/src/errors/invalid-client-metadata-error.ts +19 -0
  539. package/src/errors/invalid-dpop-key-binding-error.ts +21 -0
  540. package/src/errors/invalid-dpop-proof-error.ts +13 -0
  541. package/src/errors/invalid-grant-error.ts +16 -0
  542. package/src/errors/invalid-parameters-error.ts +12 -0
  543. package/src/errors/invalid-redirect-uri-error.ts +17 -0
  544. package/src/errors/invalid-request-error.ts +30 -0
  545. package/src/errors/invalid-token-error.ts +59 -0
  546. package/src/errors/login-required-error.ts +12 -0
  547. package/src/errors/oauth-error.ts +28 -0
  548. package/src/errors/unauthorized-client-error.ts +20 -0
  549. package/src/errors/use-dpop-nonce-error.ts +32 -0
  550. package/src/errors/www-authenticate-error.ts +65 -0
  551. package/src/index.ts +15 -0
  552. package/src/lib/html/README.md +9 -0
  553. package/src/lib/html/build-document.ts +98 -0
  554. package/src/lib/html/escapers.ts +66 -0
  555. package/src/lib/html/html.ts +61 -0
  556. package/src/lib/html/index.ts +5 -0
  557. package/src/lib/html/tags.ts +58 -0
  558. package/src/lib/html/util.ts +21 -0
  559. package/src/lib/http/README.md +11 -0
  560. package/src/lib/http/accept.ts +91 -0
  561. package/src/lib/http/context.ts +11 -0
  562. package/src/lib/http/index.ts +9 -0
  563. package/src/lib/http/method.ts +18 -0
  564. package/src/lib/http/middleware.ts +183 -0
  565. package/src/lib/http/parser.ts +64 -0
  566. package/src/lib/http/path.ts +82 -0
  567. package/src/lib/http/request.ts +141 -0
  568. package/src/lib/http/response.ts +133 -0
  569. package/src/lib/http/route.ts +56 -0
  570. package/src/lib/http/router.ts +118 -0
  571. package/src/lib/http/stream.ts +78 -0
  572. package/src/lib/http/types.ts +22 -0
  573. package/src/lib/http/url.ts +23 -0
  574. package/src/lib/redis.ts +23 -0
  575. package/src/lib/util/authorization-header.ts +26 -0
  576. package/src/lib/util/cast.ts +4 -0
  577. package/src/lib/util/crypto.ts +27 -0
  578. package/src/lib/util/date.ts +7 -0
  579. package/src/lib/util/hostname.ts +19 -0
  580. package/src/lib/util/redirect-uri.ts +46 -0
  581. package/src/lib/util/time.ts +33 -0
  582. package/src/lib/util/type.ts +4 -0
  583. package/src/lib/util/well-known.ts +8 -0
  584. package/src/metadata/build-metadata.ts +165 -0
  585. package/src/oauth-client.ts +3 -0
  586. package/src/oauth-dpop.ts +2 -0
  587. package/src/oauth-errors.ts +21 -0
  588. package/src/oauth-hooks.ts +66 -0
  589. package/src/oauth-provider.ts +1409 -0
  590. package/src/oauth-store.ts +11 -0
  591. package/src/oauth-verifier.ts +219 -0
  592. package/src/oidc/claims.ts +35 -0
  593. package/src/oidc/sub.ts +4 -0
  594. package/src/oidc/userinfo.ts +11 -0
  595. package/src/output/build-error-payload.ts +143 -0
  596. package/src/output/customization.ts +96 -0
  597. package/src/output/send-authorize-page.ts +111 -0
  598. package/src/output/send-authorize-redirect.ts +130 -0
  599. package/src/output/send-error-page.ts +41 -0
  600. package/src/output/send-web-page.ts +66 -0
  601. package/src/parameters/claims-requested.ts +106 -0
  602. package/src/parameters/oidc-payload.ts +28 -0
  603. package/src/replay/replay-manager.ts +38 -0
  604. package/src/replay/replay-store-memory.ts +36 -0
  605. package/src/replay/replay-store-redis.ts +31 -0
  606. package/src/replay/replay-store.ts +44 -0
  607. package/src/request/code.ts +24 -0
  608. package/src/request/request-data.ts +26 -0
  609. package/src/request/request-id.ts +23 -0
  610. package/src/request/request-info.ts +12 -0
  611. package/src/request/request-manager.ts +479 -0
  612. package/src/request/request-store-memory.ts +39 -0
  613. package/src/request/request-store-redis.ts +71 -0
  614. package/src/request/request-store.ts +54 -0
  615. package/src/request/request-uri.ts +29 -0
  616. package/src/request/types.ts +48 -0
  617. package/src/signer/signed-token-payload.ts +35 -0
  618. package/src/signer/signer.ts +165 -0
  619. package/src/token/refresh-token.ts +31 -0
  620. package/src/token/token-claims.ts +31 -0
  621. package/src/token/token-data.ts +33 -0
  622. package/src/token/token-id.ts +26 -0
  623. package/src/token/token-manager.ts +591 -0
  624. package/src/token/token-store.ts +78 -0
  625. package/src/token/types.ts +86 -0
  626. package/src/token/verify-token-claims.ts +65 -0
  627. package/tailwind.config.js +13 -0
  628. package/tsconfig.backend.json +9 -0
  629. package/tsconfig.frontend.json +11 -0
  630. package/tsconfig.json +8 -0
  631. package/tsconfig.tools.json +8 -0
@@ -0,0 +1,58 @@
1
+ import {
2
+ HtmlValue,
3
+ cssEscaper,
4
+ htmlEscaper,
5
+ javascriptEscaper,
6
+ jsonEscaper,
7
+ } from './escapers.js'
8
+ import { Html } from './html.js'
9
+
10
+ export { type HtmlValue }
11
+ export const html = (
12
+ tpl: TemplateStringsArray,
13
+ ...val: readonly HtmlValue[]
14
+ ) =>
15
+ tpl.length === 1 && val.length === 0
16
+ ? // Optimization for static HTML, avoid creating an iterable
17
+ Html.dangerouslyCreate(tpl)
18
+ : Html.dangerouslyCreate(htmlEscaper(tpl, val))
19
+
20
+ /**
21
+ * Escapes code to use as a JavaScript string inside a `<script>` tag.
22
+ */
23
+ export const javascriptCode = (code: string) =>
24
+ Html.dangerouslyCreate(javascriptEscaper(code))
25
+
26
+ /**
27
+ * Creates an HTML safe JavaScript code block, with JSON serialization of the
28
+ * injected variables.
29
+ *
30
+ * @example
31
+ * ```js
32
+ * const dataOnTheServer = { foo: 'bar' };
33
+ * const clientScript = js`
34
+ * const data = ${dataOnTheServer};
35
+ * console.log(data);
36
+ * `
37
+ * console.log(clientScript.toString()); // Output: 'const data = {"foo":"bar"};console.log(data);'
38
+ * ```
39
+ */
40
+ export const js = (tpl: TemplateStringsArray, ...val: readonly unknown[]) =>
41
+ tpl.length === 1 && val.length === 0
42
+ ? // Optimization for static JavaScript, avoid un-necessary serialization
43
+ javascriptCode(tpl[0])
44
+ : javascriptCode(String.raw({ raw: tpl }, ...val.map(jsonCode)))
45
+
46
+ /**
47
+ * Escapes a value to be used as a JSON string inside a `<script>` tag.
48
+ *
49
+ * @see {@link https://redux.js.org/usage/server-rendering#security-considerations}
50
+ */
51
+ export const jsonCode = (value: unknown) =>
52
+ Html.dangerouslyCreate(jsonEscaper(value))
53
+
54
+ /**
55
+ * Escapes a value to be uses as CSS styles inside a `<style>` tag.
56
+ */
57
+ export const cssCode = (code: string) =>
58
+ Html.dangerouslyCreate(cssEscaper(code))
@@ -0,0 +1,21 @@
1
+ export type NestedIterable<V> = V | Iterable<NestedIterable<V>>
2
+
3
+ export function* stringReplacer(
4
+ source: string,
5
+ searchValue: string,
6
+ replaceValue: string,
7
+ ): Generator<string, void, undefined> {
8
+ let previousIndex = 0
9
+ let index = source.indexOf(searchValue)
10
+ while (index !== -1) {
11
+ yield source.slice(previousIndex, index)
12
+ yield replaceValue
13
+ previousIndex = index + searchValue.length
14
+ index = source.indexOf(searchValue, previousIndex)
15
+ }
16
+ yield source.slice(previousIndex)
17
+ }
18
+
19
+ export function isString(value: unknown): value is string {
20
+ return typeof value === 'string'
21
+ }
@@ -0,0 +1,11 @@
1
+ # utilities for generating middlewares to work with Node's http module or Express / Connect frameworks
2
+
3
+ This library uses a functional programming style to generate middleware
4
+ functions that can be used with Node's http module or Express / Connect
5
+ frameworks.
6
+
7
+ This code _could_ be used as a standalone library, but the Bluesky dev team does
8
+ not want to maintain it as such. As it is currently only used by the
9
+ `@atproto/oauth-provider` package, it is included here. Future development
10
+ should aim to keep this library independent of the rest of the
11
+ `@atproto/oauth-provider` package, so that it can be extracted and published.
@@ -0,0 +1,91 @@
1
+ import { mediaType } from '@hapi/accept'
2
+
3
+ import { SubCtx, subCtx } from './context.js'
4
+ import {
5
+ IncomingMessage,
6
+ Middleware,
7
+ NextFunction,
8
+ ServerResponse,
9
+ } from './types.js'
10
+
11
+ type View<
12
+ T,
13
+ D,
14
+ Req extends IncomingMessage = IncomingMessage,
15
+ Res extends ServerResponse = ServerResponse,
16
+ > = (
17
+ this: SubCtx<T, { data: D }>,
18
+ req: Req,
19
+ res: Res,
20
+ next: NextFunction,
21
+ ) => void | PromiseLike<void>
22
+
23
+ /**
24
+ * @example
25
+ * ```ts
26
+ * app.use(
27
+ * acceptMiddleware(
28
+ * async function (req, res) {
29
+ * return { hello: 'world' }
30
+ * },
31
+ * {
32
+ * '': 'application/json', // Fallback to JSON
33
+ * 'text/plain': function (req, res) {
34
+ * res.writeHead(200).end(this.data.hello)
35
+ * },
36
+ * 'application/json': function (req, res) {
37
+ * res.writeHead(200).end(JSON.stringify(this.data))
38
+ * }
39
+ * }
40
+ * )
41
+ * )
42
+ */
43
+ export function acceptMiddleware<
44
+ D,
45
+ T = void,
46
+ Req extends IncomingMessage = IncomingMessage,
47
+ Res extends ServerResponse = ServerResponse,
48
+ >(
49
+ controller: (this: T, req: Req, res: Res) => D | PromiseLike<D>,
50
+ views: Record<string, string | View<T, D, Req, Res>>,
51
+ fallback: Middleware<T> = (req, res, _next) => void res.writeHead(406).end(),
52
+ ): (this: T, req: Req, res: Res, next: NextFunction) => Promise<void> {
53
+ const viewsMap = new Map(Object.entries(views))
54
+ const preferences = Array.from(viewsMap.keys()).filter(Boolean)
55
+
56
+ // Make sure that every view is either a function or a string that points to a
57
+ // function.
58
+ for (const type of viewsMap.keys()) {
59
+ const view = viewsMap.get(type)
60
+ if (typeof view === 'string' && typeof viewsMap.get(view) !== 'function') {
61
+ throw new Error(`Invalid view "${view}" for media type "${type}"`)
62
+ }
63
+ }
64
+
65
+ return async function (req, res, next) {
66
+ try {
67
+ const type = req.headers['accept']
68
+ ? mediaType(req.headers['accept'], preferences) || undefined
69
+ : '' // indicate that the client accepts anything
70
+
71
+ let view = type != null ? viewsMap.get(type) : undefined
72
+
73
+ if (typeof view === 'string') view = viewsMap.get(view)
74
+ if (typeof view === 'string') throw new Error('Invalid view') // should not happen
75
+
76
+ if (view) {
77
+ const data = await controller.call(this, req, res)
78
+ const ctx = subCtx(this, 'data', data)
79
+ if (type) res.setHeader('Content-Type', type)
80
+
81
+ await view.call(ctx, req, res, next)
82
+ } else {
83
+ // media negotiation failed
84
+ await fallback.call(this, req, res, next)
85
+ }
86
+ } catch (err) {
87
+ if (!res.headersSent) res.removeHeader('Content-Type')
88
+ next(err)
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,11 @@
1
+ export type SubCtx<Parent, Child> = Child & Omit<Parent, keyof Child>
2
+
3
+ export function subCtx<T, K extends string, V>(
4
+ ctx: T,
5
+ key: K,
6
+ value: V,
7
+ ): SubCtx<T, { [_ in K]: V }> {
8
+ return Object.create(typeof ctx === 'object' ? ctx : null, {
9
+ [key]: { value, enumerable: true, writable: false },
10
+ })
11
+ }
@@ -0,0 +1,9 @@
1
+ export * from './accept.js'
2
+ export * from './context.js'
3
+ export * from './middleware.js'
4
+ export * from './parser.js'
5
+ export * from './request.js'
6
+ export * from './response.js'
7
+ export * from './router.js'
8
+ export * from './stream.js'
9
+ export * from './types.js'
@@ -0,0 +1,18 @@
1
+ import { IncomingMessage } from './types.js'
2
+
3
+ export type MethodMatcherInput = string | Iterable<string> | MethodMatcher
4
+ export type MethodMatcher = (req: IncomingMessage) => boolean
5
+
6
+ export function createMethodMatcher(method: MethodMatcherInput): MethodMatcher {
7
+ if (method === '*') return () => true
8
+ if (typeof method === 'function') return method
9
+
10
+ if (typeof method === 'string') {
11
+ method = method.toUpperCase()
12
+ return (req) => req.method === method
13
+ }
14
+
15
+ const set = new Set(Array.from(method, (m) => m.toUpperCase()))
16
+ if (set.size === 0) return () => false
17
+ return (req) => req.method != null && set.has(req.method)
18
+ }
@@ -0,0 +1,183 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http'
2
+ import { writeJson } from './response.js'
3
+ import { Middleware, Handler, NextFunction } from './types.js'
4
+
5
+ export function combineMiddlewares<M extends Middleware<any, any, any>>(
6
+ middlewares: Iterable<null | undefined | M>,
7
+ options?: { skipKeyword?: string },
8
+ ): M
9
+
10
+ /**
11
+ * Combine express/connect like middlewares (that can be async) into a single
12
+ * middleware.
13
+ */
14
+ export function combineMiddlewares(
15
+ middlewares: Iterable<null | undefined | Middleware<unknown>>,
16
+ { skipKeyword }: { skipKeyword?: string } = {},
17
+ ): Middleware<unknown> {
18
+ const middlewaresArray = Array.from(middlewares).filter(
19
+ (x): x is NonNullable<typeof x> => x != null,
20
+ )
21
+
22
+ // Optimization: if there are no middlewares, return a noop middleware.
23
+ if (middlewaresArray.length === 0) return (req, res, next) => void next()
24
+
25
+ return function (req, res, next) {
26
+ let i = 0
27
+ const nextMiddleware = (err?: unknown) => {
28
+ if (err) {
29
+ if (skipKeyword && err === skipKeyword) next()
30
+ else next(err)
31
+ } else if (i >= middlewaresArray.length) {
32
+ next()
33
+ } else {
34
+ const currentMiddleware = middlewaresArray[i++]!
35
+ const currentNext = once(nextMiddleware)
36
+ try {
37
+ const result = currentMiddleware.call(this, req, res, currentNext)
38
+ Promise.resolve(result).catch(currentNext)
39
+ } catch (err) {
40
+ currentNext(err)
41
+ }
42
+ }
43
+ }
44
+ nextMiddleware()
45
+ }
46
+ }
47
+
48
+ export type AsHandler<M extends Middleware<any, any, any>> =
49
+ M extends Middleware<infer T, infer Req, infer Res>
50
+ ? Handler<T, Req, Res>
51
+ : never
52
+
53
+ /**
54
+ * Convert a middleware in a function that can be used as both a middleware and
55
+ * and handler.
56
+ */
57
+ export function asHandler<M extends Middleware<any, any, any>>(
58
+ middleware: M,
59
+ options?: FinalHandlerOptions,
60
+ ) {
61
+ return function (
62
+ this,
63
+ req,
64
+ res,
65
+ next = once(createFinalHandler(req, res, options)),
66
+ ) {
67
+ return middleware.call(this, req, res, next)
68
+ } as AsHandler<M>
69
+ }
70
+
71
+ export type FinalHandlerOptions = {
72
+ debug?: boolean
73
+ }
74
+
75
+ export function createFinalHandler(
76
+ req: IncomingMessage,
77
+ res: ServerResponse,
78
+ options?: FinalHandlerOptions,
79
+ ): NextFunction {
80
+ return (err) => {
81
+ if (err && (options?.debug ?? process.env['NODE_ENV'] === 'development')) {
82
+ console.error(err)
83
+ }
84
+
85
+ if (res.headersSent) {
86
+ // If an error occurred, and headers were sent, we can't know that the
87
+ // whole response body was sent. So we can't safely reuse the socket.
88
+ if (err) req.socket.destroy()
89
+
90
+ return
91
+ }
92
+
93
+ const { status, ...payload } = buildFallbackPayload(req, err)
94
+
95
+ res.setHeader('Content-Security-Policy', "default-src 'none'")
96
+ res.setHeader('X-Content-Type-Options', 'nosniff')
97
+
98
+ writeJson(res, payload, status)
99
+ }
100
+ }
101
+
102
+ function buildFallbackPayload(
103
+ req: IncomingMessage,
104
+ err: unknown,
105
+ ): {
106
+ status: number
107
+ error: string
108
+ error_description: string
109
+ stack?: undefined | string
110
+ } {
111
+ const status = err ? getErrorStatusCode(err) : 404
112
+ const expose = getProp(err, 'expose', 'boolean') ?? status < 500
113
+
114
+ return {
115
+ status,
116
+ error: err
117
+ ? expose
118
+ ? getProp(err, 'code', 'string') ??
119
+ getProp(err, 'error', 'string') ??
120
+ 'unknown_error'
121
+ : 'system_error'
122
+ : 'not_found',
123
+ error_description:
124
+ err instanceof Error
125
+ ? expose
126
+ ? getProp(err, 'error_description', 'string') ||
127
+ String(err.message) ||
128
+ 'Unknown error'
129
+ : 'System error'
130
+ : `Cannot ${req.method} ${req.url}`,
131
+ stack:
132
+ err instanceof Error && process.env['NODE_ENV'] === 'development'
133
+ ? err.stack
134
+ : undefined,
135
+ }
136
+ }
137
+
138
+ function getErrorStatusCode(err: NonNullable<unknown>): number {
139
+ const status =
140
+ getProp(err, 'status', 'number') ?? getProp(err, 'statusCode', 'number')
141
+ return status != null && status >= 400 && status < 600 ? status : 500
142
+ }
143
+
144
+ export function once<T extends NextFunction>(next: T): T {
145
+ let nextNullable: T | null = next
146
+ return function (err) {
147
+ if (!nextNullable) throw new Error('next() called multiple times')
148
+ const next = nextNullable
149
+ nextNullable = null
150
+ return next(err)
151
+ } as T
152
+ }
153
+
154
+ // eslint-disable-next-line
155
+ function getProp(obj: unknown, key: string, t: 'function'): Function | undefined
156
+ function getProp(obj: unknown, key: string, t: 'string'): string | undefined
157
+ function getProp(obj: unknown, key: string, t: 'number'): number | undefined
158
+ function getProp(obj: unknown, key: string, t: 'boolean'): boolean | undefined
159
+ function getProp(obj: unknown, key: string, t: 'object'): object | undefined
160
+ function getProp(obj: unknown, key: string, t: 'symbol'): symbol | undefined
161
+ function getProp(obj: unknown, key: string, t: 'bigint'): bigint | undefined
162
+ function getProp(obj: unknown, key: string, t: 'undefined'): undefined
163
+ function getProp(
164
+ obj: unknown,
165
+ key: string,
166
+ type:
167
+ | 'string'
168
+ | 'number'
169
+ | 'boolean'
170
+ | 'object'
171
+ | 'function'
172
+ | 'symbol'
173
+ | 'bigint'
174
+ | 'undefined',
175
+ ): unknown
176
+
177
+ function getProp(obj: unknown, key: string, type: string): unknown {
178
+ if (obj != null && typeof obj === 'object' && key in obj) {
179
+ const value = (obj as Record<string, unknown>)[key]
180
+ if (typeof value === type) return value
181
+ }
182
+ return undefined
183
+ }
@@ -0,0 +1,64 @@
1
+ import { parse as parseJson } from '@hapi/bourne'
2
+ import createHttpError from 'http-errors'
3
+
4
+ export type JsonScalar = string | number | boolean | null
5
+ export type Json = JsonScalar | Json[] | { [_ in string]?: Json }
6
+
7
+ export type Parser<T extends string = string, R = unknown> = {
8
+ readonly name: string
9
+ readonly test: (type: string) => type is T
10
+ readonly parse: (buffer: Buffer) => R
11
+ }
12
+
13
+ export type ParserName<P extends Parser> = P extends { readonly name: infer N }
14
+ ? N
15
+ : never
16
+ export type ParserType<P extends Parser> = P extends Parser<infer T> ? T : never
17
+ export type ParserResult<P extends Parser> = ReturnType<P['parse']>
18
+
19
+ export type ParserForType<P extends Parser, T> =
20
+ P extends Parser<infer U> ? (U extends T ? P : never) : never
21
+
22
+ export const parsers = [
23
+ {
24
+ name: 'json',
25
+ test: (
26
+ type: string,
27
+ ): type is `application/json` | `application/${string}+json` => {
28
+ return /^application\/(?:.+\+)?json$/.test(type)
29
+ },
30
+ parse: (buffer: Buffer): Json => {
31
+ try {
32
+ return parseJson(buffer.toString())
33
+ } catch (err) {
34
+ throw createHttpError(400, 'Invalid JSON', { cause: err })
35
+ }
36
+ },
37
+ },
38
+ {
39
+ name: 'urlencoded',
40
+ test: (type: string): type is 'application/x-www-form-urlencoded' => {
41
+ return type === 'application/x-www-form-urlencoded'
42
+ },
43
+ parse: (buffer: Buffer): Partial<Record<string, string>> => {
44
+ try {
45
+ if (!buffer.length) return {}
46
+ return Object.fromEntries(new URLSearchParams(buffer.toString()))
47
+ } catch (err) {
48
+ throw createHttpError(400, 'Invalid URL-encoded data', { cause: err })
49
+ }
50
+ },
51
+ },
52
+ {
53
+ name: 'bytes',
54
+ test: (type: string): type is 'application/octet-stream' => {
55
+ return type === 'application/octet-stream'
56
+ },
57
+ parse: (buffer: Buffer): Buffer => buffer,
58
+ },
59
+ ] as const satisfies Parser[]
60
+
61
+ export type KnownParser = (typeof parsers)[number]
62
+
63
+ export type KnownNames = KnownParser['name']
64
+ export type KnownTypes = ParserType<KnownParser>
@@ -0,0 +1,82 @@
1
+ export type PathMatcher<P extends Params> = (pathname: string) => P | undefined
2
+
3
+ type StringPath<P extends Params> = string extends keyof P
4
+ ? `/${string}`
5
+ : keyof P extends never
6
+ ? `/${string}` | ``
7
+ : {
8
+ [K in keyof P]: K extends string
9
+ ?
10
+ | `${`/:${K}` | `/${string}/:${K}`}${StringPath<Omit<P, K>>}`
11
+ | `${StringPath<Omit<P, K>>}${`/:${K}` | `/:${K}/${string}`}`
12
+ : never
13
+ }[keyof P]
14
+
15
+ export type Path<P extends Params> =
16
+ | string
17
+ | StringPath<P>
18
+ | RegExp
19
+ | PathMatcher<P>
20
+ export type Params = Record<string, undefined | string>
21
+
22
+ export function createPathMatcher<P extends Params = Params>(
23
+ refPath: Path<P>,
24
+ ): PathMatcher<P> {
25
+ if (typeof refPath === 'string') {
26
+ // Create a path matcher for a path with parameters (like /foo/:fooId/bar/:barId).
27
+ if (refPath.includes('/:')) {
28
+ const refParts = refPath
29
+ .slice(1)
30
+ .split('/')
31
+ .map((part, i) => [part, i] as const)
32
+ const refPartsLength = refParts.length
33
+
34
+ const staticParts = refParts.filter(([p]) => !p.startsWith(':'))
35
+ const paramParts = refParts
36
+ // Extract parameters, ignoring those with no name (like /foo/:/bar).
37
+ .filter(([p]) => p.startsWith(':') && p.length > 1)
38
+ .map(([p, i]) => [p.slice(1), i] as const)
39
+
40
+ return (reqPath: string) => {
41
+ const reqParts = reqPath.slice(1).split('/')
42
+
43
+ if (reqParts.length !== refPartsLength) return undefined
44
+
45
+ // Make sure all static parts match.
46
+ for (let i = 0; i < staticParts.length; i++) {
47
+ const value = staticParts[i]![0]
48
+ const idx = staticParts[i]![1]
49
+
50
+ if (value !== reqParts[idx]) return undefined
51
+ }
52
+
53
+ // Then extract the parameters.
54
+ const params: Record<string, string> = {}
55
+ for (let i = 0; i < paramParts.length; i++) {
56
+ const name = paramParts[i]![0]
57
+ const idx = paramParts[i]![1]
58
+
59
+ const value = reqParts[idx]
60
+
61
+ // Empty parameter values are not allowed.
62
+ if (!value) return undefined
63
+
64
+ params[name] = value
65
+ }
66
+
67
+ return params as P
68
+ }
69
+ }
70
+
71
+ return (reqPath: string) => (reqPath === refPath ? ({} as P) : undefined)
72
+ }
73
+
74
+ if (refPath instanceof RegExp) {
75
+ return (reqPath: string) => {
76
+ const match = reqPath.match(refPath)
77
+ return match ? ((match.groups || {}) as P) : undefined
78
+ }
79
+ }
80
+
81
+ return refPath
82
+ }
@@ -0,0 +1,141 @@
1
+ import { parse as parseCookie, serialize as serializeCookie } from 'cookie'
2
+ import { randomBytes } from 'crypto'
3
+ import createHttpError from 'http-errors'
4
+ import { z } from 'zod'
5
+
6
+ import { KnownNames } from './parser.js'
7
+ import { appendHeader } from './response.js'
8
+ import { decodeStream, parseStream } from './stream.js'
9
+ import { IncomingMessage, ServerResponse } from './types.js'
10
+ import { UrlReference, urlMatch } from './url.js'
11
+
12
+ export function parseRequestPayload<
13
+ A extends readonly KnownNames[] = readonly KnownNames[],
14
+ >(req: IncomingMessage, allow?: A) {
15
+ return parseStream(
16
+ decodeStream(req, req.headers['content-encoding']),
17
+ req.headers['content-type'],
18
+ allow,
19
+ )
20
+ }
21
+
22
+ export async function validateRequestPayload<S extends z.ZodTypeAny>(
23
+ req: IncomingMessage,
24
+ schema: S,
25
+ allow: readonly KnownNames[] = ['json', 'urlencoded'],
26
+ ): Promise<z.infer<S>> {
27
+ const payload = await parseRequestPayload(req, allow)
28
+ return schema.parseAsync(payload, { path: ['body'] })
29
+ }
30
+
31
+ export function validateFetchMode(
32
+ req: IncomingMessage,
33
+ res: ServerResponse,
34
+ expectedMode: readonly (
35
+ | null
36
+ | 'navigate'
37
+ | 'same-origin'
38
+ | 'no-cors'
39
+ | 'cors'
40
+ )[],
41
+ ) {
42
+ const reqMode = req.headers['sec-fetch-mode'] ?? null
43
+
44
+ if (Array.isArray(reqMode)) {
45
+ throw createHttpError(400, `Invalid sec-fetch-mode header`)
46
+ }
47
+
48
+ if (!(expectedMode as (string | null)[]).includes(reqMode)) {
49
+ throw createHttpError(
50
+ 403,
51
+ reqMode
52
+ ? `Forbidden sec-fetch-mode "${reqMode}" (expected ${expectedMode})`
53
+ : `Missing sec-fetch-mode (expected ${expectedMode})`,
54
+ )
55
+ }
56
+ }
57
+
58
+ export function validateReferer(
59
+ req: IncomingMessage,
60
+ res: ServerResponse,
61
+ reference: UrlReference,
62
+ allowNull = false,
63
+ ) {
64
+ const referer = req.headers['referer']
65
+ const refererUrl = referer ? new URL(referer) : null
66
+ if (refererUrl ? !urlMatch(refererUrl, reference) : !allowNull) {
67
+ throw createHttpError(403, `Invalid referer ${referer}`)
68
+ }
69
+ }
70
+
71
+ export async function setupCsrfToken(
72
+ req: IncomingMessage,
73
+ res: ServerResponse,
74
+ cookieName = 'csrf_token',
75
+ ) {
76
+ const csrfToken = randomBytes(8).toString('hex')
77
+ appendHeader(
78
+ res,
79
+ 'Set-Cookie',
80
+ serializeCookie(cookieName, csrfToken, {
81
+ secure: true,
82
+ httpOnly: false,
83
+ sameSite: 'lax',
84
+ path: req.url?.split('?', 1)[0] || '/',
85
+ }),
86
+ )
87
+ }
88
+
89
+ // CORS ensure not cross origin
90
+ export function validateSameOrigin(
91
+ req: IncomingMessage,
92
+ res: ServerResponse,
93
+ origin: string,
94
+ allowNull = true,
95
+ ) {
96
+ const reqOrigin = req.headers['origin']
97
+ if (reqOrigin ? reqOrigin !== origin : !allowNull) {
98
+ throw createHttpError(403, `Invalid origin ${reqOrigin}`)
99
+ }
100
+ }
101
+
102
+ export function validateCsrfToken(
103
+ req: IncomingMessage,
104
+ res: ServerResponse,
105
+ csrfToken: string,
106
+ cookieName = 'csrf_token',
107
+ clearCookie = false,
108
+ ) {
109
+ const cookies = parseHttpCookies(req)
110
+ if (
111
+ !csrfToken ||
112
+ !cookies ||
113
+ !cookieName ||
114
+ cookies[cookieName] !== csrfToken
115
+ ) {
116
+ throw createHttpError(403, `Invalid CSRF token`)
117
+ }
118
+
119
+ if (clearCookie) {
120
+ appendHeader(
121
+ res,
122
+ 'Set-Cookie',
123
+ serializeCookie(cookieName, '', {
124
+ secure: true,
125
+ httpOnly: false,
126
+ sameSite: 'lax',
127
+ maxAge: 0,
128
+ }),
129
+ )
130
+ }
131
+ }
132
+
133
+ export function parseHttpCookies(
134
+ req: IncomingMessage,
135
+ ): null | Record<string, undefined | string> {
136
+ return 'cookies' in req && req.cookies // Already parsed by another middleware
137
+ ? (req.cookies as any)
138
+ : req.headers['cookie']
139
+ ? ((req as any).cookies = parseCookie(req.headers['cookie']))
140
+ : null
141
+ }