@atproto/oauth-provider 0.6.5 → 0.7.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 (465) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/access-token/access-token-mode.d.ts +5 -0
  3. package/dist/access-token/access-token-mode.d.ts.map +1 -0
  4. package/dist/access-token/access-token-mode.js +9 -0
  5. package/dist/access-token/access-token-mode.js.map +1 -0
  6. package/dist/account/account-manager.d.ts +13 -7
  7. package/dist/account/account-manager.d.ts.map +1 -1
  8. package/dist/account/account-manager.js +69 -52
  9. package/dist/account/account-manager.js.map +1 -1
  10. package/dist/account/account-store.d.ts +88 -77
  11. package/dist/account/account-store.d.ts.map +1 -1
  12. package/dist/account/account-store.js +24 -73
  13. package/dist/account/account-store.js.map +1 -1
  14. package/dist/account/sign-in-data.d.ts +4 -13
  15. package/dist/account/sign-in-data.d.ts.map +1 -1
  16. package/dist/account/sign-in-data.js +9 -9
  17. package/dist/account/sign-in-data.js.map +1 -1
  18. package/dist/account/sign-up-input.d.ts +4 -5
  19. package/dist/account/sign-up-input.d.ts.map +1 -1
  20. package/dist/account/sign-up-input.js +13 -3
  21. package/dist/account/sign-up-input.js.map +1 -1
  22. package/dist/client/client-manager.d.ts +4 -1
  23. package/dist/client/client-manager.d.ts.map +1 -1
  24. package/dist/client/client-manager.js +13 -1
  25. package/dist/client/client-manager.js.map +1 -1
  26. package/dist/client/client-store.d.ts +1 -1
  27. package/dist/client/client-store.d.ts.map +1 -1
  28. package/dist/constants.d.ts +5 -1
  29. package/dist/constants.d.ts.map +1 -1
  30. package/dist/constants.js +6 -2
  31. package/dist/constants.js.map +1 -1
  32. package/dist/customization/branding.d.ts +54 -0
  33. package/dist/customization/branding.d.ts.map +1 -0
  34. package/dist/customization/branding.js +13 -0
  35. package/dist/customization/branding.js.map +1 -0
  36. package/dist/customization/build-customization-css.d.ts +3 -0
  37. package/dist/customization/build-customization-css.d.ts.map +1 -0
  38. package/dist/customization/build-customization-css.js +27 -0
  39. package/dist/customization/build-customization-css.js.map +1 -0
  40. package/dist/customization/build-customization-data.d.ts +4 -0
  41. package/dist/customization/build-customization-data.d.ts.map +1 -0
  42. package/dist/customization/build-customization-data.js +18 -0
  43. package/dist/customization/build-customization-data.js.map +1 -0
  44. package/dist/customization/colors.d.ts +7 -0
  45. package/dist/customization/colors.d.ts.map +1 -0
  46. package/dist/customization/colors.js +27 -0
  47. package/dist/customization/colors.js.map +1 -0
  48. package/dist/customization/customization.d.ts +129 -0
  49. package/dist/customization/customization.d.ts.map +1 -0
  50. package/dist/customization/customization.js +26 -0
  51. package/dist/customization/customization.js.map +1 -0
  52. package/dist/customization/links.d.ts +26 -0
  53. package/dist/customization/links.d.ts.map +1 -0
  54. package/dist/customization/links.js +12 -0
  55. package/dist/customization/links.js.map +1 -0
  56. package/dist/device/device-id.d.ts +1 -0
  57. package/dist/device/device-id.d.ts.map +1 -1
  58. package/dist/device/device-id.js +4 -0
  59. package/dist/device/device-id.js.map +1 -1
  60. package/dist/device/device-manager.d.ts +6 -36
  61. package/dist/device/device-manager.d.ts.map +1 -1
  62. package/dist/device/device-manager.js +49 -43
  63. package/dist/device/device-manager.js.map +1 -1
  64. package/dist/device/device-store.d.ts +1 -0
  65. package/dist/device/device-store.d.ts.map +1 -1
  66. package/dist/device/device-store.js.map +1 -1
  67. package/dist/dpop/dpop-manager.d.ts +3 -3
  68. package/dist/dpop/dpop-nonce.d.ts +3 -3
  69. package/dist/dpop/dpop-nonce.d.ts.map +1 -1
  70. package/dist/errors/access-denied-error.d.ts +4 -3
  71. package/dist/errors/access-denied-error.d.ts.map +1 -1
  72. package/dist/errors/access-denied-error.js +5 -6
  73. package/dist/errors/access-denied-error.js.map +1 -1
  74. package/dist/{output/build-error-payload.d.ts → errors/error-parser.d.ts} +1 -1
  75. package/dist/errors/error-parser.d.ts.map +1 -0
  76. package/dist/{output/build-error-payload.js → errors/error-parser.js} +2 -2
  77. package/dist/errors/error-parser.js.map +1 -0
  78. package/dist/errors/invalid-grant-error.d.ts +1 -0
  79. package/dist/errors/invalid-grant-error.d.ts.map +1 -1
  80. package/dist/errors/invalid-grant-error.js +5 -0
  81. package/dist/errors/invalid-grant-error.js.map +1 -1
  82. package/dist/errors/login-required-error.d.ts +1 -0
  83. package/dist/errors/login-required-error.d.ts.map +1 -1
  84. package/dist/errors/login-required-error.js +5 -0
  85. package/dist/errors/login-required-error.js.map +1 -1
  86. package/dist/index.d.ts +1 -0
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +1 -0
  89. package/dist/index.js.map +1 -1
  90. package/dist/lib/html/build-document.d.ts +2 -2
  91. package/dist/lib/html/build-document.d.ts.map +1 -1
  92. package/dist/lib/html/build-document.js +4 -0
  93. package/dist/lib/html/build-document.js.map +1 -1
  94. package/dist/lib/html/hydration-data.d.ts +4 -0
  95. package/dist/lib/html/hydration-data.d.ts.map +1 -0
  96. package/dist/{output/backend-data.js → lib/html/hydration-data.js} +8 -8
  97. package/dist/lib/html/hydration-data.js.map +1 -0
  98. package/dist/lib/html/tags.d.ts +1 -1
  99. package/dist/lib/html/tags.d.ts.map +1 -1
  100. package/dist/lib/html/tags.js +1 -1
  101. package/dist/lib/html/tags.js.map +1 -1
  102. package/dist/lib/http/accept.d.ts +2 -2
  103. package/dist/lib/http/accept.d.ts.map +1 -1
  104. package/dist/lib/http/accept.js +1 -1
  105. package/dist/lib/http/accept.js.map +1 -1
  106. package/dist/lib/http/context.d.ts +2 -4
  107. package/dist/lib/http/context.d.ts.map +1 -1
  108. package/dist/lib/http/context.js +29 -4
  109. package/dist/lib/http/context.js.map +1 -1
  110. package/dist/lib/http/headers.d.ts +3 -0
  111. package/dist/lib/http/headers.d.ts.map +1 -0
  112. package/dist/lib/http/headers.js +14 -0
  113. package/dist/lib/http/headers.js.map +1 -0
  114. package/dist/lib/http/index.d.ts +1 -0
  115. package/dist/lib/http/index.d.ts.map +1 -1
  116. package/dist/lib/http/index.js +1 -0
  117. package/dist/lib/http/index.js.map +1 -1
  118. package/dist/lib/http/middleware.d.ts +1 -1
  119. package/dist/lib/http/middleware.d.ts.map +1 -1
  120. package/dist/lib/http/middleware.js +8 -24
  121. package/dist/lib/http/middleware.js.map +1 -1
  122. package/dist/lib/http/parser.d.ts +3 -3
  123. package/dist/lib/http/parser.d.ts.map +1 -1
  124. package/dist/lib/http/request.d.ts +13 -9
  125. package/dist/lib/http/request.d.ts.map +1 -1
  126. package/dist/lib/http/request.js +27 -49
  127. package/dist/lib/http/request.js.map +1 -1
  128. package/dist/lib/http/response.d.ts +6 -2
  129. package/dist/lib/http/response.d.ts.map +1 -1
  130. package/dist/lib/http/response.js +31 -11
  131. package/dist/lib/http/response.js.map +1 -1
  132. package/dist/lib/http/route.d.ts +3 -3
  133. package/dist/lib/http/route.d.ts.map +1 -1
  134. package/dist/lib/http/route.js +1 -1
  135. package/dist/lib/http/route.js.map +1 -1
  136. package/dist/lib/http/router.d.ts +12 -11
  137. package/dist/lib/http/router.d.ts.map +1 -1
  138. package/dist/lib/http/router.js +26 -34
  139. package/dist/lib/http/router.js.map +1 -1
  140. package/dist/lib/http/security-headers.js +1 -1
  141. package/dist/lib/http/security-headers.js.map +1 -1
  142. package/dist/lib/http/stream.d.ts +3 -3
  143. package/dist/lib/http/stream.d.ts.map +1 -1
  144. package/dist/lib/http/types.d.ts +1 -1
  145. package/dist/lib/http/types.d.ts.map +1 -1
  146. package/dist/lib/send-web-page.d.ts +8 -0
  147. package/dist/lib/send-web-page.d.ts.map +1 -0
  148. package/dist/{output → lib}/send-web-page.js +9 -7
  149. package/dist/lib/send-web-page.js.map +1 -0
  150. package/dist/lib/util/authorization-header.d.ts.map +1 -1
  151. package/dist/lib/util/color.d.ts +32 -0
  152. package/dist/lib/util/color.d.ts.map +1 -0
  153. package/dist/lib/util/color.js +116 -0
  154. package/dist/lib/util/color.js.map +1 -0
  155. package/dist/lib/util/crypto.d.ts +1 -0
  156. package/dist/lib/util/crypto.d.ts.map +1 -1
  157. package/dist/lib/util/crypto.js +8 -3
  158. package/dist/lib/util/crypto.js.map +1 -1
  159. package/dist/lib/util/function.d.ts +1 -0
  160. package/dist/lib/util/function.d.ts.map +1 -1
  161. package/dist/lib/util/function.js +12 -0
  162. package/dist/lib/util/function.js.map +1 -1
  163. package/dist/lib/util/locale.d.ts +20 -0
  164. package/dist/lib/util/locale.d.ts.map +1 -0
  165. package/dist/lib/util/locale.js +14 -0
  166. package/dist/lib/util/locale.js.map +1 -0
  167. package/dist/lib/util/time.d.ts +1 -1
  168. package/dist/lib/util/time.d.ts.map +1 -1
  169. package/dist/lib/util/time.js +1 -1
  170. package/dist/lib/util/time.js.map +1 -1
  171. package/dist/lib/util/type.d.ts +22 -0
  172. package/dist/lib/util/type.d.ts.map +1 -1
  173. package/dist/lib/util/type.js.map +1 -1
  174. package/dist/lib/util/ui8.d.ts +4 -0
  175. package/dist/lib/util/ui8.d.ts.map +1 -0
  176. package/dist/lib/util/ui8.js +17 -0
  177. package/dist/lib/util/ui8.js.map +1 -0
  178. package/dist/lib/util/zod-error.d.ts +2 -0
  179. package/dist/lib/util/zod-error.d.ts.map +1 -0
  180. package/dist/lib/util/zod-error.js +16 -0
  181. package/dist/lib/util/zod-error.js.map +1 -0
  182. package/dist/oauth-errors.d.ts +22 -22
  183. package/dist/oauth-errors.d.ts.map +1 -1
  184. package/dist/oauth-errors.js +37 -45
  185. package/dist/oauth-errors.js.map +1 -1
  186. package/dist/oauth-hooks.d.ts +11 -23
  187. package/dist/oauth-hooks.d.ts.map +1 -1
  188. package/dist/oauth-hooks.js.map +1 -1
  189. package/dist/oauth-middleware.d.ts +12 -0
  190. package/dist/oauth-middleware.d.ts.map +1 -0
  191. package/dist/oauth-middleware.js +32 -0
  192. package/dist/oauth-middleware.js.map +1 -0
  193. package/dist/oauth-provider.d.ts +109 -113
  194. package/dist/oauth-provider.d.ts.map +1 -1
  195. package/dist/oauth-provider.js +124 -542
  196. package/dist/oauth-provider.js.map +1 -1
  197. package/dist/oauth-verifier.d.ts +7 -26
  198. package/dist/oauth-verifier.d.ts.map +1 -1
  199. package/dist/oauth-verifier.js +6 -16
  200. package/dist/oauth-verifier.js.map +1 -1
  201. package/dist/request/code.d.ts.map +1 -1
  202. package/dist/request/request-data.d.ts +2 -4
  203. package/dist/request/request-data.d.ts.map +1 -1
  204. package/dist/request/request-data.js.map +1 -1
  205. package/dist/request/request-manager.d.ts +4 -2
  206. package/dist/request/request-manager.d.ts.map +1 -1
  207. package/dist/request/request-manager.js +9 -8
  208. package/dist/request/request-manager.js.map +1 -1
  209. package/dist/request/request-store.d.ts +6 -0
  210. package/dist/request/request-store.d.ts.map +1 -1
  211. package/dist/request/request-store.js +3 -1
  212. package/dist/request/request-store.js.map +1 -1
  213. package/dist/result/authorization-redirect-parameters.d.ts +18 -0
  214. package/dist/result/authorization-redirect-parameters.d.ts.map +1 -0
  215. package/dist/result/authorization-redirect-parameters.js +3 -0
  216. package/dist/result/authorization-redirect-parameters.js.map +1 -0
  217. package/dist/result/authorization-result-authorize-page.d.ts +13 -0
  218. package/dist/result/authorization-result-authorize-page.d.ts.map +1 -0
  219. package/dist/result/authorization-result-authorize-page.js +3 -0
  220. package/dist/result/authorization-result-authorize-page.js.map +1 -0
  221. package/dist/result/authorization-result-redirect.d.ts +8 -0
  222. package/dist/result/authorization-result-redirect.d.ts.map +1 -0
  223. package/dist/result/authorization-result-redirect.js +3 -0
  224. package/dist/result/authorization-result-redirect.js.map +1 -0
  225. package/dist/router/assets/assets-manifest.d.ts +10 -0
  226. package/dist/router/assets/assets-manifest.d.ts.map +1 -0
  227. package/dist/router/assets/assets-manifest.js +77 -0
  228. package/dist/router/assets/assets-manifest.js.map +1 -0
  229. package/dist/router/assets/assets.d.ts +16 -0
  230. package/dist/router/assets/assets.d.ts.map +1 -0
  231. package/dist/router/assets/assets.js +43 -0
  232. package/dist/router/assets/assets.js.map +1 -0
  233. package/dist/router/assets/csrf.d.ts +4 -0
  234. package/dist/router/assets/csrf.d.ts.map +1 -0
  235. package/dist/router/assets/csrf.js +51 -0
  236. package/dist/router/assets/csrf.js.map +1 -0
  237. package/dist/router/assets/send-account-page.d.ts +7 -0
  238. package/dist/router/assets/send-account-page.d.ts.map +1 -0
  239. package/dist/router/assets/send-account-page.js +34 -0
  240. package/dist/router/assets/send-account-page.js.map +1 -0
  241. package/dist/router/assets/send-authorization-page.d.ts +5 -0
  242. package/dist/router/assets/send-authorization-page.d.ts.map +1 -0
  243. package/dist/router/assets/send-authorization-page.js +49 -0
  244. package/dist/router/assets/send-authorization-page.js.map +1 -0
  245. package/dist/router/assets/send-error-page.d.ts +4 -0
  246. package/dist/router/assets/send-error-page.d.ts.map +1 -0
  247. package/dist/router/assets/send-error-page.js +34 -0
  248. package/dist/router/assets/send-error-page.js.map +1 -0
  249. package/dist/router/create-account-page-middleware.d.ts +6 -0
  250. package/dist/router/create-account-page-middleware.d.ts.map +1 -0
  251. package/dist/router/create-account-page-middleware.js +39 -0
  252. package/dist/router/create-account-page-middleware.js.map +1 -0
  253. package/dist/router/create-api-middleware.d.ts +8 -0
  254. package/dist/router/create-api-middleware.d.ts.map +1 -0
  255. package/dist/router/create-api-middleware.js +501 -0
  256. package/dist/router/create-api-middleware.js.map +1 -0
  257. package/dist/router/create-authorization-page-middleware.d.ts +6 -0
  258. package/dist/router/create-authorization-page-middleware.d.ts.map +1 -0
  259. package/dist/router/create-authorization-page-middleware.js +104 -0
  260. package/dist/router/create-authorization-page-middleware.js.map +1 -0
  261. package/dist/router/create-oauth-middleware.d.ts +6 -0
  262. package/dist/router/create-oauth-middleware.d.ts.map +1 -0
  263. package/dist/router/create-oauth-middleware.js +142 -0
  264. package/dist/router/create-oauth-middleware.js.map +1 -0
  265. package/dist/router/error-handler.d.ts +3 -0
  266. package/dist/router/error-handler.d.ts.map +1 -0
  267. package/dist/{account/account.js → router/error-handler.js} +1 -1
  268. package/dist/router/error-handler.js.map +1 -0
  269. package/dist/router/middleware-options.d.ts +6 -0
  270. package/dist/router/middleware-options.d.ts.map +1 -0
  271. package/dist/router/middleware-options.js +3 -0
  272. package/dist/router/middleware-options.js.map +1 -0
  273. package/dist/router/send-redirect.d.ts +16 -0
  274. package/dist/router/send-redirect.d.ts.map +1 -0
  275. package/dist/{output/send-authorize-redirect.js → router/send-redirect.js} +40 -24
  276. package/dist/router/send-redirect.js.map +1 -0
  277. package/dist/{token/token-claims.d.ts → signer/api-token-payload.d.ts} +237 -232
  278. package/dist/signer/api-token-payload.d.ts.map +1 -0
  279. package/dist/signer/api-token-payload.js +17 -0
  280. package/dist/signer/api-token-payload.js.map +1 -0
  281. package/dist/signer/signed-token-payload.d.ts +164 -159
  282. package/dist/signer/signed-token-payload.d.ts.map +1 -1
  283. package/dist/signer/signed-token-payload.js +10 -16
  284. package/dist/signer/signed-token-payload.js.map +1 -1
  285. package/dist/signer/signer.d.ts +42 -11246
  286. package/dist/signer/signer.d.ts.map +1 -1
  287. package/dist/signer/signer.js +30 -15
  288. package/dist/signer/signer.js.map +1 -1
  289. package/dist/token/refresh-token.d.ts.map +1 -1
  290. package/dist/token/token-data.d.ts +1 -1
  291. package/dist/token/token-data.d.ts.map +1 -1
  292. package/dist/token/token-id.d.ts.map +1 -1
  293. package/dist/token/token-manager.d.ts +28 -26
  294. package/dist/token/token-manager.d.ts.map +1 -1
  295. package/dist/token/token-manager.js +138 -196
  296. package/dist/token/token-manager.js.map +1 -1
  297. package/dist/token/token-store.d.ts +4 -4
  298. package/dist/token/token-store.d.ts.map +1 -1
  299. package/dist/token/token-store.js +1 -0
  300. package/dist/token/token-store.js.map +1 -1
  301. package/dist/token/verify-token-claims.d.ts +3 -3
  302. package/dist/token/verify-token-claims.d.ts.map +1 -1
  303. package/dist/token/verify-token-claims.js +1 -1
  304. package/dist/token/verify-token-claims.js.map +1 -1
  305. package/dist/types/email-otp.d.ts +3 -0
  306. package/dist/types/email-otp.d.ts.map +1 -0
  307. package/dist/types/email-otp.js +6 -0
  308. package/dist/types/email-otp.js.map +1 -0
  309. package/dist/types/email.d.ts +3 -0
  310. package/dist/types/email.d.ts.map +1 -0
  311. package/dist/types/email.js +29 -0
  312. package/dist/types/email.js.map +1 -0
  313. package/dist/types/handle.d.ts +3 -0
  314. package/dist/types/handle.d.ts.map +1 -0
  315. package/dist/types/handle.js +22 -0
  316. package/dist/types/handle.js.map +1 -0
  317. package/dist/types/invite-code.d.ts +4 -0
  318. package/dist/types/invite-code.d.ts.map +1 -0
  319. package/dist/types/invite-code.js +6 -0
  320. package/dist/types/invite-code.js.map +1 -0
  321. package/dist/types/password.d.ts +4 -0
  322. package/dist/types/password.d.ts.map +1 -0
  323. package/dist/types/password.js +7 -0
  324. package/dist/types/password.js.map +1 -0
  325. package/package.json +11 -8
  326. package/src/access-token/access-token-mode.ts +4 -0
  327. package/src/account/account-manager.ts +105 -75
  328. package/src/account/account-store.ts +118 -114
  329. package/src/account/sign-in-data.ts +10 -10
  330. package/src/account/sign-up-input.ts +13 -4
  331. package/src/client/client-manager.ts +34 -2
  332. package/src/client/client-store.ts +1 -1
  333. package/src/constants.ts +6 -1
  334. package/src/customization/branding.ts +12 -0
  335. package/src/customization/build-customization-css.ts +30 -0
  336. package/src/customization/build-customization-data.ts +22 -0
  337. package/src/customization/colors.ts +30 -0
  338. package/src/customization/customization.ts +25 -0
  339. package/src/customization/links.ts +10 -0
  340. package/src/device/device-id.ts +5 -0
  341. package/src/device/device-manager.ts +76 -66
  342. package/src/device/device-store.ts +2 -0
  343. package/src/errors/access-denied-error.ts +24 -17
  344. package/src/{output/build-error-payload.ts → errors/error-parser.ts} +1 -1
  345. package/src/errors/invalid-grant-error.ts +5 -0
  346. package/src/errors/login-required-error.ts +10 -0
  347. package/src/index.ts +1 -0
  348. package/src/lib/html/build-document.ts +6 -4
  349. package/src/{output/backend-data.ts → lib/html/hydration-data.ts} +7 -5
  350. package/src/lib/html/tags.ts +2 -2
  351. package/src/lib/http/accept.ts +3 -3
  352. package/src/lib/http/context.ts +41 -10
  353. package/src/lib/http/headers.ts +15 -0
  354. package/src/lib/http/index.ts +1 -0
  355. package/src/lib/http/middleware.ts +8 -23
  356. package/src/lib/http/request.ts +40 -75
  357. package/src/lib/http/response.ts +39 -15
  358. package/src/lib/http/route.ts +8 -5
  359. package/src/lib/http/router.ts +40 -46
  360. package/src/lib/http/security-headers.ts +1 -1
  361. package/src/lib/http/types.ts +1 -6
  362. package/src/{output → lib}/send-web-page.ts +10 -9
  363. package/src/lib/util/color.ts +132 -0
  364. package/src/lib/util/crypto.ts +9 -4
  365. package/src/lib/util/function.ts +14 -0
  366. package/src/lib/util/locale.ts +18 -0
  367. package/src/lib/util/time.ts +3 -4
  368. package/src/lib/util/type.ts +24 -0
  369. package/src/lib/util/ui8.ts +14 -0
  370. package/src/lib/util/zod-error.ts +14 -0
  371. package/src/oauth-errors.ts +22 -22
  372. package/src/oauth-hooks.ts +11 -24
  373. package/src/oauth-middleware.ts +53 -0
  374. package/src/oauth-provider.ts +290 -1061
  375. package/src/oauth-verifier.ts +9 -55
  376. package/src/request/request-data.ts +5 -4
  377. package/src/request/request-manager.ts +11 -11
  378. package/src/request/request-store.ts +7 -0
  379. package/src/result/authorization-redirect-parameters.ts +24 -0
  380. package/src/result/authorization-result-authorize-page.ts +14 -0
  381. package/src/result/authorization-result-redirect.ts +8 -0
  382. package/src/router/assets/assets-manifest.ts +108 -0
  383. package/src/router/assets/assets.ts +54 -0
  384. package/src/router/assets/csrf.ts +63 -0
  385. package/src/router/assets/send-account-page.ts +43 -0
  386. package/src/router/assets/send-authorization-page.ts +62 -0
  387. package/src/router/assets/send-error-page.ts +42 -0
  388. package/src/router/create-account-page-middleware.ts +69 -0
  389. package/src/router/create-api-middleware.ts +814 -0
  390. package/src/router/create-authorization-page-middleware.ts +173 -0
  391. package/src/router/create-oauth-middleware.ts +247 -0
  392. package/src/router/error-handler.ts +6 -0
  393. package/src/router/middleware-options.ts +9 -0
  394. package/src/router/send-redirect.ts +142 -0
  395. package/src/signer/api-token-payload.ts +18 -0
  396. package/src/signer/signed-token-payload.ts +18 -28
  397. package/src/signer/signer.ts +49 -34
  398. package/src/token/token-data.ts +1 -1
  399. package/src/token/token-manager.ts +190 -239
  400. package/src/token/token-store.ts +6 -4
  401. package/src/token/verify-token-claims.ts +4 -4
  402. package/src/types/email-otp.ts +3 -0
  403. package/src/types/email.ts +26 -0
  404. package/src/types/handle.ts +18 -0
  405. package/src/types/invite-code.ts +4 -0
  406. package/src/types/password.ts +4 -0
  407. package/tsconfig.build.tsbuildinfo +1 -0
  408. package/tsconfig.json +1 -1
  409. package/dist/access-token/access-token-type.d.ts +0 -6
  410. package/dist/access-token/access-token-type.d.ts.map +0 -1
  411. package/dist/access-token/access-token-type.js +0 -10
  412. package/dist/access-token/access-token-type.js.map +0 -1
  413. package/dist/account/account.d.ts +0 -2
  414. package/dist/account/account.d.ts.map +0 -1
  415. package/dist/account/account.js.map +0 -1
  416. package/dist/assets/assets-middleware.d.ts +0 -5
  417. package/dist/assets/assets-middleware.d.ts.map +0 -1
  418. package/dist/assets/assets-middleware.js +0 -41
  419. package/dist/assets/assets-middleware.js.map +0 -1
  420. package/dist/lib/locale.d.ts +0 -15
  421. package/dist/lib/locale.d.ts.map +0 -1
  422. package/dist/lib/locale.js +0 -17
  423. package/dist/lib/locale.js.map +0 -1
  424. package/dist/output/backend-data.d.ts +0 -4
  425. package/dist/output/backend-data.d.ts.map +0 -1
  426. package/dist/output/backend-data.js.map +0 -1
  427. package/dist/output/build-authorize-data.d.ts +0 -29
  428. package/dist/output/build-authorize-data.d.ts.map +0 -1
  429. package/dist/output/build-authorize-data.js +0 -21
  430. package/dist/output/build-authorize-data.js.map +0 -1
  431. package/dist/output/build-customization-data.d.ts +0 -234
  432. package/dist/output/build-customization-data.d.ts.map +0 -1
  433. package/dist/output/build-customization-data.js +0 -174
  434. package/dist/output/build-customization-data.js.map +0 -1
  435. package/dist/output/build-error-data.d.ts +0 -3
  436. package/dist/output/build-error-data.d.ts.map +0 -1
  437. package/dist/output/build-error-data.js +0 -10
  438. package/dist/output/build-error-data.js.map +0 -1
  439. package/dist/output/build-error-payload.d.ts.map +0 -1
  440. package/dist/output/build-error-payload.js.map +0 -1
  441. package/dist/output/output-manager.d.ts +0 -28
  442. package/dist/output/output-manager.d.ts.map +0 -1
  443. package/dist/output/output-manager.js +0 -134
  444. package/dist/output/output-manager.js.map +0 -1
  445. package/dist/output/send-authorize-redirect.d.ts +0 -25
  446. package/dist/output/send-authorize-redirect.d.ts.map +0 -1
  447. package/dist/output/send-authorize-redirect.js.map +0 -1
  448. package/dist/output/send-web-page.d.ts +0 -8
  449. package/dist/output/send-web-page.d.ts.map +0 -1
  450. package/dist/output/send-web-page.js.map +0 -1
  451. package/dist/token/token-claims.d.ts.map +0 -1
  452. package/dist/token/token-claims.js +0 -27
  453. package/dist/token/token-claims.js.map +0 -1
  454. package/src/access-token/access-token-type.ts +0 -5
  455. package/src/account/account.ts +0 -1
  456. package/src/assets/assets-middleware.ts +0 -44
  457. package/src/lib/locale.ts +0 -21
  458. package/src/output/build-authorize-data.ts +0 -53
  459. package/src/output/build-customization-data.ts +0 -217
  460. package/src/output/build-error-data.ts +0 -8
  461. package/src/output/output-manager.ts +0 -188
  462. package/src/output/send-authorize-redirect.ts +0 -137
  463. package/src/token/token-claims.ts +0 -30
  464. package/tsconfig.backend.tsbuildinfo +0 -1
  465. /package/{tsconfig.backend.json → tsconfig.build.json} +0 -0
@@ -0,0 +1,173 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http'
2
+ import {
3
+ oauthAuthorizationRequestQuerySchema,
4
+ oauthClientCredentialsSchema,
5
+ } from '@atproto/oauth-types'
6
+ import { AccessDeniedError } from '../errors/access-denied-error.js'
7
+ import { InvalidRequestError } from '../errors/invalid-request-error.js'
8
+ import {
9
+ Middleware,
10
+ Router,
11
+ RouterCtx,
12
+ validateFetchDest,
13
+ validateFetchMode,
14
+ validateFetchSite,
15
+ validateOrigin,
16
+ validateReferrer,
17
+ } from '../lib/http/index.js'
18
+ import type { Awaitable } from '../lib/util/type.js'
19
+ import { extractZodErrorMessage } from '../lib/util/zod-error.js'
20
+ import type { OAuthProvider } from '../oauth-provider.js'
21
+ import { requestUriSchema } from '../request/request-uri.js'
22
+ import { AuthorizationResultRedirect } from '../result/authorization-result-redirect.js'
23
+ import { sendAuthorizePageFactory } from './assets/send-authorization-page.js'
24
+ import { sendErrorPageFactory } from './assets/send-error-page.js'
25
+ import { parseRedirectUrl } from './create-api-middleware.js'
26
+ import type { MiddlewareOptions } from './middleware-options.js'
27
+ import {
28
+ buildRedirectMode,
29
+ buildRedirectParams,
30
+ buildRedirectUri,
31
+ sendRedirect,
32
+ } from './send-redirect.js'
33
+
34
+ export function createAuthorizationPageMiddleware<
35
+ Ctx extends object | void = void,
36
+ Req extends IncomingMessage = IncomingMessage,
37
+ Res extends ServerResponse = ServerResponse,
38
+ >(
39
+ server: OAuthProvider,
40
+ { onError }: MiddlewareOptions<Req, Res>,
41
+ ): Middleware<Ctx, Req, Res> {
42
+ const sendAuthorizePage = sendAuthorizePageFactory(server.customization)
43
+ const sendErrorPage = sendErrorPageFactory(server.customization)
44
+
45
+ const issuerUrl = new URL(server.issuer)
46
+ const issuerOrigin = issuerUrl.origin
47
+
48
+ const router = new Router<Ctx, Req, Res>(issuerUrl)
49
+
50
+ router.get(
51
+ '/oauth/authorize',
52
+ withErrorHandler(async function (req, res) {
53
+ res.setHeader('Cache-Control', 'no-store')
54
+ res.setHeader('Pragma', 'no-cache')
55
+
56
+ validateFetchSite(req, ['cross-site', 'none'])
57
+ validateFetchMode(req, ['navigate'])
58
+ validateFetchDest(req, ['document'])
59
+ validateOrigin(req, issuerOrigin)
60
+
61
+ const query = Object.fromEntries(this.url.searchParams)
62
+
63
+ const clientCredentials = await oauthClientCredentialsSchema
64
+ .parseAsync(query, { path: ['query'] })
65
+ .catch(throwInvalidRequest)
66
+
67
+ if ('client_secret' in clientCredentials) {
68
+ throw new InvalidRequestError('Client secret must not be provided')
69
+ }
70
+
71
+ const authorizationRequest = await oauthAuthorizationRequestQuerySchema
72
+ .parseAsync(query, { path: ['query'] })
73
+ .catch(throwInvalidRequest)
74
+
75
+ const deviceInfo = await server.deviceManager.load(req, res)
76
+
77
+ try {
78
+ const result = await server.authorize(
79
+ clientCredentials,
80
+ authorizationRequest,
81
+ deviceInfo.deviceId,
82
+ deviceInfo.deviceMetadata,
83
+ )
84
+
85
+ if ('redirect' in result) {
86
+ return sendAuthorizeRedirect(res, result)
87
+ } else {
88
+ return sendAuthorizePage(req, res, result)
89
+ }
90
+ } catch (err) {
91
+ // If we have the "redirect_uri" parameter, we can redirect the user
92
+ // to the client with an error.
93
+ if (err instanceof AccessDeniedError && err.parameters.redirect_uri) {
94
+ // Prefer logging the cause
95
+ onError?.(req, res, err.cause ?? err, 'Authorization failed')
96
+
97
+ return sendAuthorizeRedirect(res, {
98
+ issuer: server.issuer,
99
+ parameters: err.parameters,
100
+ redirect: err.toJSON(),
101
+ })
102
+ }
103
+
104
+ throw err
105
+ }
106
+ }),
107
+ )
108
+
109
+ // This is a private endpoint that will be called by the user after the
110
+ // authorization request was either approved or denied. The logic performed
111
+ // here **could** be performed directly in the frontend. We decided to
112
+ // implement it here to avoid duplicating the logic.
113
+ router.get(
114
+ '/oauth/authorize/redirect',
115
+ withErrorHandler(async function (req, res) {
116
+ // Ensure we come from the authorization page
117
+ validateFetchSite(req, ['same-origin'])
118
+ validateFetchMode(req, ['navigate'])
119
+ validateFetchDest(req, ['document'])
120
+ validateOrigin(req, issuerOrigin)
121
+
122
+ const referrer = validateReferrer(req, {
123
+ origin: issuerOrigin,
124
+ pathname: '/oauth/authorize',
125
+ })
126
+
127
+ // Ensure we are coming from the authorization page
128
+ requestUriSchema.parse(referrer.searchParams.get('request_uri'))
129
+
130
+ return sendRedirect(res, parseRedirectUrl(this.url))
131
+ }),
132
+ )
133
+
134
+ return router.buildMiddleware()
135
+
136
+ function withErrorHandler<T extends RouterCtx>(
137
+ handler: (this: T, req: Req, res: Res) => Awaitable<void>,
138
+ ): Middleware<T, Req, Res> {
139
+ return async function (req, res) {
140
+ try {
141
+ await handler.call(this, req, res)
142
+ } catch (err) {
143
+ onError?.(
144
+ req,
145
+ res,
146
+ err,
147
+ `Failed to handle navigation request to "${req.url}"`,
148
+ )
149
+
150
+ if (!res.headersSent) {
151
+ sendErrorPage(req, res, err)
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+
158
+ function throwInvalidRequest(err: unknown): never {
159
+ throw new InvalidRequestError(
160
+ extractZodErrorMessage(err) ?? 'Input validation error',
161
+ err,
162
+ )
163
+ }
164
+
165
+ function sendAuthorizeRedirect(
166
+ res: ServerResponse,
167
+ { issuer, parameters, redirect }: AuthorizationResultRedirect,
168
+ ) {
169
+ const redirectUri = buildRedirectUri(parameters)
170
+ const mode = buildRedirectMode(parameters)
171
+ const params = buildRedirectParams(issuer, parameters, redirect)
172
+ return sendRedirect(res, { mode, redirectUri, params })
173
+ }
@@ -0,0 +1,247 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http'
2
+ import {
3
+ oauthAuthorizationRequestParSchema,
4
+ oauthClientCredentialsSchema,
5
+ oauthTokenIdentificationSchema,
6
+ oauthTokenRequestSchema,
7
+ } from '@atproto/oauth-types'
8
+ import { buildErrorPayload, buildErrorStatus } from '../errors/error-parser.js'
9
+ import { InvalidClientError } from '../errors/invalid-client-error.js'
10
+ import { InvalidGrantError } from '../errors/invalid-grant-error.js'
11
+ import { InvalidRequestError } from '../errors/invalid-request-error.js'
12
+ import { WWWAuthenticateError } from '../errors/www-authenticate-error.js'
13
+ import {
14
+ Middleware,
15
+ Router,
16
+ cacheControlMiddleware,
17
+ combineMiddlewares,
18
+ jsonHandler,
19
+ parseHttpRequest,
20
+ staticJsonMiddleware,
21
+ } from '../lib/http/index.js'
22
+ import { extractZodErrorMessage } from '../lib/util/zod-error.js'
23
+ import type { OAuthProvider } from '../oauth-provider.js'
24
+ import type { MiddlewareOptions } from './middleware-options.js'
25
+
26
+ // CORS preflight
27
+ const corsHeaders: Middleware = function (req, res, next) {
28
+ res.setHeader('Access-Control-Max-Age', '86400') // 1 day
29
+
30
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
31
+ //
32
+ // > For requests without credentials, the literal value "*" can be
33
+ // > specified as a wildcard; the value tells browsers to allow
34
+ // > requesting code from any origin to access the resource.
35
+ // > Attempting to use the wildcard with credentials results in an
36
+ // > error.
37
+ //
38
+ // A "*" is safer to use than reflecting the request origin.
39
+ res.setHeader('Access-Control-Allow-Origin', '*')
40
+
41
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
42
+ // > The value "*" only counts as a special wildcard value for
43
+ // > requests without credentials (requests without HTTP cookies or
44
+ // > HTTP authentication information). In requests with credentials,
45
+ // > it is treated as the literal method name "*" without special
46
+ // > semantics.
47
+ res.setHeader('Access-Control-Allow-Methods', '*')
48
+
49
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type,DPoP')
50
+
51
+ next()
52
+ }
53
+
54
+ const corsPreflight: Middleware = combineMiddlewares([
55
+ corsHeaders,
56
+ (req, res) => {
57
+ res.writeHead(200).end()
58
+ },
59
+ ])
60
+
61
+ export function createOAuthMiddleware<
62
+ Ctx extends object | void = void,
63
+ Req extends IncomingMessage = IncomingMessage,
64
+ Res extends ServerResponse = ServerResponse,
65
+ >(
66
+ server: OAuthProvider,
67
+ { onError }: MiddlewareOptions<Req, Res>,
68
+ ): Middleware<Ctx, Req, Res> {
69
+ const router = new Router<Ctx, Req, Res>(new URL(server.issuer))
70
+
71
+ //- Public OAuth endpoints
72
+
73
+ router.options('/.well-known/oauth-authorization-server', corsPreflight)
74
+ router.get(
75
+ '/.well-known/oauth-authorization-server',
76
+ corsHeaders,
77
+ cacheControlMiddleware(300),
78
+ staticJsonMiddleware(server.metadata),
79
+ )
80
+
81
+ router.options('/oauth/jwks', corsPreflight)
82
+ router.get(
83
+ '/oauth/jwks',
84
+ corsHeaders,
85
+ cacheControlMiddleware(300),
86
+ staticJsonMiddleware(server.jwks),
87
+ )
88
+
89
+ router.options('/oauth/par', corsPreflight)
90
+ router.post(
91
+ '/oauth/par',
92
+ corsHeaders,
93
+ oauthHandler(async function (req) {
94
+ const payload = await parseHttpRequest(req, ['json', 'urlencoded'])
95
+
96
+ const credentials = await oauthClientCredentialsSchema
97
+ .parseAsync(payload, { path: ['body'] })
98
+ .catch(throwInvalidRequest)
99
+
100
+ const authorizationRequest = await oauthAuthorizationRequestParSchema
101
+ .parseAsync(payload, { path: ['body'] })
102
+ .catch(throwInvalidRequest)
103
+
104
+ const dpopJkt = await server.checkDpopProof(
105
+ req.headers['dpop'],
106
+ req.method!,
107
+ this.url,
108
+ )
109
+
110
+ return server.pushedAuthorizationRequest(
111
+ credentials,
112
+ authorizationRequest,
113
+ dpopJkt,
114
+ )
115
+ }, 201),
116
+ )
117
+ // https://datatracker.ietf.org/doc/html/rfc9126#section-2.3
118
+ // > If the request did not use the POST method, the authorization server
119
+ // > responds with an HTTP 405 (Method Not Allowed) status code.
120
+ router.all('/oauth/par', (req, res) => {
121
+ res.writeHead(405).end()
122
+ })
123
+
124
+ router.options('/oauth/token', corsPreflight)
125
+ router.post(
126
+ '/oauth/token',
127
+ corsHeaders,
128
+ oauthHandler(async function (req) {
129
+ const payload = await parseHttpRequest(req, ['json', 'urlencoded'])
130
+
131
+ const clientMetadata = await server.deviceManager.getRequestMetadata(req)
132
+
133
+ const clientCredentials = await oauthClientCredentialsSchema
134
+ .parseAsync(payload, { path: ['body'] })
135
+ .catch(throwInvalidClient)
136
+
137
+ const tokenRequest = await oauthTokenRequestSchema
138
+ .parseAsync(payload, { path: ['body'] })
139
+ .catch(throwInvalidGrant)
140
+
141
+ const dpopJkt = await server.checkDpopProof(
142
+ req.headers['dpop'],
143
+ req.method!,
144
+ this.url,
145
+ )
146
+
147
+ return server.token(
148
+ clientCredentials,
149
+ clientMetadata,
150
+ tokenRequest,
151
+ dpopJkt,
152
+ )
153
+ }),
154
+ )
155
+
156
+ router.options('/oauth/revoke', corsPreflight)
157
+ router.post(
158
+ '/oauth/revoke',
159
+ corsHeaders,
160
+ oauthHandler(async function (req, res) {
161
+ const payload = await parseHttpRequest(req, ['json', 'urlencoded'])
162
+
163
+ const credentials = await oauthClientCredentialsSchema
164
+ .parseAsync(payload, { path: ['body'] })
165
+ .catch(throwInvalidRequest)
166
+
167
+ const tokenIdentification = await oauthTokenIdentificationSchema
168
+ .parseAsync(payload, { path: ['body'] })
169
+ .catch(throwInvalidRequest)
170
+
171
+ try {
172
+ await server.revoke(credentials, tokenIdentification)
173
+ } catch (err) {
174
+ // > Note: invalid tokens do not cause an error response since the
175
+ // > client cannot handle such an error in a reasonable way. Moreover,
176
+ // > the purpose of the revocation request, invalidating the particular
177
+ // > token, is already achieved.
178
+ //
179
+ // https://datatracker.ietf.org/doc/html/rfc7009#section-2.2
180
+
181
+ onError?.(req, res, err, 'Failed to revoke token')
182
+ }
183
+
184
+ return {}
185
+ }),
186
+ )
187
+
188
+ return router.buildMiddleware()
189
+
190
+ function oauthHandler<T>(
191
+ buildOAuthResponse: (this: T, req: Req, res: Res) => unknown,
192
+ status?: number,
193
+ ): Middleware<T, Req, Res> {
194
+ return jsonHandler<T, Req, Res>(async function (req, res) {
195
+ try {
196
+ // https://www.rfc-editor.org/rfc/rfc6749.html#section-5.1
197
+ res.setHeader('Cache-Control', 'no-store')
198
+ res.setHeader('Pragma', 'no-cache')
199
+
200
+ // https://datatracker.ietf.org/doc/html/rfc9449#section-8.2
201
+ const dpopNonce = server.nextDpopNonce()
202
+ if (dpopNonce) {
203
+ const name = 'DPoP-Nonce'
204
+ res.setHeader(name, dpopNonce)
205
+ res.appendHeader('Access-Control-Expose-Headers', name)
206
+ }
207
+
208
+ const payload = await buildOAuthResponse.call(this, req, res)
209
+ return { payload, status }
210
+ } catch (err) {
211
+ onError?.(req, res, err, 'OAuth request error')
212
+
213
+ if (!res.headersSent && err instanceof WWWAuthenticateError) {
214
+ const name = 'WWW-Authenticate'
215
+ res.setHeader(name, err.wwwAuthenticateHeader)
216
+ res.appendHeader('Access-Control-Expose-Headers', name)
217
+ }
218
+
219
+ const status = buildErrorStatus(err)
220
+ const payload = buildErrorPayload(err)
221
+
222
+ return { payload, status }
223
+ }
224
+ })
225
+ }
226
+ }
227
+
228
+ function throwInvalidGrant(err: unknown): never {
229
+ throw new InvalidGrantError(
230
+ extractZodErrorMessage(err) ?? 'Invalid grant',
231
+ err,
232
+ )
233
+ }
234
+
235
+ function throwInvalidClient(err: unknown): never {
236
+ throw new InvalidClientError(
237
+ extractZodErrorMessage(err) ?? 'Client authentication failed',
238
+ err,
239
+ )
240
+ }
241
+
242
+ function throwInvalidRequest(err: unknown): never {
243
+ throw new InvalidRequestError(
244
+ extractZodErrorMessage(err) ?? 'Input validation error',
245
+ err,
246
+ )
247
+ }
@@ -0,0 +1,6 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http'
2
+
3
+ export type ErrorHandler<
4
+ Req extends IncomingMessage = IncomingMessage,
5
+ Res extends ServerResponse = ServerResponse,
6
+ > = (req: Req, res: Res, err: unknown, message: string) => void
@@ -0,0 +1,9 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http'
2
+ import type { ErrorHandler } from './error-handler.js'
3
+
4
+ export type MiddlewareOptions<
5
+ Req extends IncomingMessage = IncomingMessage,
6
+ Res extends ServerResponse = ServerResponse,
7
+ > = {
8
+ onError?: ErrorHandler<Req, Res>
9
+ }
@@ -0,0 +1,142 @@
1
+ import type { ServerResponse } from 'node:http'
2
+ import {
3
+ OAuthAuthorizationRequestParameters,
4
+ OAuthResponseMode,
5
+ } from '@atproto/oauth-types'
6
+ import { AccessDeniedError } from '../errors/access-denied-error.js'
7
+ import { html, js } from '../lib/html/index.js'
8
+ import { sendWebPage } from '../lib/send-web-page.js'
9
+ import { AuthorizationRedirectParameters } from '../result/authorization-redirect-parameters.js'
10
+
11
+ // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-7.5.4
12
+ const REDIRECT_STATUS_CODE = 303
13
+
14
+ export const SUCCESS_REDIRECT_KEYS = [
15
+ 'code',
16
+ 'id_token',
17
+ 'access_token',
18
+ 'expires_in',
19
+ 'token_type',
20
+ ] as const
21
+
22
+ export const ERROR_REDIRECT_KEYS = [
23
+ 'error',
24
+ 'error_description',
25
+ 'error_uri',
26
+ ] as const
27
+
28
+ export type OAuthRedirectQueryParameter =
29
+ | 'iss'
30
+ | 'state'
31
+ | (typeof SUCCESS_REDIRECT_KEYS)[number]
32
+ | (typeof ERROR_REDIRECT_KEYS)[number]
33
+
34
+ export function buildRedirectUri(
35
+ parameters: OAuthAuthorizationRequestParameters,
36
+ ): string {
37
+ const uri = parameters.redirect_uri
38
+ if (uri) return uri
39
+
40
+ throw new AccessDeniedError(parameters, 'No redirect_uri', 'invalid_request')
41
+ }
42
+
43
+ export function buildRedirectMode(
44
+ parameters: OAuthAuthorizationRequestParameters,
45
+ ): OAuthResponseMode {
46
+ const mode = parameters.response_mode || 'query' // @TODO default should depend on response_type
47
+ return mode
48
+ }
49
+
50
+ export function buildRedirectParams(
51
+ issuer: string,
52
+ parameters: OAuthAuthorizationRequestParameters,
53
+ redirect: AuthorizationRedirectParameters,
54
+ ): [OAuthRedirectQueryParameter, string][] {
55
+ const params: [OAuthRedirectQueryParameter, string][] = [
56
+ ['iss', issuer], // rfc9207
57
+ ]
58
+
59
+ if (parameters.state != null) {
60
+ params.push(['state', parameters.state])
61
+ }
62
+
63
+ const keys = 'code' in redirect ? SUCCESS_REDIRECT_KEYS : ERROR_REDIRECT_KEYS
64
+ for (const key of keys) {
65
+ const value = redirect[key]
66
+ if (value != null) params.push([key, value])
67
+ }
68
+
69
+ return params
70
+ }
71
+
72
+ export type OAuthRedirectOptions = {
73
+ mode: OAuthResponseMode
74
+ redirectUri: string
75
+ params: Iterable<[string, string]>
76
+ }
77
+
78
+ export function sendRedirect(
79
+ res: ServerResponse,
80
+ { mode, redirectUri: uri, params }: OAuthRedirectOptions,
81
+ ): void {
82
+ res.setHeader('Cache-Control', 'no-store')
83
+
84
+ switch (mode) {
85
+ case 'query':
86
+ return writeQuery(res, uri, params)
87
+ case 'fragment':
88
+ return writeFragment(res, uri, params)
89
+ case 'form_post':
90
+ return writeFormPost(res, uri, params)
91
+ }
92
+
93
+ // @ts-expect-error fool proof
94
+ throw new Error(`Unsupported mode: ${mode}`)
95
+ }
96
+
97
+ function writeQuery(
98
+ res: ServerResponse,
99
+ uri: string,
100
+ params: Iterable<[string, string]>,
101
+ ): void {
102
+ const url = new URL(uri)
103
+ for (const [key, value] of params) url.searchParams.set(key, value)
104
+ res.writeHead(REDIRECT_STATUS_CODE, { Location: url.href }).end()
105
+ }
106
+
107
+ function writeFragment(
108
+ res: ServerResponse,
109
+ uri: string,
110
+ params: Iterable<[string, string]>,
111
+ ): void {
112
+ const url = new URL(uri)
113
+ const searchParams = new URLSearchParams()
114
+ for (const [key, value] of params) searchParams.set(key, value)
115
+ url.hash = searchParams.toString()
116
+ res.writeHead(REDIRECT_STATUS_CODE, { Location: url.href }).end()
117
+ }
118
+
119
+ function writeFormPost(
120
+ res: ServerResponse,
121
+ uri: string,
122
+ params: Iterable<[string, string]>,
123
+ ): void {
124
+ // Prevent the Chrome from caching this page
125
+ // see: https://latesthackingnews.com/2023/12/12/google-updates-chrome-bfcache-for-faster-page-viewing/
126
+ res.setHeader('Set-Cookie', `bfCacheBypass=foo; max-age=1; SameSite=Lax`)
127
+ res.setHeader('Cache-Control', 'no-store')
128
+ res.setHeader('Permissions-Policy', 'otp-credentials=*, document-domain=()')
129
+
130
+ return sendWebPage(res, {
131
+ htmlAttrs: { lang: 'en' },
132
+ body: html`
133
+ <form method="post" action="${uri}">
134
+ ${Array.from(params, ([key, value]) => [
135
+ html`<input type="hidden" name="${key}" value="${value}" />`,
136
+ ])}
137
+ <input type="submit" value="Continue" />
138
+ </form>
139
+ `,
140
+ scripts: [js`document.forms[0].submit();`],
141
+ })
142
+ }
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod'
2
+ import { jwtPayloadSchema } from '@atproto/jwk'
3
+ import { deviceIdSchema } from '../oauth-store.js'
4
+ import { subSchema } from '../oidc/sub.js'
5
+ import { requestUriSchema } from '../request/request-uri.js'
6
+
7
+ export const apiTokenPayloadSchema = jwtPayloadSchema
8
+ .extend({
9
+ sub: subSchema,
10
+
11
+ deviceId: deviceIdSchema,
12
+ // If the token is bound to a particular authorization request, it can only
13
+ // be used in the context of that request.
14
+ requestUri: requestUriSchema.optional(),
15
+ })
16
+ .passthrough()
17
+
18
+ export type ApiTokenPayload = z.infer<typeof apiTokenPayloadSchema>
@@ -1,35 +1,25 @@
1
1
  import { z } from 'zod'
2
2
  import { jwtPayloadSchema } from '@atproto/jwk'
3
3
  import { clientIdSchema } from '../client/client-id.js'
4
- import { Simplify } from '../lib/util/type.js'
5
4
  import { subSchema } from '../oidc/sub.js'
6
5
  import { tokenIdSchema } from '../token/token-id.js'
7
6
 
8
- export const signedTokenPayloadSchema = z.intersection(
9
- jwtPayloadSchema
10
- .pick({
11
- exp: true,
12
- iat: true,
13
- iss: true,
14
- aud: true,
15
- })
16
- .required(),
17
- jwtPayloadSchema
18
- .omit({
19
- exp: true,
20
- iat: true,
21
- iss: true,
22
- aud: true,
23
- })
24
- .partial()
25
- .extend({
26
- jti: tokenIdSchema,
27
- sub: subSchema,
28
- client_id: clientIdSchema,
29
- })
30
- .passthrough(),
31
- )
7
+ export const signedTokenPayloadSchema = jwtPayloadSchema
8
+ .partial()
9
+ .extend({
10
+ // Following are required
11
+ jti: tokenIdSchema,
12
+ sub: subSchema,
13
+ exp: z.number().int(),
14
+ iat: z.number().int(),
15
+ iss: z.string().min(1),
32
16
 
33
- export type SignedTokenPayload = Simplify<
34
- z.infer<typeof signedTokenPayloadSchema>
35
- >
17
+ // @NOTE "aud", "scope", "client_id" are not required, as are stored in the
18
+ // DB in 'light' access token mode.
19
+
20
+ // Restrict type of following
21
+ client_id: clientIdSchema.optional(),
22
+ })
23
+ .passthrough()
24
+
25
+ export type SignedTokenPayload = z.infer<typeof signedTokenPayloadSchema>