@atproto/oauth-provider 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (631) hide show
  1. package/.postcssrc.yml +3 -0
  2. package/CHANGELOG.md +19 -0
  3. package/LICENSE.txt +7 -0
  4. package/dist/access-token/access-token-type.d.ts +6 -0
  5. package/dist/access-token/access-token-type.d.ts.map +1 -0
  6. package/dist/access-token/access-token-type.js +10 -0
  7. package/dist/access-token/access-token-type.js.map +1 -0
  8. package/dist/account/account-manager.d.ts +14 -0
  9. package/dist/account/account-manager.d.ts.map +1 -0
  10. package/dist/account/account-manager.js +39 -0
  11. package/dist/account/account-manager.js.map +1 -0
  12. package/dist/account/account-store.d.ts +39 -0
  13. package/dist/account/account-store.d.ts.map +1 -0
  14. package/dist/account/account-store.js +19 -0
  15. package/dist/account/account-store.js.map +1 -0
  16. package/dist/account/account.d.ts +8 -0
  17. package/dist/account/account.d.ts.map +1 -0
  18. package/dist/account/account.js +3 -0
  19. package/dist/account/account.js.map +1 -0
  20. package/dist/assets/app/bundle-manifest.json +22 -0
  21. package/dist/assets/app/main.css +3 -0
  22. package/dist/assets/app/main.js +20 -0
  23. package/dist/assets/app/main.js.map +1 -0
  24. package/dist/assets/asset.d.ts +9 -0
  25. package/dist/assets/asset.d.ts.map +1 -0
  26. package/dist/assets/asset.js +3 -0
  27. package/dist/assets/asset.js.map +1 -0
  28. package/dist/assets/assets-middleware.d.ts +2 -0
  29. package/dist/assets/assets-middleware.d.ts.map +1 -0
  30. package/dist/assets/assets-middleware.js +30 -0
  31. package/dist/assets/assets-middleware.js.map +1 -0
  32. package/dist/assets/index.d.ts +4 -0
  33. package/dist/assets/index.d.ts.map +1 -0
  34. package/dist/assets/index.js +65 -0
  35. package/dist/assets/index.js.map +1 -0
  36. package/dist/client/client-auth.d.ts +13 -0
  37. package/dist/client/client-auth.d.ts.map +1 -0
  38. package/dist/client/client-auth.js +35 -0
  39. package/dist/client/client-auth.js.map +1 -0
  40. package/dist/client/client-data.d.ts +8 -0
  41. package/dist/client/client-data.d.ts.map +1 -0
  42. package/dist/client/client-data.js +3 -0
  43. package/dist/client/client-data.js.map +1 -0
  44. package/dist/client/client-id.d.ts +4 -0
  45. package/dist/client/client-id.d.ts.map +1 -0
  46. package/dist/client/client-id.js +6 -0
  47. package/dist/client/client-id.js.map +1 -0
  48. package/dist/client/client-info.d.ts +13 -0
  49. package/dist/client/client-info.d.ts.map +1 -0
  50. package/dist/client/client-info.js +3 -0
  51. package/dist/client/client-info.js.map +1 -0
  52. package/dist/client/client-manager.d.ts +38 -0
  53. package/dist/client/client-manager.d.ts.map +1 -0
  54. package/dist/client/client-manager.js +534 -0
  55. package/dist/client/client-manager.js.map +1 -0
  56. package/dist/client/client-store.d.ts +13 -0
  57. package/dist/client/client-store.d.ts.map +1 -0
  58. package/dist/client/client-store.js +39 -0
  59. package/dist/client/client-store.js.map +1 -0
  60. package/dist/client/client-utils.d.ts +6 -0
  61. package/dist/client/client-utils.d.ts.map +1 -0
  62. package/dist/client/client-utils.js +40 -0
  63. package/dist/client/client-utils.js.map +1 -0
  64. package/dist/client/client.d.ts +41 -0
  65. package/dist/client/client.d.ts.map +1 -0
  66. package/dist/client/client.js +163 -0
  67. package/dist/client/client.js.map +1 -0
  68. package/dist/constants.d.ts +42 -0
  69. package/dist/constants.d.ts.map +1 -0
  70. package/dist/constants.js +53 -0
  71. package/dist/constants.js.map +1 -0
  72. package/dist/device/device-data.d.ts +20 -0
  73. package/dist/device/device-data.d.ts.map +1 -0
  74. package/dist/device/device-data.js +11 -0
  75. package/dist/device/device-data.js.map +1 -0
  76. package/dist/device/device-details.d.ts +17 -0
  77. package/dist/device/device-details.d.ts.map +1 -0
  78. package/dist/device/device-details.js +34 -0
  79. package/dist/device/device-details.js.map +1 -0
  80. package/dist/device/device-id.d.ts +6 -0
  81. package/dist/device/device-id.d.ts.map +1 -0
  82. package/dist/device/device-id.js +18 -0
  83. package/dist/device/device-id.js.map +1 -0
  84. package/dist/device/device-manager.d.ts +88 -0
  85. package/dist/device/device-manager.d.ts.map +1 -0
  86. package/dist/device/device-manager.js +206 -0
  87. package/dist/device/device-manager.js.map +1 -0
  88. package/dist/device/device-store.d.ts +15 -0
  89. package/dist/device/device-store.d.ts.map +1 -0
  90. package/dist/device/device-store.js +36 -0
  91. package/dist/device/device-store.js.map +1 -0
  92. package/dist/device/session-id.d.ts +6 -0
  93. package/dist/device/session-id.d.ts.map +1 -0
  94. package/dist/device/session-id.js +18 -0
  95. package/dist/device/session-id.js.map +1 -0
  96. package/dist/dpop/dpop-manager.d.ts +33 -0
  97. package/dist/dpop/dpop-manager.d.ts.map +1 -0
  98. package/dist/dpop/dpop-manager.js +115 -0
  99. package/dist/dpop/dpop-manager.js.map +1 -0
  100. package/dist/dpop/dpop-nonce.d.ts +13 -0
  101. package/dist/dpop/dpop-nonce.d.ts.map +1 -0
  102. package/dist/dpop/dpop-nonce.js +94 -0
  103. package/dist/dpop/dpop-nonce.js.map +1 -0
  104. package/dist/errors/access-denied-error.d.ts +8 -0
  105. package/dist/errors/access-denied-error.d.ts.map +1 -0
  106. package/dist/errors/access-denied-error.js +21 -0
  107. package/dist/errors/access-denied-error.js.map +1 -0
  108. package/dist/errors/account-selection-required-error.d.ts +6 -0
  109. package/dist/errors/account-selection-required-error.d.ts.map +1 -0
  110. package/dist/errors/account-selection-required-error.js +11 -0
  111. package/dist/errors/account-selection-required-error.js.map +1 -0
  112. package/dist/errors/consent-required-error.d.ts +6 -0
  113. package/dist/errors/consent-required-error.d.ts.map +1 -0
  114. package/dist/errors/consent-required-error.js +11 -0
  115. package/dist/errors/consent-required-error.js.map +1 -0
  116. package/dist/errors/invalid-authorization-details-error.d.ts +20 -0
  117. package/dist/errors/invalid-authorization-details-error.d.ts.map +1 -0
  118. package/dist/errors/invalid-authorization-details-error.js +26 -0
  119. package/dist/errors/invalid-authorization-details-error.js.map +1 -0
  120. package/dist/errors/invalid-client-error.d.ts +18 -0
  121. package/dist/errors/invalid-client-error.d.ts.map +1 -0
  122. package/dist/errors/invalid-client-error.js +24 -0
  123. package/dist/errors/invalid-client-error.js.map +1 -0
  124. package/dist/errors/invalid-client-id-error.d.ts +13 -0
  125. package/dist/errors/invalid-client-id-error.d.ts.map +1 -0
  126. package/dist/errors/invalid-client-id-error.js +25 -0
  127. package/dist/errors/invalid-client-id-error.js.map +1 -0
  128. package/dist/errors/invalid-client-metadata-error.d.ts +13 -0
  129. package/dist/errors/invalid-client-metadata-error.d.ts.map +1 -0
  130. package/dist/errors/invalid-client-metadata-error.js +23 -0
  131. package/dist/errors/invalid-client-metadata-error.js.map +1 -0
  132. package/dist/errors/invalid-dpop-key-binding-error.d.ts +12 -0
  133. package/dist/errors/invalid-dpop-key-binding-error.d.ts.map +1 -0
  134. package/dist/errors/invalid-dpop-key-binding-error.js +20 -0
  135. package/dist/errors/invalid-dpop-key-binding-error.js.map +1 -0
  136. package/dist/errors/invalid-dpop-proof-error.d.ts +5 -0
  137. package/dist/errors/invalid-dpop-proof-error.d.ts.map +1 -0
  138. package/dist/errors/invalid-dpop-proof-error.js +12 -0
  139. package/dist/errors/invalid-dpop-proof-error.js.map +1 -0
  140. package/dist/errors/invalid-grant-error.d.ts +14 -0
  141. package/dist/errors/invalid-grant-error.d.ts.map +1 -0
  142. package/dist/errors/invalid-grant-error.js +20 -0
  143. package/dist/errors/invalid-grant-error.js.map +1 -0
  144. package/dist/errors/invalid-parameters-error.d.ts +6 -0
  145. package/dist/errors/invalid-parameters-error.d.ts.map +1 -0
  146. package/dist/errors/invalid-parameters-error.js +11 -0
  147. package/dist/errors/invalid-parameters-error.js.map +1 -0
  148. package/dist/errors/invalid-redirect-uri-error.d.ts +11 -0
  149. package/dist/errors/invalid-redirect-uri-error.d.ts.map +1 -0
  150. package/dist/errors/invalid-redirect-uri-error.js +21 -0
  151. package/dist/errors/invalid-redirect-uri-error.js.map +1 -0
  152. package/dist/errors/invalid-request-error.d.ts +28 -0
  153. package/dist/errors/invalid-request-error.d.ts.map +1 -0
  154. package/dist/errors/invalid-request-error.js +34 -0
  155. package/dist/errors/invalid-request-error.js.map +1 -0
  156. package/dist/errors/invalid-token-error.d.ts +16 -0
  157. package/dist/errors/invalid-token-error.d.ts.map +1 -0
  158. package/dist/errors/invalid-token-error.js +45 -0
  159. package/dist/errors/invalid-token-error.js.map +1 -0
  160. package/dist/errors/login-required-error.d.ts +6 -0
  161. package/dist/errors/login-required-error.d.ts.map +1 -0
  162. package/dist/errors/login-required-error.js +11 -0
  163. package/dist/errors/login-required-error.js.map +1 -0
  164. package/dist/errors/oauth-error.d.ts +13 -0
  165. package/dist/errors/oauth-error.d.ts.map +1 -0
  166. package/dist/errors/oauth-error.js +29 -0
  167. package/dist/errors/oauth-error.js.map +1 -0
  168. package/dist/errors/unauthorized-client-error.d.ts +18 -0
  169. package/dist/errors/unauthorized-client-error.d.ts.map +1 -0
  170. package/dist/errors/unauthorized-client-error.js +24 -0
  171. package/dist/errors/unauthorized-client-error.js.map +1 -0
  172. package/dist/errors/use-dpop-nonce-error.d.ts +18 -0
  173. package/dist/errors/use-dpop-nonce-error.d.ts.map +1 -0
  174. package/dist/errors/use-dpop-nonce-error.js +27 -0
  175. package/dist/errors/use-dpop-nonce-error.js.map +1 -0
  176. package/dist/errors/www-authenticate-error.d.ts +9 -0
  177. package/dist/errors/www-authenticate-error.d.ts.map +1 -0
  178. package/dist/errors/www-authenticate-error.js +46 -0
  179. package/dist/errors/www-authenticate-error.js.map +1 -0
  180. package/dist/index.d.ts +14 -0
  181. package/dist/index.d.ts.map +1 -0
  182. package/dist/index.js +31 -0
  183. package/dist/index.js.map +1 -0
  184. package/dist/lib/html/build-document.d.ts +32 -0
  185. package/dist/lib/html/build-document.d.ts.map +1 -0
  186. package/dist/lib/html/build-document.js +61 -0
  187. package/dist/lib/html/build-document.js.map +1 -0
  188. package/dist/lib/html/escapers.d.ts +9 -0
  189. package/dist/lib/html/escapers.d.ts.map +1 -0
  190. package/dist/lib/html/escapers.js +66 -0
  191. package/dist/lib/html/escapers.js.map +1 -0
  192. package/dist/lib/html/html.d.ts +13 -0
  193. package/dist/lib/html/html.d.ts.map +1 -0
  194. package/dist/lib/html/html.js +53 -0
  195. package/dist/lib/html/html.js.map +1 -0
  196. package/dist/lib/html/index.d.ts +4 -0
  197. package/dist/lib/html/index.d.ts.map +1 -0
  198. package/dist/lib/html/index.js +21 -0
  199. package/dist/lib/html/index.js.map +1 -0
  200. package/dist/lib/html/tags.d.ts +34 -0
  201. package/dist/lib/html/tags.d.ts.map +1 -0
  202. package/dist/lib/html/tags.js +47 -0
  203. package/dist/lib/html/tags.js.map +1 -0
  204. package/dist/lib/html/util.d.ts +4 -0
  205. package/dist/lib/html/util.d.ts.map +1 -0
  206. package/dist/lib/html/util.js +20 -0
  207. package/dist/lib/html/util.js.map +1 -0
  208. package/dist/lib/http/accept.d.ts +29 -0
  209. package/dist/lib/http/accept.d.ts.map +1 -0
  210. package/dist/lib/http/accept.js +67 -0
  211. package/dist/lib/http/accept.js.map +1 -0
  212. package/dist/lib/http/context.d.ts +5 -0
  213. package/dist/lib/http/context.d.ts.map +1 -0
  214. package/dist/lib/http/context.js +10 -0
  215. package/dist/lib/http/context.js.map +1 -0
  216. package/dist/lib/http/index.d.ts +10 -0
  217. package/dist/lib/http/index.d.ts.map +1 -0
  218. package/dist/lib/http/index.js +26 -0
  219. package/dist/lib/http/index.js.map +1 -0
  220. package/dist/lib/http/method.d.ts +6 -0
  221. package/dist/lib/http/method.d.ts.map +1 -0
  222. package/dist/lib/http/method.js +19 -0
  223. package/dist/lib/http/method.js.map +1 -0
  224. package/dist/lib/http/middleware.d.ts +18 -0
  225. package/dist/lib/http/middleware.d.ts.map +1 -0
  226. package/dist/lib/http/middleware.js +118 -0
  227. package/dist/lib/http/middleware.js.map +1 -0
  228. package/dist/lib/http/parser.d.ts +33 -0
  229. package/dist/lib/http/parser.d.ts.map +1 -0
  230. package/dist/lib/http/parser.js +48 -0
  231. package/dist/lib/http/parser.js.map +1 -0
  232. package/dist/lib/http/path.d.ts +9 -0
  233. package/dist/lib/http/path.d.ts.map +1 -0
  234. package/dist/lib/http/path.js +54 -0
  235. package/dist/lib/http/path.js.map +1 -0
  236. package/dist/lib/http/request.d.ts +33 -0
  237. package/dist/lib/http/request.d.ts.map +1 -0
  238. package/dist/lib/http/request.js +86 -0
  239. package/dist/lib/http/request.js.map +1 -0
  240. package/dist/lib/http/response.d.ts +13 -0
  241. package/dist/lib/http/response.d.ts.map +1 -0
  242. package/dist/lib/http/response.js +98 -0
  243. package/dist/lib/http/response.js.map +1 -0
  244. package/dist/lib/http/route.d.ts +25 -0
  245. package/dist/lib/http/route.d.ts.map +1 -0
  246. package/dist/lib/http/route.js +39 -0
  247. package/dist/lib/http/route.js.map +1 -0
  248. package/dist/lib/http/router.d.ts +32 -0
  249. package/dist/lib/http/router.d.ts.map +1 -0
  250. package/dist/lib/http/router.js +74 -0
  251. package/dist/lib/http/router.js.map +1 -0
  252. package/dist/lib/http/stream.d.ts +13 -0
  253. package/dist/lib/http/stream.d.ts.map +1 -0
  254. package/dist/lib/http/stream.js +46 -0
  255. package/dist/lib/http/stream.js.map +1 -0
  256. package/dist/lib/http/types.d.ts +7 -0
  257. package/dist/lib/http/types.d.ts.map +1 -0
  258. package/dist/lib/http/types.js +3 -0
  259. package/dist/lib/http/types.js.map +1 -0
  260. package/dist/lib/http/url.d.ts +8 -0
  261. package/dist/lib/http/url.d.ts.map +1 -0
  262. package/dist/lib/http/url.js +22 -0
  263. package/dist/lib/http/url.js.map +1 -0
  264. package/dist/lib/redis.d.ts +5 -0
  265. package/dist/lib/redis.d.ts.map +1 -0
  266. package/dist/lib/redis.js +22 -0
  267. package/dist/lib/redis.js.map +1 -0
  268. package/dist/lib/util/authorization-header.d.ts +4 -0
  269. package/dist/lib/util/authorization-header.d.ts.map +1 -0
  270. package/dist/lib/util/authorization-header.js +23 -0
  271. package/dist/lib/util/authorization-header.js.map +1 -0
  272. package/dist/lib/util/cast.d.ts +2 -0
  273. package/dist/lib/util/cast.d.ts.map +1 -0
  274. package/dist/lib/util/cast.js +10 -0
  275. package/dist/lib/util/cast.js.map +1 -0
  276. package/dist/lib/util/crypto.d.ts +3 -0
  277. package/dist/lib/util/crypto.d.ts.map +1 -0
  278. package/dist/lib/util/crypto.js +29 -0
  279. package/dist/lib/util/crypto.js.map +1 -0
  280. package/dist/lib/util/date.d.ts +3 -0
  281. package/dist/lib/util/date.d.ts.map +1 -0
  282. package/dist/lib/util/date.js +12 -0
  283. package/dist/lib/util/date.js.map +1 -0
  284. package/dist/lib/util/hostname.d.ts +6 -0
  285. package/dist/lib/util/hostname.d.ts.map +1 -0
  286. package/dist/lib/util/hostname.js +24 -0
  287. package/dist/lib/util/hostname.js.map +1 -0
  288. package/dist/lib/util/redirect-uri.d.ts +7 -0
  289. package/dist/lib/util/redirect-uri.d.ts.map +1 -0
  290. package/dist/lib/util/redirect-uri.js +44 -0
  291. package/dist/lib/util/redirect-uri.js.map +1 -0
  292. package/dist/lib/util/time.d.ts +6 -0
  293. package/dist/lib/util/time.d.ts.map +1 -0
  294. package/dist/lib/util/time.js +28 -0
  295. package/dist/lib/util/time.js.map +1 -0
  296. package/dist/lib/util/type.d.ts +6 -0
  297. package/dist/lib/util/type.d.ts.map +1 -0
  298. package/dist/lib/util/type.js +3 -0
  299. package/dist/lib/util/type.js.map +1 -0
  300. package/dist/lib/util/well-known.d.ts +3 -0
  301. package/dist/lib/util/well-known.d.ts.map +1 -0
  302. package/dist/lib/util/well-known.js +11 -0
  303. package/dist/lib/util/well-known.js.map +1 -0
  304. package/dist/metadata/build-metadata.d.ts +14 -0
  305. package/dist/metadata/build-metadata.d.ts.map +1 -0
  306. package/dist/metadata/build-metadata.js +132 -0
  307. package/dist/metadata/build-metadata.js.map +1 -0
  308. package/dist/oauth-client.d.ts +4 -0
  309. package/dist/oauth-client.d.ts.map +1 -0
  310. package/dist/oauth-client.js +19 -0
  311. package/dist/oauth-client.js.map +1 -0
  312. package/dist/oauth-dpop.d.ts +3 -0
  313. package/dist/oauth-dpop.d.ts.map +1 -0
  314. package/dist/oauth-dpop.js +19 -0
  315. package/dist/oauth-dpop.js.map +1 -0
  316. package/dist/oauth-errors.d.ts +20 -0
  317. package/dist/oauth-errors.d.ts.map +1 -0
  318. package/dist/oauth-errors.js +43 -0
  319. package/dist/oauth-errors.js.map +1 -0
  320. package/dist/oauth-hooks.d.ts +42 -0
  321. package/dist/oauth-hooks.d.ts.map +1 -0
  322. package/dist/oauth-hooks.js +3 -0
  323. package/dist/oauth-hooks.js.map +1 -0
  324. package/dist/oauth-provider.d.ts +179 -0
  325. package/dist/oauth-provider.d.ts.map +1 -0
  326. package/dist/oauth-provider.js +748 -0
  327. package/dist/oauth-provider.js.map +1 -0
  328. package/dist/oauth-store.d.ts +11 -0
  329. package/dist/oauth-store.d.ts.map +1 -0
  330. package/dist/oauth-store.js +27 -0
  331. package/dist/oauth-store.js.map +1 -0
  332. package/dist/oauth-verifier.d.ts +66 -0
  333. package/dist/oauth-verifier.d.ts.map +1 -0
  334. package/dist/oauth-verifier.js +94 -0
  335. package/dist/oauth-verifier.js.map +1 -0
  336. package/dist/oidc/claims.d.ts +16 -0
  337. package/dist/oidc/claims.d.ts.map +1 -0
  338. package/dist/oidc/claims.js +29 -0
  339. package/dist/oidc/claims.js.map +1 -0
  340. package/dist/oidc/sub.d.ts +4 -0
  341. package/dist/oidc/sub.d.ts.map +1 -0
  342. package/dist/oidc/sub.js +6 -0
  343. package/dist/oidc/sub.js.map +1 -0
  344. package/dist/oidc/userinfo.d.ts +7 -0
  345. package/dist/oidc/userinfo.d.ts.map +1 -0
  346. package/dist/oidc/userinfo.js +3 -0
  347. package/dist/oidc/userinfo.js.map +1 -0
  348. package/dist/output/build-error-payload.d.ts +6 -0
  349. package/dist/output/build-error-payload.d.ts.map +1 -0
  350. package/dist/output/build-error-payload.js +108 -0
  351. package/dist/output/build-error-payload.js.map +1 -0
  352. package/dist/output/customization.d.ts +37 -0
  353. package/dist/output/customization.d.ts.map +1 -0
  354. package/dist/output/customization.js +62 -0
  355. package/dist/output/customization.js.map +1 -0
  356. package/dist/output/send-authorize-page.d.ts +43 -0
  357. package/dist/output/send-authorize-page.d.ts.map +1 -0
  358. package/dist/output/send-authorize-page.js +49 -0
  359. package/dist/output/send-authorize-page.js.map +1 -0
  360. package/dist/output/send-authorize-redirect.d.ts +25 -0
  361. package/dist/output/send-authorize-redirect.d.ts.map +1 -0
  362. package/dist/output/send-authorize-redirect.js +72 -0
  363. package/dist/output/send-authorize-redirect.js.map +1 -0
  364. package/dist/output/send-error-page.d.ts +5 -0
  365. package/dist/output/send-error-page.d.ts.map +1 -0
  366. package/dist/output/send-error-page.js +31 -0
  367. package/dist/output/send-error-page.js.map +1 -0
  368. package/dist/output/send-web-page.d.ts +8 -0
  369. package/dist/output/send-web-page.d.ts.map +1 -0
  370. package/dist/output/send-web-page.js +48 -0
  371. package/dist/output/send-web-page.js.map +1 -0
  372. package/dist/parameters/claims-requested.d.ts +3 -0
  373. package/dist/parameters/claims-requested.d.ts.map +1 -0
  374. package/dist/parameters/claims-requested.js +77 -0
  375. package/dist/parameters/claims-requested.js.map +1 -0
  376. package/dist/parameters/oidc-payload.d.ts +31 -0
  377. package/dist/parameters/oidc-payload.d.ts.map +1 -0
  378. package/dist/parameters/oidc-payload.js +25 -0
  379. package/dist/parameters/oidc-payload.js.map +1 -0
  380. package/dist/replay/replay-manager.d.ts +10 -0
  381. package/dist/replay/replay-manager.d.ts.map +1 -0
  382. package/dist/replay/replay-manager.js +23 -0
  383. package/dist/replay/replay-manager.js.map +1 -0
  384. package/dist/replay/replay-store-memory.d.ts +11 -0
  385. package/dist/replay/replay-store-memory.d.ts.map +1 -0
  386. package/dist/replay/replay-store-memory.js +30 -0
  387. package/dist/replay/replay-store-memory.js.map +1 -0
  388. package/dist/replay/replay-store-redis.d.ts +16 -0
  389. package/dist/replay/replay-store-redis.d.ts.map +1 -0
  390. package/dist/replay/replay-store-redis.js +20 -0
  391. package/dist/replay/replay-store-redis.js.map +1 -0
  392. package/dist/replay/replay-store.d.ts +16 -0
  393. package/dist/replay/replay-store.d.ts.map +1 -0
  394. package/dist/replay/replay-store.js +22 -0
  395. package/dist/replay/replay-store.js.map +1 -0
  396. package/dist/request/code.d.ts +7 -0
  397. package/dist/request/code.d.ts.map +1 -0
  398. package/dist/request/code.js +20 -0
  399. package/dist/request/code.js.map +1 -0
  400. package/dist/request/request-data.d.ts +21 -0
  401. package/dist/request/request-data.d.ts.map +1 -0
  402. package/dist/request/request-data.js +6 -0
  403. package/dist/request/request-data.js.map +1 -0
  404. package/dist/request/request-id.d.ts +6 -0
  405. package/dist/request/request-id.d.ts.map +1 -0
  406. package/dist/request/request-id.js +18 -0
  407. package/dist/request/request-id.js.map +1 -0
  408. package/dist/request/request-info.d.ts +12 -0
  409. package/dist/request/request-info.d.ts.map +1 -0
  410. package/dist/request/request-info.js +3 -0
  411. package/dist/request/request-info.js.map +1 -0
  412. package/dist/request/request-manager.d.ts +40 -0
  413. package/dist/request/request-manager.d.ts.map +1 -0
  414. package/dist/request/request-manager.js +310 -0
  415. package/dist/request/request-manager.js.map +1 -0
  416. package/dist/request/request-store-memory.d.ts +16 -0
  417. package/dist/request/request-store-memory.d.ts.map +1 -0
  418. package/dist/request/request-store-memory.js +31 -0
  419. package/dist/request/request-store-memory.js.map +1 -0
  420. package/dist/request/request-store-redis.d.ts +24 -0
  421. package/dist/request/request-store-redis.d.ts.map +1 -0
  422. package/dist/request/request-store-redis.js +58 -0
  423. package/dist/request/request-store-redis.js.map +1 -0
  424. package/dist/request/request-store.d.ts +27 -0
  425. package/dist/request/request-store.d.ts.map +1 -0
  426. package/dist/request/request-store.js +37 -0
  427. package/dist/request/request-store.js.map +1 -0
  428. package/dist/request/request-uri.d.ts +8 -0
  429. package/dist/request/request-uri.d.ts.map +1 -0
  430. package/dist/request/request-uri.js +24 -0
  431. package/dist/request/request-uri.js.map +1 -0
  432. package/dist/request/types.d.ts +328 -0
  433. package/dist/request/types.d.ts.map +1 -0
  434. package/dist/request/types.js +27 -0
  435. package/dist/request/types.js.map +1 -0
  436. package/dist/signer/signed-token-payload.d.ts +1694 -0
  437. package/dist/signer/signed-token-payload.d.ts.map +1 -0
  438. package/dist/signer/signed-token-payload.js +32 -0
  439. package/dist/signer/signed-token-payload.js.map +1 -0
  440. package/dist/signer/signer.d.ts +193 -0
  441. package/dist/signer/signer.d.ts.map +1 -0
  442. package/dist/signer/signer.js +101 -0
  443. package/dist/signer/signer.js.map +1 -0
  444. package/dist/token/refresh-token.d.ts +7 -0
  445. package/dist/token/refresh-token.d.ts.map +1 -0
  446. package/dist/token/refresh-token.js +20 -0
  447. package/dist/token/refresh-token.js.map +1 -0
  448. package/dist/token/token-claims.d.ts +1687 -0
  449. package/dist/token/token-claims.d.ts.map +1 -0
  450. package/dist/token/token-claims.js +30 -0
  451. package/dist/token/token-claims.js.map +1 -0
  452. package/dist/token/token-data.d.ts +20 -0
  453. package/dist/token/token-data.d.ts.map +1 -0
  454. package/dist/token/token-data.js +3 -0
  455. package/dist/token/token-data.js.map +1 -0
  456. package/dist/token/token-id.d.ts +7 -0
  457. package/dist/token/token-id.d.ts.map +1 -0
  458. package/dist/token/token-id.js +20 -0
  459. package/dist/token/token-id.js.map +1 -0
  460. package/dist/token/token-manager.d.ts +48 -0
  461. package/dist/token/token-manager.d.ts.map +1 -0
  462. package/dist/token/token-manager.js +421 -0
  463. package/dist/token/token-manager.js.map +1 -0
  464. package/dist/token/token-store.d.ts +35 -0
  465. package/dist/token/token-store.d.ts.map +1 -0
  466. package/dist/token/token-store.js +38 -0
  467. package/dist/token/token-store.js.map +1 -0
  468. package/dist/token/types.d.ts +250 -0
  469. package/dist/token/types.d.ts.map +1 -0
  470. package/dist/token/types.js +36 -0
  471. package/dist/token/types.js.map +1 -0
  472. package/dist/token/verify-token-claims.d.ts +17 -0
  473. package/dist/token/verify-token-claims.d.ts.map +1 -0
  474. package/dist/token/verify-token-claims.js +39 -0
  475. package/dist/token/verify-token-claims.js.map +1 -0
  476. package/package.json +83 -0
  477. package/rollup.config.js +55 -0
  478. package/src/access-token/access-token-type.ts +5 -0
  479. package/src/account/account-manager.ts +55 -0
  480. package/src/account/account-store.ts +74 -0
  481. package/src/account/account.ts +10 -0
  482. package/src/assets/app/app.tsx +28 -0
  483. package/src/assets/app/backend-data.ts +65 -0
  484. package/src/assets/app/components/accept-form.tsx +112 -0
  485. package/src/assets/app/components/account-identifier.tsx +18 -0
  486. package/src/assets/app/components/account-picker.tsx +108 -0
  487. package/src/assets/app/components/client-identifier.tsx +32 -0
  488. package/src/assets/app/components/client-name.tsx +30 -0
  489. package/src/assets/app/components/error-card.tsx +41 -0
  490. package/src/assets/app/components/help-card.tsx +42 -0
  491. package/src/assets/app/components/layout-title-page.tsx +43 -0
  492. package/src/assets/app/components/layout-welcome.tsx +58 -0
  493. package/src/assets/app/components/sign-in-form.tsx +290 -0
  494. package/src/assets/app/components/sign-up-account-form.tsx +210 -0
  495. package/src/assets/app/components/sign-up-disclaimer.tsx +44 -0
  496. package/src/assets/app/components/url-viewer.tsx +70 -0
  497. package/src/assets/app/cookies.ts +11 -0
  498. package/src/assets/app/hooks/use-api.ts +104 -0
  499. package/src/assets/app/hooks/use-bound-dispatch.ts +5 -0
  500. package/src/assets/app/hooks/use-csrf-token.ts +5 -0
  501. package/src/assets/app/lib/api.ts +64 -0
  502. package/src/assets/app/lib/clsx.ts +4 -0
  503. package/src/assets/app/lib/util.ts +10 -0
  504. package/src/assets/app/main.css +11 -0
  505. package/src/assets/app/main.tsx +28 -0
  506. package/src/assets/app/views/accept-view.tsx +51 -0
  507. package/src/assets/app/views/authorize-view.tsx +101 -0
  508. package/src/assets/app/views/error-view.tsx +27 -0
  509. package/src/assets/app/views/sign-in-view.tsx +121 -0
  510. package/src/assets/app/views/sign-up-view.tsx +93 -0
  511. package/src/assets/app/views/welcome-view.tsx +61 -0
  512. package/src/assets/asset.ts +8 -0
  513. package/src/assets/assets-middleware.ts +32 -0
  514. package/src/assets/index.ts +74 -0
  515. package/src/client/client-auth.ts +45 -0
  516. package/src/client/client-data.ts +9 -0
  517. package/src/client/client-id.ts +4 -0
  518. package/src/client/client-info.ts +13 -0
  519. package/src/client/client-manager.ts +818 -0
  520. package/src/client/client-store.ts +38 -0
  521. package/src/client/client-utils.ts +43 -0
  522. package/src/client/client.ts +231 -0
  523. package/src/constants.ts +69 -0
  524. package/src/device/device-data.ts +11 -0
  525. package/src/device/device-details.ts +43 -0
  526. package/src/device/device-id.ts +23 -0
  527. package/src/device/device-manager.ts +287 -0
  528. package/src/device/device-store.ts +35 -0
  529. package/src/device/session-id.ts +22 -0
  530. package/src/dpop/dpop-manager.ts +147 -0
  531. package/src/dpop/dpop-nonce.ts +104 -0
  532. package/src/errors/access-denied-error.ts +26 -0
  533. package/src/errors/account-selection-required-error.ts +12 -0
  534. package/src/errors/consent-required-error.ts +12 -0
  535. package/src/errors/invalid-authorization-details-error.ts +22 -0
  536. package/src/errors/invalid-client-error.ts +20 -0
  537. package/src/errors/invalid-client-id-error.ts +20 -0
  538. package/src/errors/invalid-client-metadata-error.ts +19 -0
  539. package/src/errors/invalid-dpop-key-binding-error.ts +21 -0
  540. package/src/errors/invalid-dpop-proof-error.ts +13 -0
  541. package/src/errors/invalid-grant-error.ts +16 -0
  542. package/src/errors/invalid-parameters-error.ts +12 -0
  543. package/src/errors/invalid-redirect-uri-error.ts +17 -0
  544. package/src/errors/invalid-request-error.ts +30 -0
  545. package/src/errors/invalid-token-error.ts +59 -0
  546. package/src/errors/login-required-error.ts +12 -0
  547. package/src/errors/oauth-error.ts +28 -0
  548. package/src/errors/unauthorized-client-error.ts +20 -0
  549. package/src/errors/use-dpop-nonce-error.ts +32 -0
  550. package/src/errors/www-authenticate-error.ts +65 -0
  551. package/src/index.ts +15 -0
  552. package/src/lib/html/README.md +9 -0
  553. package/src/lib/html/build-document.ts +98 -0
  554. package/src/lib/html/escapers.ts +66 -0
  555. package/src/lib/html/html.ts +61 -0
  556. package/src/lib/html/index.ts +5 -0
  557. package/src/lib/html/tags.ts +58 -0
  558. package/src/lib/html/util.ts +21 -0
  559. package/src/lib/http/README.md +11 -0
  560. package/src/lib/http/accept.ts +91 -0
  561. package/src/lib/http/context.ts +11 -0
  562. package/src/lib/http/index.ts +9 -0
  563. package/src/lib/http/method.ts +18 -0
  564. package/src/lib/http/middleware.ts +183 -0
  565. package/src/lib/http/parser.ts +64 -0
  566. package/src/lib/http/path.ts +82 -0
  567. package/src/lib/http/request.ts +141 -0
  568. package/src/lib/http/response.ts +133 -0
  569. package/src/lib/http/route.ts +56 -0
  570. package/src/lib/http/router.ts +118 -0
  571. package/src/lib/http/stream.ts +78 -0
  572. package/src/lib/http/types.ts +22 -0
  573. package/src/lib/http/url.ts +23 -0
  574. package/src/lib/redis.ts +23 -0
  575. package/src/lib/util/authorization-header.ts +26 -0
  576. package/src/lib/util/cast.ts +4 -0
  577. package/src/lib/util/crypto.ts +27 -0
  578. package/src/lib/util/date.ts +7 -0
  579. package/src/lib/util/hostname.ts +19 -0
  580. package/src/lib/util/redirect-uri.ts +46 -0
  581. package/src/lib/util/time.ts +33 -0
  582. package/src/lib/util/type.ts +4 -0
  583. package/src/lib/util/well-known.ts +8 -0
  584. package/src/metadata/build-metadata.ts +165 -0
  585. package/src/oauth-client.ts +3 -0
  586. package/src/oauth-dpop.ts +2 -0
  587. package/src/oauth-errors.ts +21 -0
  588. package/src/oauth-hooks.ts +66 -0
  589. package/src/oauth-provider.ts +1409 -0
  590. package/src/oauth-store.ts +11 -0
  591. package/src/oauth-verifier.ts +219 -0
  592. package/src/oidc/claims.ts +35 -0
  593. package/src/oidc/sub.ts +4 -0
  594. package/src/oidc/userinfo.ts +11 -0
  595. package/src/output/build-error-payload.ts +143 -0
  596. package/src/output/customization.ts +96 -0
  597. package/src/output/send-authorize-page.ts +111 -0
  598. package/src/output/send-authorize-redirect.ts +130 -0
  599. package/src/output/send-error-page.ts +41 -0
  600. package/src/output/send-web-page.ts +66 -0
  601. package/src/parameters/claims-requested.ts +106 -0
  602. package/src/parameters/oidc-payload.ts +28 -0
  603. package/src/replay/replay-manager.ts +38 -0
  604. package/src/replay/replay-store-memory.ts +36 -0
  605. package/src/replay/replay-store-redis.ts +31 -0
  606. package/src/replay/replay-store.ts +44 -0
  607. package/src/request/code.ts +24 -0
  608. package/src/request/request-data.ts +26 -0
  609. package/src/request/request-id.ts +23 -0
  610. package/src/request/request-info.ts +12 -0
  611. package/src/request/request-manager.ts +479 -0
  612. package/src/request/request-store-memory.ts +39 -0
  613. package/src/request/request-store-redis.ts +71 -0
  614. package/src/request/request-store.ts +54 -0
  615. package/src/request/request-uri.ts +29 -0
  616. package/src/request/types.ts +48 -0
  617. package/src/signer/signed-token-payload.ts +35 -0
  618. package/src/signer/signer.ts +165 -0
  619. package/src/token/refresh-token.ts +31 -0
  620. package/src/token/token-claims.ts +31 -0
  621. package/src/token/token-data.ts +33 -0
  622. package/src/token/token-id.ts +26 -0
  623. package/src/token/token-manager.ts +591 -0
  624. package/src/token/token-store.ts +78 -0
  625. package/src/token/types.ts +86 -0
  626. package/src/token/verify-token-claims.ts +65 -0
  627. package/tailwind.config.js +13 -0
  628. package/tsconfig.backend.json +9 -0
  629. package/tsconfig.frontend.json +11 -0
  630. package/tsconfig.json +8 -0
  631. package/tsconfig.tools.json +8 -0
@@ -0,0 +1,130 @@
1
+ import {
2
+ OAuthAuthenticationRequestParameters,
3
+ OAuthTokenType,
4
+ } from '@atproto/oauth-types'
5
+ import { ServerResponse } from 'node:http'
6
+
7
+ import { Client } from '../client/client.js'
8
+ import { html, js } from '../lib/html/index.js'
9
+ import { Code } from '../request/code.js'
10
+ import { sendWebPage } from './send-web-page.js'
11
+
12
+ // https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-7.5.4
13
+ const REDIRECT_STATUS_CODE = 303
14
+
15
+ export type AuthorizationResponseParameters = {
16
+ // Will be added from AuthorizationResultRedirect['issuer']
17
+ // iss: string // rfc9207
18
+
19
+ // Will be added from AuthorizationResultRedirect['parameters']
20
+ // state?: string
21
+
22
+ code?: Code
23
+ id_token?: string
24
+ access_token?: string
25
+ token_type?: OAuthTokenType
26
+ expires_in?: string
27
+
28
+ response?: string // FAPI JARM
29
+ session_state?: string // OIDC Session Management
30
+
31
+ error?: string
32
+ error_description?: string
33
+ error_uri?: string
34
+ }
35
+
36
+ export type AuthorizationResultRedirect = {
37
+ issuer: string
38
+ client: Client
39
+ parameters: OAuthAuthenticationRequestParameters
40
+ redirect: AuthorizationResponseParameters
41
+ }
42
+
43
+ export async function sendAuthorizeRedirect(
44
+ res: ServerResponse,
45
+ result: AuthorizationResultRedirect,
46
+ ): Promise<void> {
47
+ const { issuer, parameters, redirect, client } = result
48
+
49
+ const uri = parameters.redirect_uri || client.metadata.redirect_uris[0]
50
+ const mode = parameters.response_mode || 'query' // @TODO: default should depend on response_type
51
+
52
+ const entries: [string, string][] = Object.entries({
53
+ iss: issuer, // rfc9207
54
+ state: parameters.state,
55
+
56
+ response: redirect.response, // FAPI JARM
57
+ session_state: redirect.session_state, // OIDC Session Management
58
+
59
+ code: redirect.code,
60
+ id_token: redirect.id_token,
61
+ access_token: redirect.access_token,
62
+ expires_in: redirect.expires_in,
63
+ token_type: redirect.token_type,
64
+
65
+ error: redirect.error,
66
+ error_description: redirect.error_description,
67
+ error_uri: redirect.error_uri,
68
+ }).filter((entry): entry is [string, string] => entry[1] != null)
69
+
70
+ res.setHeader('Cache-Control', 'no-store')
71
+
72
+ switch (mode) {
73
+ case 'query':
74
+ return writeQuery(res, uri, entries)
75
+ case 'fragment':
76
+ return writeFragment(res, uri, entries)
77
+ case 'form_post':
78
+ return writeFormPost(res, uri, entries)
79
+ }
80
+
81
+ // @ts-expect-error fool proof
82
+ throw new Error(`Unsupported mode: ${mode}`)
83
+ }
84
+
85
+ function writeQuery(
86
+ res: ServerResponse,
87
+ uri: string,
88
+ entries: readonly [string, string][],
89
+ ) {
90
+ const url = new URL(uri)
91
+ for (const [key, value] of entries) url.searchParams.set(key, value)
92
+ res.writeHead(REDIRECT_STATUS_CODE, { Location: url.href }).end()
93
+ }
94
+
95
+ function writeFragment(
96
+ res: ServerResponse,
97
+ uri: string,
98
+ entries: readonly [string, string][],
99
+ ) {
100
+ const url = new URL(uri)
101
+ const searchParams = new URLSearchParams()
102
+ for (const [key, value] of entries) searchParams.set(key, value)
103
+ url.hash = searchParams.toString()
104
+ res.writeHead(REDIRECT_STATUS_CODE, { Location: url.href }).end()
105
+ }
106
+
107
+ async function writeFormPost(
108
+ res: ServerResponse,
109
+ uri: string,
110
+ entries: readonly [string, string][],
111
+ ) {
112
+ // Prevent the Chrome from caching this page
113
+ // see: https://latesthackingnews.com/2023/12/12/google-updates-chrome-bfcache-for-faster-page-viewing/
114
+ res.setHeader('Set-Cookie', `bfCacheBypass=foo; max-age=1; SameSite=Lax`)
115
+ res.setHeader('Cache-Control', 'no-store')
116
+ res.setHeader('Permissions-Policy', 'otp-credentials=*, document-domain=()')
117
+
118
+ return sendWebPage(res, {
119
+ htmlAttrs: { lang: 'en' },
120
+ body: html`
121
+ <form method="post" action="${uri}">
122
+ ${entries.map(([key, value]) => [
123
+ html`<input type="hidden" name="${key}" value="${value}" />`,
124
+ ])}
125
+ <input type="submit" value="Continue" />
126
+ </form>
127
+ `,
128
+ scripts: [js`document.forms[0].submit();`],
129
+ })
130
+ }
@@ -0,0 +1,41 @@
1
+ import { ServerResponse } from 'node:http'
2
+
3
+ import { getAsset } from '../assets/index.js'
4
+ import { cssCode, html } from '../lib/html/index.js'
5
+ import { buildErrorPayload, buildErrorStatus } from './build-error-payload.js'
6
+ import {
7
+ Customization,
8
+ buildCustomizationCss,
9
+ buildCustomizationData,
10
+ } from './customization.js'
11
+ import { declareBackendData, sendWebPage } from './send-web-page.js'
12
+
13
+ export async function sendErrorPage(
14
+ res: ServerResponse,
15
+ err: unknown,
16
+ customization?: Customization,
17
+ ): Promise<void> {
18
+ const [jsAsset, cssAsset] = await Promise.all([
19
+ getAsset('main.js'),
20
+ getAsset('main.css'),
21
+ ])
22
+
23
+ return sendWebPage(res, {
24
+ status: buildErrorStatus(err),
25
+ scripts: [
26
+ declareBackendData(
27
+ '__customizationData',
28
+ buildCustomizationData(customization),
29
+ ),
30
+ declareBackendData('__errorData', buildErrorPayload(err)),
31
+ jsAsset, // Last (to be able to read the global variables)
32
+ ],
33
+ styles: [
34
+ cssAsset, // First (to be overridden by customization)
35
+ cssCode(buildCustomizationCss(customization)),
36
+ ],
37
+ htmlAttrs: { lang: 'en' },
38
+ title: 'Error',
39
+ body: html`<div id="root"></div>`,
40
+ })
41
+ }
@@ -0,0 +1,66 @@
1
+ import { createHash } from 'node:crypto'
2
+ import { ServerResponse } from 'node:http'
3
+
4
+ import {
5
+ AssetRef,
6
+ buildDocument,
7
+ BuildDocumentOptions,
8
+ Html,
9
+ js,
10
+ } from '../lib/html/index.js'
11
+ import { writeHtml } from '../lib/http/response.js'
12
+
13
+ export function declareBackendData(name: string, data: unknown) {
14
+ // The script tag is removed after the data is assigned to the global variable
15
+ // to prevent other scripts from deducing the value of the variable. The "app"
16
+ // script will read the global variable and then unset it. See
17
+ // "readBackendData" in "src/assets/app/backend-data.ts".
18
+ return js`window[${name}]=${data};document.currentScript.remove();`
19
+ }
20
+
21
+ export function sendWebPage(
22
+ res: ServerResponse,
23
+ { status = 200, ...options }: BuildDocumentOptions & { status?: number },
24
+ ): void {
25
+ // @TODO: make these headers configurable (?)
26
+ res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless')
27
+ res.setHeader('Cross-Origin-Resource-Policy', 'same-origin')
28
+ res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
29
+ res.setHeader('Referrer-Policy', 'same-origin')
30
+ res.setHeader('X-Frame-Options', 'DENY')
31
+ res.setHeader('X-Content-Type-Options', 'nosniff')
32
+ res.setHeader('X-XSS-Protection', '0')
33
+ res.setHeader('Strict-Transport-Security', 'max-age=63072000')
34
+ res.setHeader(
35
+ 'Content-Security-Policy',
36
+ [
37
+ `default-src 'none'`,
38
+ `frame-ancestors 'none'`,
39
+ `form-action 'none'`,
40
+ `base-uri ${options.base?.origin || `'none'`}`,
41
+ `script-src 'self' ${
42
+ options.scripts?.map(assetToHash).map(hashToCspRule).join(' ') ?? ''
43
+ }`,
44
+ `style-src 'self' ${
45
+ options.styles?.map(assetToHash).map(hashToCspRule).join(' ') ?? ''
46
+ }`,
47
+ `img-src 'self' data: https:`,
48
+ `connect-src 'self'`,
49
+ `upgrade-insecure-requests`,
50
+ ].join('; '),
51
+ )
52
+
53
+ const html = buildDocument(options)
54
+
55
+ writeHtml(res, html.toString(), status)
56
+ }
57
+
58
+ function assetToHash(asset: Html | AssetRef): string {
59
+ return asset instanceof Html
60
+ ? createHash('sha256').update(asset.toString()).digest('base64')
61
+ : asset.sha256
62
+ }
63
+
64
+ function hashToCspRule(hash: string): string {
65
+ return `'sha256-${hash}'`
66
+ }
@@ -0,0 +1,106 @@
1
+ import {
2
+ OAuthAuthenticationRequestParameters,
3
+ OidcClaimsParameter,
4
+ OidcEntityType,
5
+ } from '@atproto/oauth-types'
6
+ import { InvalidRequestError } from '../errors/invalid-request-error.js'
7
+
8
+ export function claimRequested(
9
+ parameters: OAuthAuthenticationRequestParameters,
10
+ entityType: OidcEntityType,
11
+ claimName: OidcClaimsParameter,
12
+ value: unknown,
13
+ ): boolean {
14
+ if (claimAvailable(parameters, entityType, claimName, value)) {
15
+ return true
16
+ }
17
+
18
+ const entityClaims = parameters.claims?.[entityType]
19
+ if (entityClaims?.[claimName]?.essential === true) {
20
+ // https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.5.5.1
21
+ //
22
+ // > By requesting Claims as Essential Claims, the RP indicates to the
23
+ // > End-User that releasing these Claims will ensure a smooth
24
+ // > authorization for the specific task requested by the End-User. Note
25
+ // > that even if the Claims are not available because the End-User did
26
+ // > not authorize their release or they are not present, the
27
+ // > Authorization Server MUST NOT generate an error when Claims are not
28
+ // > returned, whether they are Essential or Voluntary, unless otherwise
29
+ // > specified in the description of the specific claim.
30
+ switch (claimName) {
31
+ case 'acr':
32
+ // https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.5.5.1.1
33
+ //
34
+ // > If this is an Essential Claim and the requirement cannot be met,
35
+ // > then the Authorization Server MUST treat that outcome as a failed
36
+ // > authentication attempt.
37
+ throw new InvalidRequestError(
38
+ `Unable to provide essential claim: ${claimName}`,
39
+ )
40
+ }
41
+ }
42
+
43
+ return false
44
+ }
45
+
46
+ function claimAvailable(
47
+ parameters: OAuthAuthenticationRequestParameters,
48
+ entityType: OidcEntityType,
49
+ claimName: OidcClaimsParameter,
50
+ value: unknown,
51
+ ): boolean {
52
+ if (value === undefined) return false
53
+
54
+ if (parameters.claims) {
55
+ const entityClaims = parameters.claims[entityType]
56
+ if (entityClaims === undefined) return false
57
+
58
+ const claimConfig = entityClaims[claimName]
59
+ if (claimConfig === undefined) return false
60
+ if (claimConfig === null) return true
61
+
62
+ if (
63
+ claimConfig.value !== undefined &&
64
+ !compareClaimValue(claimConfig.value, value)
65
+ ) {
66
+ return false
67
+ }
68
+
69
+ if (
70
+ claimConfig?.values !== undefined &&
71
+ !claimConfig.values.some((v) => compareClaimValue(v, value))
72
+ ) {
73
+ return false
74
+ }
75
+ }
76
+
77
+ return true
78
+ }
79
+
80
+ type DefinedValue = NonNullable<unknown> | null
81
+
82
+ function compareClaimValue(
83
+ expectedValue: DefinedValue,
84
+ value: DefinedValue,
85
+ ): boolean {
86
+ const expectedType = typeof expectedValue
87
+ const valueType = typeof value
88
+
89
+ if (expectedType !== valueType) return false
90
+
91
+ switch (typeof expectedValue) {
92
+ case 'undefined':
93
+ case 'string':
94
+ case 'number':
95
+ case 'boolean':
96
+ return expectedValue === value
97
+ case 'object':
98
+ if (expectedValue === null) return value === null
99
+ // @TODO (?): allow object comparison
100
+ // falls through
101
+ default:
102
+ throw new InvalidRequestError(
103
+ `Unable to compare claim value of type ${expectedType}`,
104
+ )
105
+ }
106
+ }
@@ -0,0 +1,28 @@
1
+ import { OAuthAuthenticationRequestParameters } from '@atproto/oauth-types'
2
+ import { Account } from '../account/account.js'
3
+ import { OIDCStandardPayload, OIDC_SCOPE_CLAIMS } from '../oidc/claims.js'
4
+ import { claimRequested } from './claims-requested.js'
5
+
6
+ export function oidcPayload(
7
+ params: OAuthAuthenticationRequestParameters,
8
+ account: Account,
9
+ ) {
10
+ const payload: OIDCStandardPayload = {}
11
+
12
+ const scopes = params.scope ? params.scope?.split(' ') : undefined
13
+ if (scopes) {
14
+ for (const [scope, claims] of Object.entries(OIDC_SCOPE_CLAIMS)) {
15
+ const allowed = scopes.includes(scope)
16
+ for (const claim of claims) {
17
+ const value = allowed ? account[claim] : undefined
18
+ // Should not throw as RequestManager should have already checked
19
+ // that all the essential claims are available.
20
+ if (claimRequested(params, 'id_token', claim, value)) {
21
+ payload[claim] = value as any // All good as long as the account props match the claims
22
+ }
23
+ }
24
+ }
25
+ }
26
+
27
+ return payload
28
+ }
@@ -0,0 +1,38 @@
1
+ import { ClientId } from '../client/client-id.js'
2
+ import {
3
+ CLIENT_ASSERTION_MAX_AGE,
4
+ DPOP_NONCE_MAX_AGE,
5
+ JAR_MAX_AGE,
6
+ } from '../constants.js'
7
+ import { ReplayStore } from './replay-store.js'
8
+
9
+ const SECURITY_RATIO = 1.1 // 10% extra time for security
10
+ const asTimeFrame = (timeFrame: number) => Math.ceil(timeFrame * SECURITY_RATIO)
11
+
12
+ export class ReplayManager {
13
+ constructor(protected readonly replayStore: ReplayStore) {}
14
+
15
+ async uniqueAuth(jti: string, clientId: ClientId): Promise<boolean> {
16
+ return this.replayStore.unique(
17
+ `Auth@${clientId}`,
18
+ jti,
19
+ asTimeFrame(CLIENT_ASSERTION_MAX_AGE),
20
+ )
21
+ }
22
+
23
+ async uniqueJar(jti: string, clientId: ClientId): Promise<boolean> {
24
+ return this.replayStore.unique(
25
+ `JAR@${clientId}`,
26
+ jti,
27
+ asTimeFrame(JAR_MAX_AGE),
28
+ )
29
+ }
30
+
31
+ async uniqueDpop(jti: string, clientId?: ClientId): Promise<boolean> {
32
+ return this.replayStore.unique(
33
+ clientId ? `DPoP@${clientId}` : `DPoP`,
34
+ jti,
35
+ asTimeFrame(DPOP_NONCE_MAX_AGE),
36
+ )
37
+ }
38
+ }
@@ -0,0 +1,36 @@
1
+ import type { ReplayStore } from './replay-store.js'
2
+
3
+ export class ReplayStoreMemory implements ReplayStore {
4
+ private lastCleanup = Date.now()
5
+ private nonces = new Map<string, number>()
6
+
7
+ /**
8
+ * Returns true if the nonce is unique within the given time frame.
9
+ */
10
+ async unique(
11
+ namespace: string,
12
+ nonce: string,
13
+ timeFrame: number,
14
+ ): Promise<boolean> {
15
+ this.cleanup()
16
+ const key = `${namespace}:${nonce}`
17
+
18
+ const now = Date.now()
19
+
20
+ const exp = this.nonces.get(key)
21
+ this.nonces.set(key, now + timeFrame)
22
+
23
+ return exp == null || exp < now
24
+ }
25
+
26
+ private cleanup() {
27
+ const now = Date.now()
28
+
29
+ if (this.lastCleanup < now - 60_000) {
30
+ for (const [key, expires] of this.nonces) {
31
+ if (expires < now) this.nonces.delete(key)
32
+ }
33
+ this.lastCleanup = now
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,31 @@
1
+ import { Redis } from 'ioredis'
2
+
3
+ import { CreateRedisOptions, createRedis } from '../lib/redis.js'
4
+ import type { ReplayStore } from './replay-store.js'
5
+
6
+ export type { CreateRedisOptions, Redis }
7
+
8
+ export type ReplayStoreRedisOptions = {
9
+ redis: CreateRedisOptions
10
+ }
11
+
12
+ export class ReplayStoreRedis implements ReplayStore {
13
+ private readonly redis: Redis
14
+
15
+ constructor(options: ReplayStoreRedisOptions) {
16
+ this.redis = createRedis(options.redis)
17
+ }
18
+
19
+ /**
20
+ * Returns true if the nonce is unique within the given time frame.
21
+ */
22
+ async unique(
23
+ namespace: string,
24
+ nonce: string,
25
+ timeFrame: number,
26
+ ): Promise<boolean> {
27
+ const key = `nonces:${namespace}:${nonce}`
28
+ const prev = await this.redis.set(key, '1', 'PX', timeFrame, 'GET')
29
+ return prev == null
30
+ }
31
+ }
@@ -0,0 +1,44 @@
1
+ import { Awaitable } from '../lib/util/type.js'
2
+
3
+ // Export all types needed to implement the ReplayStore interface
4
+ export type { Awaitable }
5
+
6
+ export interface ReplayStore {
7
+ /**
8
+ * Returns true if the nonce is unique within the given time frame. While not
9
+ * strictly necessary for security purposes, the namespace should be used to
10
+ * mitigate denial of service attacks from one client to the other.
11
+ *
12
+ * @param timeFrame expressed in milliseconds. Will never exceed 24 hours.
13
+ */
14
+ unique(
15
+ namespace: string,
16
+ nonce: string,
17
+ timeFrame: number,
18
+ ): Awaitable<boolean>
19
+ }
20
+
21
+ export function isReplayStore(
22
+ implementation: Record<string, unknown> & Partial<ReplayStore>,
23
+ ): implementation is Record<string, unknown> & ReplayStore {
24
+ return typeof implementation.unique === 'function'
25
+ }
26
+
27
+ export function ifReplayStore(
28
+ implementation?: Record<string, unknown> & Partial<ReplayStore>,
29
+ ): ReplayStore | undefined {
30
+ if (implementation && isReplayStore(implementation)) {
31
+ return implementation
32
+ }
33
+
34
+ return undefined
35
+ }
36
+
37
+ export function asReplayStore(
38
+ implementation?: Record<string, unknown> & Partial<ReplayStore>,
39
+ ): ReplayStore {
40
+ const store = ifReplayStore(implementation)
41
+ if (store) return store
42
+
43
+ throw new Error('Invalid ReplayStore implementation')
44
+ }
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod'
2
+
3
+ import { CODE_BYTES_LENGTH, CODE_PREFIX } from '../constants.js'
4
+ import { randomHexId } from '../lib/util/crypto.js'
5
+
6
+ export const CODE_LENGTH = CODE_PREFIX.length + CODE_BYTES_LENGTH * 2 // hex encoding
7
+
8
+ export const codeSchema = z
9
+ .string()
10
+ .length(CODE_LENGTH) // hex encoding
11
+ .refine(
12
+ (v): v is `${typeof CODE_PREFIX}${string}` => v.startsWith(CODE_PREFIX),
13
+ {
14
+ message: `Invalid code format`,
15
+ },
16
+ )
17
+
18
+ export const isCode = (data: unknown): data is Code =>
19
+ codeSchema.safeParse(data).success
20
+
21
+ export type Code = z.infer<typeof codeSchema>
22
+ export const generateCode = async (): Promise<Code> => {
23
+ return `${CODE_PREFIX}${await randomHexId(CODE_BYTES_LENGTH)}`
24
+ }
@@ -0,0 +1,26 @@
1
+ import { OAuthAuthenticationRequestParameters } from '@atproto/oauth-types'
2
+
3
+ import { ClientAuth } from '../client/client-auth.js'
4
+ import { ClientId } from '../client/client-id.js'
5
+ import { DeviceId } from '../device/device-id.js'
6
+ import { Sub } from '../oidc/sub.js'
7
+ import { Code } from './code.js'
8
+
9
+ export type RequestData = {
10
+ clientId: ClientId
11
+ clientAuth: ClientAuth
12
+ parameters: Readonly<OAuthAuthenticationRequestParameters>
13
+ expiresAt: Date
14
+ deviceId: DeviceId | null
15
+ sub: Sub | null
16
+ code: Code | null
17
+ }
18
+
19
+ export type RequestDataAuthorized = RequestData & {
20
+ sub: Sub
21
+ deviceId: DeviceId
22
+ }
23
+
24
+ export const isRequestDataAuthorized = (
25
+ data: RequestData,
26
+ ): data is RequestDataAuthorized => data.sub !== null && data.deviceId !== null
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod'
2
+
3
+ import { REQUEST_ID_BYTES_LENGTH, REQUEST_ID_PREFIX } from '../constants.js'
4
+ import { randomHexId } from '../lib/util/crypto.js'
5
+
6
+ export const REQUEST_ID_LENGTH =
7
+ REQUEST_ID_PREFIX.length + REQUEST_ID_BYTES_LENGTH * 2 // hex encoding
8
+
9
+ export const requestIdSchema = z
10
+ .string()
11
+ .length(REQUEST_ID_LENGTH)
12
+ .refine(
13
+ (v): v is `${typeof REQUEST_ID_PREFIX}${string}` =>
14
+ v.startsWith(REQUEST_ID_PREFIX),
15
+ {
16
+ message: `Invalid request ID format`,
17
+ },
18
+ )
19
+
20
+ export type RequestId = z.infer<typeof requestIdSchema>
21
+ export const generateRequestId = async (): Promise<RequestId> => {
22
+ return `${REQUEST_ID_PREFIX}${await randomHexId(REQUEST_ID_BYTES_LENGTH)}`
23
+ }
@@ -0,0 +1,12 @@
1
+ import { OAuthAuthenticationRequestParameters } from '@atproto/oauth-types'
2
+ import { ClientAuth } from '../client/client-auth.js'
3
+ import { RequestId } from './request-id.js'
4
+ import { RequestUri } from './request-uri.js'
5
+
6
+ export type RequestInfo = {
7
+ id: RequestId
8
+ uri: RequestUri
9
+ parameters: Readonly<OAuthAuthenticationRequestParameters>
10
+ expiresAt: Date
11
+ clientAuth: ClientAuth
12
+ }