@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
@@ -1,44 +0,0 @@
1
- import { assets } from '@atproto/oauth-provider-ui'
2
- import {
3
- Middleware,
4
- validateFetchDest,
5
- validateFetchSite,
6
- writeStream,
7
- } from '../lib/http/index.js'
8
-
9
- export const ASSETS_URL_PREFIX = '/@atproto/oauth-provider/~assets/'
10
-
11
- export function buildAssetUrl(filename: string): string {
12
- return `${ASSETS_URL_PREFIX}${encodeURIComponent(filename)}`
13
- }
14
-
15
- export function authorizeAssetsMiddleware(): Middleware {
16
- return async function assetsMiddleware(req, res, next): Promise<void> {
17
- if (req.method !== 'GET' && req.method !== 'HEAD') return next()
18
- if (!req.url?.startsWith(ASSETS_URL_PREFIX)) return next()
19
-
20
- const filename = req.url.slice(ASSETS_URL_PREFIX.length)
21
- if (!filename) return next()
22
-
23
- const asset = assets.get(filename)
24
- if (!asset) return next()
25
-
26
- try {
27
- // Allow "null" (ie. no header) to allow loading assets outside of a
28
- // fetch context (not from a web page).
29
- validateFetchSite(req, res, [null, 'none', 'cross-site', 'same-origin'])
30
- validateFetchDest(req, res, [null, 'document', 'style', 'script'])
31
- } catch (err) {
32
- return next(err)
33
- }
34
-
35
- if (req.headers['if-none-match'] === asset.sha256) {
36
- return void res.writeHead(304).end()
37
- }
38
-
39
- res.setHeader('ETag', asset.sha256)
40
- res.setHeader('Cache-Control', 'public, max-age=31536000, immutable')
41
-
42
- writeStream(res, asset.stream(), { contentType: asset.mime })
43
- }
44
- }
package/src/lib/locale.ts DELETED
@@ -1,21 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- export const localeSchema = z
4
- .string()
5
- .regex(/^[a-z]{2,3}(-[A-Z]{2})?$/, 'Invalid locale')
6
- export type Locale = z.infer<typeof localeSchema>
7
-
8
- export const multiLangStringSchema = z.intersection(
9
- z.object({ en: z.string() }), // en is required
10
- z.record(localeSchema, z.union([z.string(), z.undefined()])),
11
- )
12
- export type MultiLangString = z.infer<typeof multiLangStringSchema>
13
-
14
- export const AVAILABLE_LOCALES = [
15
- // TODO: Add more in this list as translations are added in the PO files
16
- 'en',
17
- 'fr',
18
- ] as const satisfies readonly Locale[]
19
- export type AvailableLocale = (typeof AVAILABLE_LOCALES)[number]
20
- export const isAvailableLocale = (v: unknown): v is AvailableLocale =>
21
- (AVAILABLE_LOCALES as readonly unknown[]).includes(v)
@@ -1,53 +0,0 @@
1
- import type { AuthorizeData, Session } from '@atproto/oauth-provider-api'
2
- import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
3
- import { DeviceAccountInfo } from '../account/account-store.js'
4
- import { Account } from '../account/account.js'
5
- import { Client } from '../client/client.js'
6
- import { RequestUri } from '../request/request-uri.js'
7
-
8
- export type ScopeDetail = {
9
- scope: string
10
- description?: string
11
- }
12
-
13
- export type AuthorizationResultAuthorize = {
14
- issuer: string
15
- client: Client
16
- parameters: OAuthAuthorizationRequestParameters
17
- authorize: {
18
- uri: RequestUri
19
- scopeDetails?: ScopeDetail[]
20
- sessions: readonly {
21
- account: Account
22
- info: DeviceAccountInfo
23
-
24
- selected: boolean
25
- loginRequired: boolean
26
- consentRequired: boolean
27
- }[]
28
- }
29
- }
30
-
31
- export type { AuthorizeData, Session }
32
-
33
- export function buildAuthorizeData(
34
- data: AuthorizationResultAuthorize,
35
- ): AuthorizeData {
36
- return {
37
- clientId: data.client.id,
38
- clientMetadata: data.client.metadata,
39
- clientTrusted: data.client.info.isTrusted,
40
- requestUri: data.authorize.uri,
41
- loginHint: data.parameters.login_hint,
42
- newSessionsRequireConsent: data.parameters.prompt === 'consent',
43
- scopeDetails: data.authorize.scopeDetails,
44
- sessions: data.authorize.sessions.map(
45
- (session): Session => ({
46
- account: session.account,
47
- selected: session.selected,
48
- loginRequired: session.loginRequired,
49
- consentRequired: session.consentRequired,
50
- }),
51
- ),
52
- }
53
- }
@@ -1,217 +0,0 @@
1
- import { z } from 'zod'
2
- import { CustomizationData } from '@atproto/oauth-provider-api'
3
- import { hcaptchaConfigSchema } from '../lib/hcaptcha.js'
4
- import { isLinkRel } from '../lib/html/build-document.js'
5
- import { multiLangStringSchema } from '../lib/locale.js'
6
- export { type HcaptchaConfig, hcaptchaConfigSchema } from '../lib/hcaptcha.js'
7
-
8
- // Matches colors defined in tailwind.config.js
9
- export const colorNames = ['brand', 'error', 'warning', 'success'] as const
10
- export const colorNameSchema = z.enum(colorNames)
11
- export type ColorName = z.infer<typeof colorNameSchema>
12
-
13
- const parsedColorSchema = z.string().transform((value, ctx): RgbColor => {
14
- try {
15
- const { r, g, b, a } = parseColor(value)
16
- if (a != null) {
17
- ctx.addIssue({
18
- code: z.ZodIssueCode.custom,
19
- message: 'Alpha values are not supported',
20
- })
21
- }
22
- return { r, g, b }
23
- } catch (e) {
24
- ctx.addIssue({
25
- code: z.ZodIssueCode.custom,
26
- message: e instanceof Error ? e.message : 'Invalid color value',
27
- })
28
- // Won't actually be used (since an issue was added):
29
- return { r: 0, g: 0, b: 0 }
30
- }
31
- })
32
- export type ParsedColor = z.infer<typeof parsedColorSchema> // Same as RgbColor
33
-
34
- export const colorsDefinitionSchema = z.record(
35
- colorNameSchema,
36
- parsedColorSchema.optional(),
37
- )
38
- export type ColorsDefinition = z.infer<typeof colorsDefinitionSchema>
39
-
40
- export const localizedStringSchema = z.union([
41
- z.string(),
42
- multiLangStringSchema,
43
- ])
44
- export type LocalizedString = z.infer<typeof localizedStringSchema>
45
-
46
- export const linkRelSchema = z.string().refine(isLinkRel, 'Invalid link rel')
47
- export type LinkRel = z.infer<typeof linkRelSchema>
48
-
49
- export const linkDefinitionSchema = z.object({
50
- title: localizedStringSchema,
51
- href: z.string().url(),
52
- rel: linkRelSchema.optional(),
53
- })
54
- export type LinkDefinition = z.infer<typeof linkDefinitionSchema>
55
-
56
- /**
57
- * Aesthetic customization
58
- */
59
- export const brandingConfigSchema = z.object({
60
- name: z.string().optional(),
61
- logo: z.string().optional(),
62
- colors: colorsDefinitionSchema.optional(),
63
- links: z.array(linkDefinitionSchema).optional(),
64
- })
65
- export type BrandingInput = z.input<typeof brandingConfigSchema>
66
- export type Branding = z.infer<typeof brandingConfigSchema>
67
-
68
- export const customizationSchema = z.object({
69
- /**
70
- * Available user domains that can be used to sign up. A non-empty array
71
- * is required to enable the sign-up feature.
72
- */
73
- availableUserDomains: z.array(z.string()).optional(),
74
- /**
75
- * UI customizations
76
- */
77
- branding: brandingConfigSchema.optional(),
78
- /**
79
- * Is an invite code required to sign up?
80
- */
81
- inviteCodeRequired: z.boolean().optional(),
82
- /**
83
- * Enables hCaptcha during sign-up.
84
- */
85
- hcaptcha: hcaptchaConfigSchema.optional(),
86
- })
87
- export type CustomizationInput = z.input<typeof customizationSchema>
88
- export type Customization = z.infer<typeof customizationSchema>
89
-
90
- export function buildCustomizationData({
91
- branding,
92
- availableUserDomains,
93
- inviteCodeRequired,
94
- hcaptcha,
95
- }: Customization): CustomizationData {
96
- // @NOTE the front end does not need colors here as they will be injected as
97
- // CSS variables.
98
- // @NOTE We only copy the values explicitly needed to avoid leaking sensitive
99
- // data (in case the caller passed more than what we expect).
100
- return {
101
- availableUserDomains,
102
- inviteCodeRequired,
103
- hcaptchaSiteKey: hcaptcha?.siteKey,
104
- name: branding?.name,
105
- logo: branding?.logo,
106
- links: branding?.links,
107
- }
108
- }
109
-
110
- export function buildCustomizationCss({ branding }: Customization) {
111
- const vars = Array.from(buildCustomizationVars(branding))
112
- if (vars.length) return `:root { ${vars.join(' ')} }`
113
-
114
- return ''
115
- }
116
-
117
- function* buildCustomizationVars(branding?: Branding) {
118
- if (branding?.colors) {
119
- for (const name of colorNames) {
120
- const value = branding.colors[name]
121
- if (!value) continue // Skip missing colors
122
-
123
- const { r, g, b } = value
124
-
125
- const contrast = computeLuma({ r, g, b }) > 128 ? '0 0 0' : '255 255 255'
126
-
127
- yield `--color-${name}: ${r} ${g} ${b};`
128
- yield `--color-${name}-c: ${contrast};`
129
- }
130
- }
131
- }
132
-
133
- type RgbColor = { r: number; g: number; b: number }
134
- type RgbaColor = { r: number; g: number; b: number; a?: number }
135
- function parseColor(color: string): RgbaColor {
136
- if (color.startsWith('#')) {
137
- return parseHexColor(color)
138
- }
139
-
140
- if (color.startsWith('rgba(')) {
141
- return parseRgbaColor(color)
142
- }
143
-
144
- if (color.startsWith('rgb(')) {
145
- return parseRgbColor(color)
146
- }
147
-
148
- // Should never happen (as long as the input is a validated WebColor)
149
- throw new TypeError(`Invalid color value: ${color}`)
150
- }
151
-
152
- function parseHexColor(v: string) {
153
- // parseInt('az', 16) does not return NaN so we need to check the format
154
- if (!/^#[0-9a-f]+$/i.test(v)) {
155
- throw new TypeError(`Invalid hex color value: ${v}`)
156
- }
157
-
158
- if (v.length === 4 || v.length === 5) {
159
- const r = parseUi8Hex(v.slice(1, 2))
160
- const g = parseUi8Hex(v.slice(2, 3))
161
- const b = parseUi8Hex(v.slice(3, 4))
162
- const a = v.length > 4 ? parseUi8Hex(v.slice(4, 5)) : undefined
163
- return { r, g, b, a }
164
- }
165
-
166
- if (v.length === 7 || v.length === 9) {
167
- const r = parseUi8Hex(v.slice(1, 3))
168
- const g = parseUi8Hex(v.slice(3, 5))
169
- const b = parseUi8Hex(v.slice(5, 7))
170
- const a = v.length > 8 ? parseUi8Hex(v.slice(7, 9)) : undefined
171
- return { r, g, b, a }
172
- }
173
-
174
- throw new TypeError(`Invalid hex color value: ${v}`)
175
- }
176
-
177
- function parseRgbColor(v: string) {
178
- const matches = v.match(/^\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/)
179
- if (!matches) throw new TypeError(`Invalid rgb color value: ${v}`)
180
-
181
- const r = parseUi8Dec(matches[1])
182
- const g = parseUi8Dec(matches[2])
183
- const b = parseUi8Dec(matches[3])
184
- return { r, g, b }
185
- }
186
-
187
- function parseRgbaColor(v: string) {
188
- const matches = v.match(
189
- /^\s*rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/,
190
- )
191
- if (!matches) throw new TypeError(`Invalid rgba color value: ${v}`)
192
-
193
- const r = parseUi8Dec(matches[1])
194
- const g = parseUi8Dec(matches[2])
195
- const b = parseUi8Dec(matches[3])
196
- const a = parseUi8Dec(matches[4])
197
- return { r, g, b, a }
198
- }
199
-
200
- function computeLuma({ r, g, b }: RgbaColor) {
201
- return 0.299 * r + 0.587 * g + 0.114 * b
202
- }
203
-
204
- function parseUi8Hex(v: string) {
205
- return asUi8(parseInt(v, 16))
206
- }
207
-
208
- function parseUi8Dec(v: string) {
209
- return asUi8(parseInt(v, 10))
210
- }
211
-
212
- function asUi8(v: number) {
213
- if (v >= 0 && v <= 255 && v === (v | 0)) return v
214
- throw new TypeError(
215
- `Invalid color component "${v}" (expected an integer between 0 and 255)`,
216
- )
217
- }
@@ -1,8 +0,0 @@
1
- import { ErrorData } from '@atproto/oauth-provider-api'
2
- import { buildErrorPayload } from './build-error-payload.js'
3
-
4
- // @NOTE: The primary role of this function is to ensure that the ErrorPayload
5
- // and ErrorData types are in sync.
6
- export function buildErrorData(error: unknown): ErrorData {
7
- return buildErrorPayload(error)
8
- }
@@ -1,188 +0,0 @@
1
- import type { ServerResponse } from 'node:http'
2
- import { CustomizationData } from '@atproto/oauth-provider-api'
3
- import { assets } from '@atproto/oauth-provider-ui'
4
- import { buildAssetUrl } from '../assets/assets-middleware.js'
5
- import { CspConfig, mergeCsp } from '../lib/csp/index.js'
6
- import {
7
- AssetRef,
8
- Html,
9
- LinkAttrs,
10
- MetaAttrs,
11
- cssCode,
12
- html,
13
- isLinkRel,
14
- } from '../lib/html/index.js'
15
- import { CrossOriginEmbedderPolicy } from '../lib/http/security-headers.js'
16
- import { AVAILABLE_LOCALES, Locale, isAvailableLocale } from '../lib/locale.js'
17
- import { declareBackendData } from './backend-data.js'
18
- import {
19
- AuthorizationResultAuthorize,
20
- buildAuthorizeData,
21
- } from './build-authorize-data.js'
22
- import {
23
- Customization,
24
- LinkDefinition,
25
- buildCustomizationCss,
26
- buildCustomizationData,
27
- } from './build-customization-data.js'
28
- import { buildErrorData } from './build-error-data.js'
29
- import { buildErrorStatus } from './build-error-payload.js'
30
- import { sendWebPage } from './send-web-page.js'
31
-
32
- const BASE_CSP: CspConfig = {
33
- // API calls are made to the same origin
34
- 'connect-src': ["'self'"],
35
- // Allow loading of PDS logo & User avatars
36
- 'img-src': ['data:', 'https:'],
37
- // Prevent embedding in iframes
38
- 'frame-ancestors': ["'none'"],
39
- }
40
-
41
- /**
42
- * @see {@link https://docs.hcaptcha.com/#content-security-policy-settings}
43
- */
44
- const HCAPTCHA_CSP: CspConfig = {
45
- 'script-src': ['https://hcaptcha.com', 'https://*.hcaptcha.com'],
46
- 'frame-src': ['https://hcaptcha.com', 'https://*.hcaptcha.com'],
47
- 'style-src': ['https://hcaptcha.com', 'https://*.hcaptcha.com'],
48
- 'connect-src': ['https://hcaptcha.com', 'https://*.hcaptcha.com'],
49
- }
50
-
51
- export type SendPageOptions = {
52
- preferredLocales?: readonly string[]
53
- }
54
-
55
- export class OutputManager {
56
- readonly links?: readonly LinkDefinition[]
57
- readonly meta: readonly MetaAttrs[] = [
58
- { name: 'robots', content: 'noindex' },
59
- { name: 'description', content: 'ATProto OAuth authorization page' },
60
- ]
61
- readonly csp: CspConfig
62
- readonly coep: CrossOriginEmbedderPolicy
63
- readonly customizationData: CustomizationData
64
- readonly customizationCss: Html
65
-
66
- constructor(customization: Customization) {
67
- this.links = customization.branding?.links
68
-
69
- // "cache" these:
70
- this.customizationData = buildCustomizationData(customization)
71
- this.customizationCss = cssCode(buildCustomizationCss(customization))
72
-
73
- this.csp = mergeCsp(
74
- BASE_CSP,
75
- customization?.hcaptcha ? HCAPTCHA_CSP : undefined,
76
- )
77
- // Because we are loading avatar images from external sources, that might
78
- // not have CORP headers set, we need to use at least "credentialless".
79
- this.coep = customization?.hcaptcha
80
- ? // https://github.com/hCaptcha/react-hcaptcha/issues/259
81
- // @TODO Remove the use of `unsafeNone` once the issue above is resolved
82
- CrossOriginEmbedderPolicy.unsafeNone
83
- : CrossOriginEmbedderPolicy.credentialless
84
- }
85
-
86
- buildAssets(
87
- name: string,
88
- backendData: Record<string, unknown>,
89
- ): {
90
- scripts: (AssetRef | Html)[]
91
- styles: (AssetRef | Html)[]
92
- } {
93
- return {
94
- scripts: [
95
- declareBackendData(backendData),
96
- // After backend injected data
97
- ...Array.from(assets)
98
- .filter(
99
- ([, item]) =>
100
- item.type === 'chunk' && item.isEntry && item.name === name,
101
- )
102
- .map(([filename]) => ({ url: buildAssetUrl(filename) })),
103
- ],
104
- styles: [
105
- ...Array.from(assets)
106
- .filter(([, item]) => item.mime === 'text/css')
107
- .map(([filename]) => ({ url: buildAssetUrl(filename) })),
108
- // Last (to be able to override the default styles)
109
- this.customizationCss,
110
- ],
111
- }
112
- }
113
-
114
- async sendAuthorizePage(
115
- res: ServerResponse,
116
- data: AuthorizationResultAuthorize,
117
- options?: SendPageOptions,
118
- ): Promise<void> {
119
- const locale = negotiateLocale(
120
- data.parameters.ui_locales?.split(' ') ?? options?.preferredLocales,
121
- )
122
-
123
- const { scripts, styles } = this.buildAssets('authorization-page', {
124
- __availableLocales: AVAILABLE_LOCALES,
125
- __customizationData: this.customizationData,
126
- __authorizeData: buildAuthorizeData(data),
127
- })
128
-
129
- return sendWebPage(res, {
130
- scripts,
131
- styles,
132
- meta: this.meta,
133
- links: this.buildLinks(locale),
134
- htmlAttrs: { lang: locale },
135
- body: html`<div id="root"></div>`,
136
- csp: this.csp,
137
- coep: this.coep,
138
- })
139
- }
140
-
141
- async sendErrorPage(
142
- res: ServerResponse,
143
- err: unknown,
144
- options?: SendPageOptions,
145
- ): Promise<void> {
146
- const locale = negotiateLocale(options?.preferredLocales)
147
-
148
- const { scripts, styles } = this.buildAssets('error-page', {
149
- __availableLocales: AVAILABLE_LOCALES,
150
- __customizationData: this.customizationData,
151
- __errorData: buildErrorData(err),
152
- })
153
-
154
- return sendWebPage(res, {
155
- status: buildErrorStatus(err),
156
- scripts,
157
- styles,
158
- meta: this.meta,
159
- links: this.buildLinks(locale),
160
- htmlAttrs: { lang: locale },
161
- body: html`<div id="root"></div>`,
162
- csp: this.csp,
163
- coep: this.coep,
164
- })
165
- }
166
-
167
- buildLinks(locale: Locale) {
168
- return this.links
169
- ?.map(({ rel, href, title }: LinkDefinition): LinkAttrs | undefined =>
170
- isLinkRel(rel)
171
- ? typeof title === 'string'
172
- ? { href, rel, title }
173
- : { href, rel, title: title[locale] || title.en }
174
- : undefined,
175
- )
176
- .filter((v) => v != null)
177
- }
178
- }
179
-
180
- function negotiateLocale(desiredLocales?: readonly string[]): Locale {
181
- if (desiredLocales) {
182
- for (const locale of desiredLocales) {
183
- if (locale === '*') break // use default
184
- if (isAvailableLocale(locale)) return locale
185
- }
186
- }
187
- return 'en'
188
- }
@@ -1,137 +0,0 @@
1
- import type { ServerResponse } from 'node:http'
2
- import {
3
- OAuthAuthorizationRequestParameters,
4
- OAuthTokenType,
5
- } from '@atproto/oauth-types'
6
- import { InvalidRequestError } from '../errors/invalid-request-error.js'
7
- import { html, js } from '../lib/html/index.js'
8
- import { Code } from '../request/code.js'
9
- import { sendWebPage } from './send-web-page.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
- /**
15
- * @note `iss` and `state` will be added from the
16
- * {@link AuthorizationResultRedirect} object.
17
- */
18
- export type AuthorizationRedirectParameters =
19
- | {
20
- // iss: string
21
- // state?: string
22
- code: Code
23
- id_token?: string
24
- access_token?: string
25
- token_type?: OAuthTokenType
26
- expires_in?: string
27
- }
28
- | {
29
- // iss: string
30
- // state?: string
31
- error: string
32
- error_description?: string
33
- error_uri?: string
34
- }
35
-
36
- const SUCCESS_REDIRECT_KEYS = [
37
- 'code',
38
- 'id_token',
39
- 'access_token',
40
- 'expires_in',
41
- 'token_type',
42
- ] as const
43
-
44
- const ERROR_REDIRECT_KEYS = ['error', 'error_description', 'error_uri'] as const
45
-
46
- export type AuthorizationResultRedirect = {
47
- issuer: string
48
- parameters: OAuthAuthorizationRequestParameters
49
- redirect: AuthorizationRedirectParameters
50
- }
51
-
52
- export async function sendAuthorizeRedirect(
53
- res: ServerResponse,
54
- result: AuthorizationResultRedirect,
55
- ): Promise<void> {
56
- const { issuer, parameters, redirect } = result
57
-
58
- const uri = parameters.redirect_uri
59
- if (!uri) throw new InvalidRequestError('No redirect_uri')
60
-
61
- const mode = parameters.response_mode || 'query' // @TODO: default should depend on response_type
62
-
63
- const entries: [string, string][] = [
64
- ['iss', issuer], // rfc9207
65
- ]
66
-
67
- if (parameters.state != null) {
68
- entries.push(['state', parameters.state])
69
- }
70
-
71
- const keys = 'code' in redirect ? SUCCESS_REDIRECT_KEYS : ERROR_REDIRECT_KEYS
72
- for (const key of keys) {
73
- const value = redirect[key]
74
- if (value != null) entries.push([key, value])
75
- }
76
-
77
- res.setHeader('Cache-Control', 'no-store')
78
-
79
- switch (mode) {
80
- case 'query':
81
- return writeQuery(res, uri, entries)
82
- case 'fragment':
83
- return writeFragment(res, uri, entries)
84
- case 'form_post':
85
- return writeFormPost(res, uri, entries)
86
- }
87
-
88
- // @ts-expect-error fool proof
89
- throw new Error(`Unsupported mode: ${mode}`)
90
- }
91
-
92
- function writeQuery(
93
- res: ServerResponse,
94
- uri: string,
95
- entries: readonly [string, string][],
96
- ) {
97
- const url = new URL(uri)
98
- for (const [key, value] of entries) url.searchParams.set(key, value)
99
- res.writeHead(REDIRECT_STATUS_CODE, { Location: url.href }).end()
100
- }
101
-
102
- function writeFragment(
103
- res: ServerResponse,
104
- uri: string,
105
- entries: readonly [string, string][],
106
- ) {
107
- const url = new URL(uri)
108
- const searchParams = new URLSearchParams()
109
- for (const [key, value] of entries) searchParams.set(key, value)
110
- url.hash = searchParams.toString()
111
- res.writeHead(REDIRECT_STATUS_CODE, { Location: url.href }).end()
112
- }
113
-
114
- async function writeFormPost(
115
- res: ServerResponse,
116
- uri: string,
117
- entries: readonly [string, string][],
118
- ) {
119
- // Prevent the Chrome from caching this page
120
- // see: https://latesthackingnews.com/2023/12/12/google-updates-chrome-bfcache-for-faster-page-viewing/
121
- res.setHeader('Set-Cookie', `bfCacheBypass=foo; max-age=1; SameSite=Lax`)
122
- res.setHeader('Cache-Control', 'no-store')
123
- res.setHeader('Permissions-Policy', 'otp-credentials=*, document-domain=()')
124
-
125
- return sendWebPage(res, {
126
- htmlAttrs: { lang: 'en' },
127
- body: html`
128
- <form method="post" action="${uri}">
129
- ${entries.map(([key, value]) => [
130
- html`<input type="hidden" name="${key}" value="${value}" />`,
131
- ])}
132
- <input type="submit" value="Continue" />
133
- </form>
134
- `,
135
- scripts: [js`document.forms[0].submit();`],
136
- })
137
- }
@@ -1,30 +0,0 @@
1
- import { z } from 'zod'
2
- import { jwtPayloadSchema } from '@atproto/jwk'
3
- import { clientIdSchema } from '../client/client-id.js'
4
- import { Simplify } from '../lib/util/type.js'
5
- import { subSchema } from '../oidc/sub.js'
6
-
7
- export const tokenClaimsSchema = z.intersection(
8
- jwtPayloadSchema
9
- .pick({
10
- iat: true,
11
- exp: true,
12
- aud: true,
13
- })
14
- .required(),
15
- jwtPayloadSchema
16
- .omit({
17
- exp: true,
18
- iat: true,
19
- iss: true,
20
- aud: true,
21
- jti: true,
22
- })
23
- .partial()
24
- .extend({
25
- sub: subSchema,
26
- client_id: clientIdSchema,
27
- }),
28
- )
29
-
30
- export type TokenClaims = Simplify<z.infer<typeof tokenClaimsSchema>>