@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,11 @@
1
+ /**
2
+ * Every store file exports all the types needed to implement that store. This
3
+ * files re-exports all the types from the x-store files.
4
+ */
5
+
6
+ export * from './account/account-store.js'
7
+ export * from './client/client-store.js'
8
+ export * from './device/device-store.js'
9
+ export * from './replay/replay-store.js'
10
+ export * from './request/request-store.js'
11
+ export * from './token/token-store.js'
@@ -0,0 +1,219 @@
1
+ import { Key, Keyset, isSignedJwt } from '@atproto/jwk'
2
+ import {
3
+ AccessToken,
4
+ OAuthTokenType,
5
+ oauthIssuerIdentifierSchema,
6
+ } from '@atproto/oauth-types'
7
+ import { Redis, type RedisOptions } from 'ioredis'
8
+
9
+ import { AccessTokenType } from './access-token/access-token-type.js'
10
+ import { DpopManager, DpopManagerOptions } from './dpop/dpop-manager.js'
11
+ import { DpopNonce } from './dpop/dpop-nonce.js'
12
+ import { InvalidDpopProofError } from './errors/invalid-dpop-proof-error.js'
13
+ import { InvalidTokenError } from './errors/invalid-token-error.js'
14
+ import { UseDpopNonceError } from './errors/use-dpop-nonce-error.js'
15
+ import { WWWAuthenticateError } from './errors/www-authenticate-error.js'
16
+ import { parseAuthorizationHeader } from './lib/util/authorization-header.js'
17
+ import { Override } from './lib/util/type.js'
18
+ import { ReplayManager } from './replay/replay-manager.js'
19
+ import { ReplayStoreMemory } from './replay/replay-store-memory.js'
20
+ import { ReplayStoreRedis } from './replay/replay-store-redis.js'
21
+ import { ReplayStore } from './replay/replay-store.js'
22
+ import { Signer } from './signer/signer.js'
23
+ import {
24
+ VerifyTokenClaimsOptions,
25
+ VerifyTokenClaimsResult,
26
+ verifyTokenClaims,
27
+ } from './token/verify-token-claims.js'
28
+
29
+ export type OAuthVerifierOptions = Override<
30
+ DpopManagerOptions,
31
+ {
32
+ /**
33
+ * The "issuer" identifier of the OAuth provider, this is the base URL of the
34
+ * OAuth provider.
35
+ */
36
+ issuer: URL | string
37
+
38
+ /**
39
+ * The keyset used to sign tokens. Note that OIDC requires that at least one
40
+ * RS256 key is present in the keyset. ATPROTO requires ES256.
41
+ */
42
+ keyset: Keyset | Iterable<Key | undefined | null | false>
43
+
44
+ /**
45
+ * If set to {@link AccessTokenType.jwt}, the provider will use JWTs for
46
+ * access tokens. If set to {@link AccessTokenType.id}, the provider will
47
+ * use tokenId as access tokens. If set to {@link AccessTokenType.auto},
48
+ * JWTs will only be used if the audience is different from the issuer.
49
+ * Defaults to {@link AccessTokenType.jwt}.
50
+ *
51
+ * Here is a comparison of the two types:
52
+ *
53
+ * - pro id: less CPU intensive (no crypto operations)
54
+ * - pro id: less bandwidth (shorter tokens than jwt)
55
+ * - pro id: token data is in sync with database (e.g. revocation)
56
+ * - pro jwt: stateless: no I/O needed (no db lookups through token store)
57
+ * - pro jwt: stateless: allows Resource Server to be on a different
58
+ * host/server
59
+ */
60
+ accessTokenType?: AccessTokenType
61
+
62
+ /**
63
+ * A redis instance to use for replay protection. If not provided, replay
64
+ * protection will use memory storage.
65
+ */
66
+ redis?: Redis | RedisOptions | string
67
+
68
+ replayStore?: ReplayStore
69
+ }
70
+ >
71
+
72
+ export {
73
+ AccessTokenType,
74
+ DpopNonce,
75
+ Keyset,
76
+ type ReplayStore,
77
+ type VerifyTokenClaimsOptions,
78
+ }
79
+
80
+ export class OAuthVerifier {
81
+ public readonly issuer: string
82
+ public readonly keyset: Keyset
83
+
84
+ protected readonly accessTokenType: AccessTokenType
85
+ protected readonly dpopManager: DpopManager
86
+ protected readonly replayManager: ReplayManager
87
+ protected readonly signer: Signer
88
+
89
+ constructor({
90
+ redis,
91
+ issuer,
92
+ keyset,
93
+ replayStore = redis != null
94
+ ? new ReplayStoreRedis({ redis })
95
+ : new ReplayStoreMemory(),
96
+ accessTokenType = AccessTokenType.jwt,
97
+
98
+ ...dpopMgrOptions
99
+ }: OAuthVerifierOptions) {
100
+ const issuerParsed = oauthIssuerIdentifierSchema.parse(issuer)
101
+ const issuerUrl = new URL(issuerParsed)
102
+
103
+ // TODO (?) support issuer with path
104
+ if (issuerUrl.pathname !== '/') {
105
+ throw new TypeError(
106
+ `"issuer" must be an URL with no path, search or hash (${issuerUrl})`,
107
+ )
108
+ }
109
+
110
+ this.issuer = issuerParsed
111
+ this.keyset = keyset instanceof Keyset ? keyset : new Keyset(keyset)
112
+
113
+ this.accessTokenType = accessTokenType
114
+ this.dpopManager = new DpopManager(dpopMgrOptions)
115
+ this.replayManager = new ReplayManager(replayStore)
116
+ this.signer = new Signer(this.issuer, this.keyset)
117
+ }
118
+
119
+ public nextDpopNonce() {
120
+ return this.dpopManager.nextNonce()
121
+ }
122
+
123
+ public async checkDpopProof(
124
+ proof: unknown,
125
+ htm: string,
126
+ htu: string | URL,
127
+ accessToken?: string,
128
+ ): Promise<string | null> {
129
+ if (proof === undefined) return null
130
+
131
+ const { payload, jkt } = await this.dpopManager.checkProof(
132
+ proof,
133
+ htm,
134
+ htu,
135
+ accessToken,
136
+ )
137
+
138
+ const unique = await this.replayManager.uniqueDpop(payload.jti)
139
+ if (!unique) throw new InvalidDpopProofError('DPoP proof jti is not unique')
140
+
141
+ return jkt
142
+ }
143
+
144
+ protected assertTokenTypeAllowed(
145
+ tokenType: OAuthTokenType,
146
+ accessTokenType: AccessTokenType,
147
+ ) {
148
+ if (
149
+ this.accessTokenType !== AccessTokenType.auto &&
150
+ this.accessTokenType !== accessTokenType
151
+ ) {
152
+ throw new InvalidTokenError(tokenType, `Invalid token type`)
153
+ }
154
+ }
155
+
156
+ protected async authenticateToken(
157
+ tokenType: OAuthTokenType,
158
+ token: AccessToken,
159
+ dpopJkt: string | null,
160
+ verifyOptions?: VerifyTokenClaimsOptions,
161
+ ): Promise<VerifyTokenClaimsResult> {
162
+ if (!isSignedJwt(token)) {
163
+ throw new InvalidTokenError(tokenType, `Malformed token`)
164
+ }
165
+
166
+ this.assertTokenTypeAllowed(tokenType, AccessTokenType.jwt)
167
+
168
+ const { payload } = await this.signer
169
+ .verifyAccessToken(token)
170
+ .catch((err) => {
171
+ throw InvalidTokenError.from(err, tokenType)
172
+ })
173
+
174
+ return verifyTokenClaims(
175
+ token,
176
+ payload.jti,
177
+ tokenType,
178
+ dpopJkt,
179
+ payload,
180
+ verifyOptions,
181
+ )
182
+ }
183
+
184
+ public async authenticateRequest(
185
+ method: string,
186
+ url: URL,
187
+ headers: {
188
+ authorization?: string
189
+ dpop?: unknown
190
+ },
191
+ verifyOptions?: VerifyTokenClaimsOptions,
192
+ ): Promise<VerifyTokenClaimsResult> {
193
+ const [tokenType, token] = parseAuthorizationHeader(headers.authorization)
194
+ try {
195
+ const dpopJkt = await this.checkDpopProof(
196
+ headers.dpop,
197
+ method,
198
+ url,
199
+ token,
200
+ )
201
+
202
+ if (tokenType === 'DPoP' && !dpopJkt) {
203
+ throw new InvalidDpopProofError(`DPoP proof required`)
204
+ }
205
+
206
+ return await this.authenticateToken(
207
+ tokenType,
208
+ token,
209
+ dpopJkt,
210
+ verifyOptions,
211
+ )
212
+ } catch (err) {
213
+ if (err instanceof UseDpopNonceError) throw err.toWwwAuthenticateError()
214
+ if (err instanceof WWWAuthenticateError) throw err
215
+
216
+ throw InvalidTokenError.from(err, tokenType)
217
+ }
218
+ }
219
+ }
@@ -0,0 +1,35 @@
1
+ import { JwtPayload } from '@atproto/jwk'
2
+
3
+ /**
4
+ * @see {@link https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims | OpenID Connect Core 1.0, 5.4. Requesting Claims using Scope Values}
5
+ */
6
+ export const OIDC_SCOPE_CLAIMS = Object.freeze({
7
+ email: Object.freeze(['email', 'email_verified'] as const),
8
+ phone: Object.freeze(['phone_number', 'phone_number_verified'] as const),
9
+ address: Object.freeze(['address'] as const),
10
+ profile: Object.freeze([
11
+ 'name',
12
+ 'family_name',
13
+ 'given_name',
14
+ 'middle_name',
15
+ 'nickname',
16
+ 'preferred_username',
17
+ 'gender',
18
+ 'picture',
19
+ 'profile',
20
+ 'website',
21
+ 'birthdate',
22
+ 'zoneinfo',
23
+ 'locale',
24
+ 'updated_at',
25
+ ] as const),
26
+ })
27
+
28
+ export const OIDC_STANDARD_CLAIMS = Object.freeze(
29
+ Object.values(OIDC_SCOPE_CLAIMS).flat(),
30
+ )
31
+
32
+ export type OIDCStandardClaim = (typeof OIDC_STANDARD_CLAIMS)[number]
33
+ export type OIDCStandardPayload = Partial<{
34
+ [K in OIDCStandardClaim]?: JwtPayload[K]
35
+ }>
@@ -0,0 +1,4 @@
1
+ import { z } from 'zod'
2
+
3
+ export const subSchema = z.string().min(1)
4
+ export type Sub = z.infer<typeof subSchema>
@@ -0,0 +1,11 @@
1
+ import { OIDCStandardPayload } from './claims.js'
2
+
3
+ export type Userinfo = OIDCStandardPayload & {
4
+ // "The sub (subject) Claim MUST always be returned in the UserInfo Response."
5
+ sub: string
6
+
7
+ // client_id is not mandatory per spec, but we require it here for convenience
8
+ client_id: string
9
+
10
+ username?: string
11
+ }
@@ -0,0 +1,143 @@
1
+ import { JwtVerifyError } from '@atproto/jwk'
2
+ import { JOSEError } from 'jose/errors'
3
+ import { ZodError } from 'zod'
4
+
5
+ import { OAuthError } from '../errors/oauth-error.js'
6
+
7
+ const INVALID_REQUEST = 'invalid_request'
8
+ const SERVER_ERROR = 'server_error'
9
+
10
+ export function buildErrorStatus(error: unknown): number {
11
+ if (error instanceof OAuthError) {
12
+ return error.statusCode
13
+ }
14
+
15
+ if (error instanceof JwtVerifyError) {
16
+ return 400
17
+ }
18
+
19
+ if (error instanceof ZodError) {
20
+ return 400
21
+ }
22
+
23
+ if (error instanceof JOSEError) {
24
+ return 400
25
+ }
26
+
27
+ if (error instanceof TypeError) {
28
+ return 400
29
+ }
30
+
31
+ if (isBoom(error)) {
32
+ return error.output.statusCode
33
+ }
34
+
35
+ if (isXrpcError(error)) {
36
+ return error.type
37
+ }
38
+
39
+ const status = (error as any)?.status
40
+ if (
41
+ typeof status === 'number' &&
42
+ status === (status | 0) &&
43
+ status >= 400 &&
44
+ status < 600
45
+ ) {
46
+ return status
47
+ }
48
+
49
+ return 500
50
+ }
51
+
52
+ export function buildErrorPayload(error: unknown): {
53
+ error: string
54
+ error_description: string
55
+ } {
56
+ if (error instanceof OAuthError) {
57
+ return error.toJSON()
58
+ }
59
+
60
+ if (error instanceof ZodError) {
61
+ return {
62
+ error: INVALID_REQUEST,
63
+ error_description: error.issues[0]?.message || 'Invalid request',
64
+ }
65
+ }
66
+
67
+ if (error instanceof JOSEError) {
68
+ return {
69
+ error: INVALID_REQUEST,
70
+ error_description: error.message,
71
+ }
72
+ }
73
+
74
+ if (error instanceof TypeError) {
75
+ return {
76
+ error: INVALID_REQUEST,
77
+ error_description: error.message,
78
+ }
79
+ }
80
+
81
+ if (isBoom(error)) {
82
+ return {
83
+ error: error.output.statusCode <= 500 ? INVALID_REQUEST : SERVER_ERROR,
84
+ error_description:
85
+ error.output.statusCode <= 500
86
+ ? isPayloadLike(error.output?.payload)
87
+ ? error.output.payload.message
88
+ : error.message
89
+ : 'Server error',
90
+ }
91
+ }
92
+
93
+ if (isXrpcError(error)) {
94
+ return {
95
+ error: error.type <= 500 ? INVALID_REQUEST : SERVER_ERROR,
96
+ error_description: error.payload.message,
97
+ }
98
+ }
99
+
100
+ const status = buildErrorStatus(error)
101
+ return {
102
+ error: status < 500 ? INVALID_REQUEST : SERVER_ERROR,
103
+ error_description:
104
+ error instanceof Error && (error as any)?.expose === true
105
+ ? error.message
106
+ : 'Server error',
107
+ }
108
+ }
109
+
110
+ function isBoom(v: unknown): v is Error & {
111
+ isBoom: true
112
+ output: { statusCode: number; payload: unknown }
113
+ } {
114
+ return (
115
+ v instanceof Error &&
116
+ (v as any).isBoom === true &&
117
+ isHttpErrorCode(v['output']?.['statusCode'])
118
+ )
119
+ }
120
+
121
+ function isXrpcError(v: unknown): v is Error & {
122
+ type: number
123
+ payload: { error: string; message: string }
124
+ } {
125
+ return (
126
+ v instanceof Error &&
127
+ isHttpErrorCode(v['type']) &&
128
+ isPayloadLike(v['payload'])
129
+ )
130
+ }
131
+
132
+ function isHttpErrorCode(v: unknown): v is number {
133
+ return typeof v === 'number' && v >= 400 && v < 600 && v === (v | 0)
134
+ }
135
+
136
+ function isPayloadLike(v: unknown): v is { error: string; message: string } {
137
+ return (
138
+ v != null &&
139
+ typeof v === 'object' &&
140
+ typeof v['error'] === 'string' &&
141
+ typeof v['message'] === 'string'
142
+ )
143
+ }
@@ -0,0 +1,96 @@
1
+ // Matches colors defined in tailwind.config.js
2
+ const colorNames = ['primary', 'error'] as const
3
+ type ColorName = (typeof colorNames)[number]
4
+ const isColorName = (name: string): name is ColorName =>
5
+ (colorNames as readonly string[]).includes(name)
6
+
7
+ export type FieldDefinition = {
8
+ label?: string
9
+ placeholder?: string
10
+ pattern?: string
11
+ title?: string
12
+ }
13
+
14
+ export type ExtraFieldDefinition = FieldDefinition & {
15
+ type: 'text' | 'password' | 'date' | 'captcha'
16
+ required?: boolean
17
+ [_: string]: unknown
18
+ }
19
+
20
+ export type Customization = {
21
+ name?: string
22
+ logo?: string
23
+ colors?: { [_ in ColorName]?: string }
24
+ links?: Array<{
25
+ href: string
26
+ title: string
27
+ rel?: string
28
+ }>
29
+ }
30
+
31
+ export function buildCustomizationData({
32
+ name,
33
+ logo,
34
+ links,
35
+ }: Customization = {}) {
36
+ return {
37
+ name,
38
+ logo,
39
+ links,
40
+ }
41
+ }
42
+
43
+ export function buildCustomizationCss(customization?: Customization) {
44
+ if (!customization?.colors) return ''
45
+
46
+ const vars = Object.entries(customization.colors)
47
+ .filter((e) => isColorName(e[0]) && e[1] != null)
48
+ .map(([name, value]) => [name, parseColor(value)] as const)
49
+ .filter((e): e is [ColorName, ParsedColor] => e[1] != null)
50
+ // alpha not supported by tailwind (it does not work that way)
51
+ .map(([name, { r, g, b }]) => `--color-${name}: ${r} ${g} ${b};`)
52
+
53
+ return `:root { ${vars.join(' ')} }`
54
+ }
55
+
56
+ type ParsedColor = { r: number; g: number; b: number; a?: number }
57
+ function parseColor(color: string): undefined | ParsedColor {
58
+ if (color.startsWith('#')) {
59
+ if (color.length === 4 || color.length === 5) {
60
+ const [r, g, b, a] = color
61
+ .slice(1)
62
+ .split('')
63
+ .map((c) => parseInt(c + c, 16))
64
+ return { r, g, b, a }
65
+ }
66
+
67
+ if (color.length === 7 || color.length === 9) {
68
+ const r = parseInt(color.slice(1, 3), 16)
69
+ const g = parseInt(color.slice(3, 5), 16)
70
+ const b = parseInt(color.slice(5, 7), 16)
71
+ const a = color.length > 8 ? parseInt(color.slice(7, 9), 16) : undefined
72
+ return { r, g, b, a }
73
+ }
74
+
75
+ return undefined
76
+ }
77
+
78
+ const rgbMatch = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/)
79
+ if (rgbMatch) {
80
+ const [, r, g, b] = rgbMatch
81
+ return { r: parseInt(r, 10), g: parseInt(g, 10), b: parseInt(b, 10) }
82
+ }
83
+
84
+ const rgbaMatch = color.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d+)\)/)
85
+ if (rgbaMatch) {
86
+ const [, r, g, b, a] = rgbaMatch
87
+ return {
88
+ r: parseInt(r, 10),
89
+ g: parseInt(g, 10),
90
+ b: parseInt(b, 10),
91
+ a: parseInt(a, 10),
92
+ }
93
+ }
94
+
95
+ return undefined
96
+ }
@@ -0,0 +1,111 @@
1
+ import {
2
+ OAuthAuthenticationRequestParameters,
3
+ OAuthClientMetadata,
4
+ } from '@atproto/oauth-types'
5
+ import { ServerResponse } from 'node:http'
6
+
7
+ import { DeviceAccountInfo } from '../account/account-store.js'
8
+ import { Account } from '../account/account.js'
9
+ import { getAsset } from '../assets/index.js'
10
+ import { Client } from '../client/client.js'
11
+ import { cssCode, html } from '../lib/html/index.js'
12
+ import { RequestUri } from '../request/request-uri.js'
13
+ import {
14
+ Customization,
15
+ buildCustomizationCss,
16
+ buildCustomizationData,
17
+ } from './customization.js'
18
+ import { declareBackendData, sendWebPage } from './send-web-page.js'
19
+
20
+ export type AuthorizationResultAuthorize = {
21
+ issuer: string
22
+ client: Client
23
+ parameters: OAuthAuthenticationRequestParameters
24
+ authorize: {
25
+ uri: RequestUri
26
+ sessions: readonly {
27
+ account: Account
28
+ info: DeviceAccountInfo
29
+
30
+ selected: boolean
31
+ loginRequired: boolean
32
+ consentRequired: boolean
33
+ }[]
34
+ }
35
+ }
36
+
37
+ // TODO: find a way to share this type with the frontend code
38
+ // (app/backend-data.ts)
39
+
40
+ type Session = {
41
+ account: Account
42
+ info?: never // Prevent accidental leaks to frontend
43
+
44
+ selected: boolean
45
+ loginRequired: boolean
46
+ consentRequired: boolean
47
+ }
48
+
49
+ export type AuthorizeData = {
50
+ clientId: string
51
+ clientMetadata: OAuthClientMetadata
52
+ clientTrusted: boolean
53
+ requestUri: string
54
+ csrfCookie: string
55
+ loginHint?: string
56
+ newSessionsRequireConsent: boolean
57
+ sessions: Session[]
58
+ }
59
+
60
+ function buildAuthorizeData(data: AuthorizationResultAuthorize): AuthorizeData {
61
+ return {
62
+ clientId: data.client.id,
63
+ clientMetadata: data.client.metadata,
64
+ clientTrusted: data.client.info.isTrusted,
65
+ requestUri: data.authorize.uri,
66
+ csrfCookie: `csrf-${data.authorize.uri}`,
67
+ loginHint: data.parameters.login_hint,
68
+ newSessionsRequireConsent: data.parameters.prompt === 'consent',
69
+ sessions: data.authorize.sessions.map(
70
+ (session): Session => ({
71
+ account: session.account,
72
+ selected: session.selected,
73
+ loginRequired: session.loginRequired,
74
+ consentRequired: session.consentRequired,
75
+ }),
76
+ ),
77
+ }
78
+ }
79
+
80
+ export async function sendAuthorizePage(
81
+ res: ServerResponse,
82
+ data: AuthorizationResultAuthorize,
83
+ customization?: Customization,
84
+ ): Promise<void> {
85
+ res.setHeader('Cache-Control', 'no-store')
86
+ res.setHeader('Permissions-Policy', 'otp-credentials=*, document-domain=()')
87
+
88
+ const [jsAsset, cssAsset] = await Promise.all([
89
+ getAsset('main.js'),
90
+ getAsset('main.css'),
91
+ ])
92
+
93
+ return sendWebPage(res, {
94
+ scripts: [
95
+ declareBackendData(
96
+ '__customizationData',
97
+ buildCustomizationData(customization),
98
+ ),
99
+ declareBackendData('__authorizeData', buildAuthorizeData(data)),
100
+ jsAsset, // Last (to be able to read the global variables)
101
+ ],
102
+ styles: [
103
+ cssAsset, // First (to be overridden by customization)
104
+ cssCode(buildCustomizationCss(customization)),
105
+ ],
106
+ links: customization?.links,
107
+ htmlAttrs: { lang: 'en' },
108
+ title: 'Authorize',
109
+ body: html`<div id="root"></div>`,
110
+ })
111
+ }