@udibo/oauth2 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 (375) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +174 -0
  3. package/SECURITY.md +77 -0
  4. package/esm/_dnt.polyfills.d.ts +17 -0
  5. package/esm/_dnt.polyfills.js +15 -0
  6. package/esm/adapters/hono/_common.d.ts +66 -0
  7. package/esm/adapters/hono/_common.js +108 -0
  8. package/esm/adapters/hono/authorization-server.d.ts +211 -0
  9. package/esm/adapters/hono/authorization-server.js +214 -0
  10. package/esm/adapters/hono/bff/auth-request-store.d.ts +164 -0
  11. package/esm/adapters/hono/bff/auth-request-store.js +154 -0
  12. package/esm/adapters/hono/bff/bff.d.ts +852 -0
  13. package/esm/adapters/hono/bff/bff.js +1194 -0
  14. package/esm/adapters/hono/bff/cookie-prefix.d.ts +72 -0
  15. package/esm/adapters/hono/bff/cookie-prefix.js +85 -0
  16. package/esm/adapters/hono/bff/mod.d.ts +19 -0
  17. package/esm/adapters/hono/bff/mod.js +19 -0
  18. package/esm/adapters/hono/bff/proxy.d.ts +108 -0
  19. package/esm/adapters/hono/bff/proxy.js +314 -0
  20. package/esm/adapters/hono/bff/session-store.d.ts +250 -0
  21. package/esm/adapters/hono/bff/session-store.js +216 -0
  22. package/esm/adapters/hono/bff/testing.d.ts +165 -0
  23. package/esm/adapters/hono/bff/testing.js +254 -0
  24. package/esm/adapters/hono/identity.d.ts +117 -0
  25. package/esm/adapters/hono/identity.js +215 -0
  26. package/esm/adapters/hono/log.d.ts +49 -0
  27. package/esm/adapters/hono/log.js +66 -0
  28. package/esm/adapters/hono/resource-server.d.ts +101 -0
  29. package/esm/adapters/hono/resource-server.js +108 -0
  30. package/esm/client/_http.d.ts +91 -0
  31. package/esm/client/_http.js +303 -0
  32. package/esm/client/base.d.ts +184 -0
  33. package/esm/client/base.js +93 -0
  34. package/esm/client/bff-client.d.ts +235 -0
  35. package/esm/client/bff-client.js +280 -0
  36. package/esm/client/browser-storage.d.ts +152 -0
  37. package/esm/client/browser-storage.js +246 -0
  38. package/esm/client/check.d.ts +114 -0
  39. package/esm/client/check.js +97 -0
  40. package/esm/client/direct-client.d.ts +707 -0
  41. package/esm/client/direct-client.js +1237 -0
  42. package/esm/client/discovery-cache.d.ts +138 -0
  43. package/esm/client/discovery-cache.js +124 -0
  44. package/esm/client/events.d.ts +54 -0
  45. package/esm/client/events.js +37 -0
  46. package/esm/client/mod.d.ts +35 -0
  47. package/esm/client/mod.js +33 -0
  48. package/esm/client/storage.d.ts +127 -0
  49. package/esm/client/storage.js +81 -0
  50. package/esm/deps/jsr.io/@std/assert/1.0.19/almost_equals.d.ts +29 -0
  51. package/esm/deps/jsr.io/@std/assert/1.0.19/almost_equals.js +47 -0
  52. package/esm/deps/jsr.io/@std/assert/1.0.19/array_includes.d.ts +28 -0
  53. package/esm/deps/jsr.io/@std/assert/1.0.19/array_includes.js +65 -0
  54. package/esm/deps/jsr.io/@std/assert/1.0.19/assert.d.ts +16 -0
  55. package/esm/deps/jsr.io/@std/assert/1.0.19/assert.js +23 -0
  56. package/esm/deps/jsr.io/@std/assert/1.0.19/assertion_error.d.ts +25 -0
  57. package/esm/deps/jsr.io/@std/assert/1.0.19/assertion_error.js +30 -0
  58. package/esm/deps/jsr.io/@std/assert/1.0.19/equal.d.ts +24 -0
  59. package/esm/deps/jsr.io/@std/assert/1.0.19/equal.js +193 -0
  60. package/esm/deps/jsr.io/@std/assert/1.0.19/equals.d.ts +36 -0
  61. package/esm/deps/jsr.io/@std/assert/1.0.19/equals.js +61 -0
  62. package/esm/deps/jsr.io/@std/assert/1.0.19/exists.d.ts +17 -0
  63. package/esm/deps/jsr.io/@std/assert/1.0.19/exists.js +27 -0
  64. package/esm/deps/jsr.io/@std/assert/1.0.19/fail.d.ts +14 -0
  65. package/esm/deps/jsr.io/@std/assert/1.0.19/fail.js +20 -0
  66. package/esm/deps/jsr.io/@std/assert/1.0.19/false.d.ts +18 -0
  67. package/esm/deps/jsr.io/@std/assert/1.0.19/false.js +23 -0
  68. package/esm/deps/jsr.io/@std/assert/1.0.19/greater.d.ts +19 -0
  69. package/esm/deps/jsr.io/@std/assert/1.0.19/greater.js +29 -0
  70. package/esm/deps/jsr.io/@std/assert/1.0.19/greater_or_equal.d.ts +19 -0
  71. package/esm/deps/jsr.io/@std/assert/1.0.19/greater_or_equal.js +29 -0
  72. package/esm/deps/jsr.io/@std/assert/1.0.19/instance_of.d.ts +22 -0
  73. package/esm/deps/jsr.io/@std/assert/1.0.19/instance_of.js +52 -0
  74. package/esm/deps/jsr.io/@std/assert/1.0.19/is_error.d.ts +24 -0
  75. package/esm/deps/jsr.io/@std/assert/1.0.19/is_error.js +53 -0
  76. package/esm/deps/jsr.io/@std/assert/1.0.19/less.d.ts +18 -0
  77. package/esm/deps/jsr.io/@std/assert/1.0.19/less.js +28 -0
  78. package/esm/deps/jsr.io/@std/assert/1.0.19/less_or_equal.d.ts +19 -0
  79. package/esm/deps/jsr.io/@std/assert/1.0.19/less_or_equal.js +29 -0
  80. package/esm/deps/jsr.io/@std/assert/1.0.19/match.d.ts +17 -0
  81. package/esm/deps/jsr.io/@std/assert/1.0.19/match.js +26 -0
  82. package/esm/deps/jsr.io/@std/assert/1.0.19/mod.d.ts +43 -0
  83. package/esm/deps/jsr.io/@std/assert/1.0.19/mod.js +45 -0
  84. package/esm/deps/jsr.io/@std/assert/1.0.19/not_equals.d.ts +26 -0
  85. package/esm/deps/jsr.io/@std/assert/1.0.19/not_equals.js +39 -0
  86. package/esm/deps/jsr.io/@std/assert/1.0.19/not_instance_of.d.ts +19 -0
  87. package/esm/deps/jsr.io/@std/assert/1.0.19/not_instance_of.js +29 -0
  88. package/esm/deps/jsr.io/@std/assert/1.0.19/not_match.d.ts +17 -0
  89. package/esm/deps/jsr.io/@std/assert/1.0.19/not_match.js +26 -0
  90. package/esm/deps/jsr.io/@std/assert/1.0.19/not_strict_equals.d.ts +22 -0
  91. package/esm/deps/jsr.io/@std/assert/1.0.19/not_strict_equals.js +32 -0
  92. package/esm/deps/jsr.io/@std/assert/1.0.19/object_match.d.ts +28 -0
  93. package/esm/deps/jsr.io/@std/assert/1.0.19/object_match.js +177 -0
  94. package/esm/deps/jsr.io/@std/assert/1.0.19/rejects.d.ts +41 -0
  95. package/esm/deps/jsr.io/@std/assert/1.0.19/rejects.js +53 -0
  96. package/esm/deps/jsr.io/@std/assert/1.0.19/strict_equals.d.ts +23 -0
  97. package/esm/deps/jsr.io/@std/assert/1.0.19/strict_equals.js +58 -0
  98. package/esm/deps/jsr.io/@std/assert/1.0.19/string_includes.d.ts +17 -0
  99. package/esm/deps/jsr.io/@std/assert/1.0.19/string_includes.js +26 -0
  100. package/esm/deps/jsr.io/@std/assert/1.0.19/throws.d.ts +44 -0
  101. package/esm/deps/jsr.io/@std/assert/1.0.19/throws.js +44 -0
  102. package/esm/deps/jsr.io/@std/assert/1.0.19/unimplemented.d.ts +14 -0
  103. package/esm/deps/jsr.io/@std/assert/1.0.19/unimplemented.js +20 -0
  104. package/esm/deps/jsr.io/@std/assert/1.0.19/unreachable.d.ts +14 -0
  105. package/esm/deps/jsr.io/@std/assert/1.0.19/unreachable.js +20 -0
  106. package/esm/deps/jsr.io/@std/async/1.5.0/delay.d.ts +44 -0
  107. package/esm/deps/jsr.io/@std/async/1.5.0/delay.js +84 -0
  108. package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.d.ts +39 -0
  109. package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.js +61 -0
  110. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common16.d.ts +22 -0
  111. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common16.js +51 -0
  112. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common32.d.ts +34 -0
  113. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common32.js +192 -0
  114. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common64.d.ts +34 -0
  115. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common64.js +113 -0
  116. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common_detach.d.ts +3 -0
  117. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common_detach.js +13 -0
  118. package/esm/deps/jsr.io/@std/encoding/1.0.11/_types.d.ts +8 -0
  119. package/esm/deps/jsr.io/@std/encoding/1.0.11/_types.js +2 -0
  120. package/esm/deps/jsr.io/@std/encoding/1.0.11/_validate_binary_like.d.ts +1 -0
  121. package/esm/deps/jsr.io/@std/encoding/1.0.11/_validate_binary_like.js +26 -0
  122. package/esm/deps/jsr.io/@std/encoding/1.0.11/ascii85.d.ts +60 -0
  123. package/esm/deps/jsr.io/@std/encoding/1.0.11/ascii85.js +152 -0
  124. package/esm/deps/jsr.io/@std/encoding/1.0.11/base32.d.ts +39 -0
  125. package/esm/deps/jsr.io/@std/encoding/1.0.11/base32.js +87 -0
  126. package/esm/deps/jsr.io/@std/encoding/1.0.11/base58.d.ts +39 -0
  127. package/esm/deps/jsr.io/@std/encoding/1.0.11/base58.js +131 -0
  128. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64.d.ts +39 -0
  129. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64.js +82 -0
  130. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64url.d.ts +39 -0
  131. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64url.js +72 -0
  132. package/esm/deps/jsr.io/@std/encoding/1.0.11/hex.d.ts +38 -0
  133. package/esm/deps/jsr.io/@std/encoding/1.0.11/hex.js +87 -0
  134. package/esm/deps/jsr.io/@std/encoding/1.0.11/mod.d.ts +97 -0
  135. package/esm/deps/jsr.io/@std/encoding/1.0.11/mod.js +99 -0
  136. package/esm/deps/jsr.io/@std/encoding/1.0.11/varint.d.ts +119 -0
  137. package/esm/deps/jsr.io/@std/encoding/1.0.11/varint.js +209 -0
  138. package/esm/deps/jsr.io/@std/http/1.1.3/status.d.ts +343 -0
  139. package/esm/deps/jsr.io/@std/http/1.1.3/status.js +343 -0
  140. package/esm/deps/jsr.io/@std/internal/1.0.14/assertion_state.d.ts +159 -0
  141. package/esm/deps/jsr.io/@std/internal/1.0.14/assertion_state.js +223 -0
  142. package/esm/deps/jsr.io/@std/internal/1.0.14/build_message.d.ts +79 -0
  143. package/esm/deps/jsr.io/@std/internal/1.0.14/build_message.js +116 -0
  144. package/esm/deps/jsr.io/@std/internal/1.0.14/diff.d.ts +139 -0
  145. package/esm/deps/jsr.io/@std/internal/1.0.14/diff.js +277 -0
  146. package/esm/deps/jsr.io/@std/internal/1.0.14/diff_str.d.ts +98 -0
  147. package/esm/deps/jsr.io/@std/internal/1.0.14/diff_str.js +181 -0
  148. package/esm/deps/jsr.io/@std/internal/1.0.14/format.d.ts +29 -0
  149. package/esm/deps/jsr.io/@std/internal/1.0.14/format.js +68 -0
  150. package/esm/deps/jsr.io/@std/internal/1.0.14/styles.d.ts +158 -0
  151. package/esm/deps/jsr.io/@std/internal/1.0.14/styles.js +206 -0
  152. package/esm/deps/jsr.io/@std/internal/1.0.14/types.d.ts +24 -0
  153. package/esm/deps/jsr.io/@std/internal/1.0.14/types.js +3 -0
  154. package/esm/deps/jsr.io/@std/testing/1.0.20/_test_suite.d.ts +91 -0
  155. package/esm/deps/jsr.io/@std/testing/1.0.20/_test_suite.js +347 -0
  156. package/esm/deps/jsr.io/@std/testing/1.0.20/bdd.d.ts +382 -0
  157. package/esm/deps/jsr.io/@std/testing/1.0.20/bdd.js +1110 -0
  158. package/esm/deps/jsr.io/@udibo/http-error/0.11.1/mod.d.ts +363 -0
  159. package/esm/deps/jsr.io/@udibo/http-error/0.11.1/mod.js +616 -0
  160. package/esm/errors.d.ts +203 -0
  161. package/esm/errors.js +287 -0
  162. package/esm/identity/captcha.d.ts +147 -0
  163. package/esm/identity/captcha.js +64 -0
  164. package/esm/identity/delivery.d.ts +96 -0
  165. package/esm/identity/delivery.js +41 -0
  166. package/esm/identity/errors.d.ts +39 -0
  167. package/esm/identity/errors.js +46 -0
  168. package/esm/identity/events.d.ts +242 -0
  169. package/esm/identity/events.js +39 -0
  170. package/esm/identity/external/_shared.d.ts +86 -0
  171. package/esm/identity/external/_shared.js +107 -0
  172. package/esm/identity/external/_token-exchange.d.ts +61 -0
  173. package/esm/identity/external/_token-exchange.js +179 -0
  174. package/esm/identity/external/apple-client-secret.d.ts +82 -0
  175. package/esm/identity/external/apple-client-secret.js +133 -0
  176. package/esm/identity/external/apple.d.ts +64 -0
  177. package/esm/identity/external/apple.js +248 -0
  178. package/esm/identity/external/discord.d.ts +38 -0
  179. package/esm/identity/external/discord.js +62 -0
  180. package/esm/identity/external/errors.d.ts +48 -0
  181. package/esm/identity/external/errors.js +36 -0
  182. package/esm/identity/external/flow.d.ts +107 -0
  183. package/esm/identity/external/flow.js +158 -0
  184. package/esm/identity/external/github.d.ts +42 -0
  185. package/esm/identity/external/github.js +164 -0
  186. package/esm/identity/external/google.d.ts +52 -0
  187. package/esm/identity/external/google.js +38 -0
  188. package/esm/identity/external/mod.d.ts +63 -0
  189. package/esm/identity/external/mod.js +61 -0
  190. package/esm/identity/external/oauth2.d.ts +110 -0
  191. package/esm/identity/external/oauth2.js +158 -0
  192. package/esm/identity/external/oidc.d.ts +81 -0
  193. package/esm/identity/external/oidc.js +250 -0
  194. package/esm/identity/external/provider.d.ts +132 -0
  195. package/esm/identity/external/provider.js +12 -0
  196. package/esm/identity/hibp.d.ts +67 -0
  197. package/esm/identity/hibp.js +87 -0
  198. package/esm/identity/identifier.d.ts +44 -0
  199. package/esm/identity/identifier.js +47 -0
  200. package/esm/identity/lockout.d.ts +155 -0
  201. package/esm/identity/lockout.js +117 -0
  202. package/esm/identity/mfa/mod.d.ts +42 -0
  203. package/esm/identity/mfa/mod.js +42 -0
  204. package/esm/identity/mfa/recovery-codes.d.ts +96 -0
  205. package/esm/identity/mfa/recovery-codes.js +80 -0
  206. package/esm/identity/mfa/service.d.ts +338 -0
  207. package/esm/identity/mfa/service.js +351 -0
  208. package/esm/identity/mfa/totp.d.ts +186 -0
  209. package/esm/identity/mfa/totp.js +194 -0
  210. package/esm/identity/migration.d.ts +155 -0
  211. package/esm/identity/migration.js +243 -0
  212. package/esm/identity/mod.d.ts +65 -0
  213. package/esm/identity/mod.js +64 -0
  214. package/esm/identity/otp.d.ts +255 -0
  215. package/esm/identity/otp.js +245 -0
  216. package/esm/identity/password-policy.d.ts +45 -0
  217. package/esm/identity/password-policy.js +60 -0
  218. package/esm/identity/password.d.ts +171 -0
  219. package/esm/identity/password.js +160 -0
  220. package/esm/identity/rate-limit.d.ts +192 -0
  221. package/esm/identity/rate-limit.js +168 -0
  222. package/esm/identity/service.d.ts +579 -0
  223. package/esm/identity/service.js +835 -0
  224. package/esm/identity/session.d.ts +122 -0
  225. package/esm/identity/session.js +48 -0
  226. package/esm/identity/token-flow.d.ts +214 -0
  227. package/esm/identity/token-flow.js +173 -0
  228. package/esm/models/authentication.d.ts +24 -0
  229. package/esm/models/authentication.js +1 -0
  230. package/esm/models/authorization-code.d.ts +63 -0
  231. package/esm/models/authorization-code.js +1 -0
  232. package/esm/models/authorization.d.ts +165 -0
  233. package/esm/models/authorization.js +160 -0
  234. package/esm/models/client.d.ts +78 -0
  235. package/esm/models/client.js +1 -0
  236. package/esm/models/device-authorization.d.ts +30 -0
  237. package/esm/models/device-authorization.js +1 -0
  238. package/esm/models/responses.d.ts +93 -0
  239. package/esm/models/responses.js +1 -0
  240. package/esm/models/scope.d.ts +81 -0
  241. package/esm/models/scope.js +125 -0
  242. package/esm/models/token.d.ts +135 -0
  243. package/esm/models/token.js +1 -0
  244. package/esm/package.json +3 -0
  245. package/esm/react/callback.d.ts +52 -0
  246. package/esm/react/callback.js +71 -0
  247. package/esm/react/components/class-names.d.ts +91 -0
  248. package/esm/react/components/class-names.js +118 -0
  249. package/esm/react/components/internal.d.ts +62 -0
  250. package/esm/react/components/internal.js +102 -0
  251. package/esm/react/components/mfa-challenge-form.d.ts +66 -0
  252. package/esm/react/components/mfa-challenge-form.js +46 -0
  253. package/esm/react/components/mfa-enrollment-form.d.ts +83 -0
  254. package/esm/react/components/mfa-enrollment-form.js +41 -0
  255. package/esm/react/components/mod.d.ts +103 -0
  256. package/esm/react/components/mod.js +93 -0
  257. package/esm/react/components/request-password-reset-form.d.ts +61 -0
  258. package/esm/react/components/request-password-reset-form.js +41 -0
  259. package/esm/react/components/reset-password-form.d.ts +66 -0
  260. package/esm/react/components/reset-password-form.js +56 -0
  261. package/esm/react/components/sign-in-form.d.ts +74 -0
  262. package/esm/react/components/sign-in-form.js +43 -0
  263. package/esm/react/components/sign-up-form.d.ts +85 -0
  264. package/esm/react/components/sign-up-form.js +57 -0
  265. package/esm/react/components/types.d.ts +208 -0
  266. package/esm/react/components/types.js +14 -0
  267. package/esm/react/components/use-auth-form.d.ts +118 -0
  268. package/esm/react/components/use-auth-form.js +172 -0
  269. package/esm/react/components/user-menu.d.ts +79 -0
  270. package/esm/react/components/user-menu.js +73 -0
  271. package/esm/react/context.d.ts +51 -0
  272. package/esm/react/context.js +16 -0
  273. package/esm/react/mod.d.ts +26 -0
  274. package/esm/react/mod.js +26 -0
  275. package/esm/react/provider.d.ts +40 -0
  276. package/esm/react/provider.js +189 -0
  277. package/esm/react/require-auth.d.ts +31 -0
  278. package/esm/react/require-auth.js +37 -0
  279. package/esm/react/testing.d.ts +322 -0
  280. package/esm/react/testing.js +461 -0
  281. package/esm/react/use-authorization.d.ts +31 -0
  282. package/esm/react/use-authorization.js +36 -0
  283. package/esm/react/use-oauth2.d.ts +112 -0
  284. package/esm/react/use-oauth2.js +127 -0
  285. package/esm/server/authorization-server.d.ts +736 -0
  286. package/esm/server/authorization-server.js +1304 -0
  287. package/esm/server/client-authentication.d.ts +28 -0
  288. package/esm/server/client-authentication.js +51 -0
  289. package/esm/server/grants/authorization-code.d.ts +179 -0
  290. package/esm/server/grants/authorization-code.js +232 -0
  291. package/esm/server/grants/client-credentials.d.ts +52 -0
  292. package/esm/server/grants/client-credentials.js +53 -0
  293. package/esm/server/grants/device-authorization.d.ts +103 -0
  294. package/esm/server/grants/device-authorization.js +156 -0
  295. package/esm/server/grants/grant.d.ts +165 -0
  296. package/esm/server/grants/grant.js +173 -0
  297. package/esm/server/grants/password.d.ts +80 -0
  298. package/esm/server/grants/password.js +92 -0
  299. package/esm/server/grants/refresh-token.d.ts +80 -0
  300. package/esm/server/grants/refresh-token.js +136 -0
  301. package/esm/server/introspection-token-reader.d.ts +153 -0
  302. package/esm/server/introspection-token-reader.js +164 -0
  303. package/esm/server/jwks-token-reader.d.ts +263 -0
  304. package/esm/server/jwks-token-reader.js +508 -0
  305. package/esm/server/mod.d.ts +23 -0
  306. package/esm/server/mod.js +15 -0
  307. package/esm/server/public-suffix/mod.d.ts +62 -0
  308. package/esm/server/public-suffix/mod.js +103 -0
  309. package/esm/server/public-suffix/rules.d.ts +23 -0
  310. package/esm/server/public-suffix/rules.js +23 -0
  311. package/esm/server/redirect-uri.d.ts +187 -0
  312. package/esm/server/redirect-uri.js +331 -0
  313. package/esm/server/resource-server.d.ts +286 -0
  314. package/esm/server/resource-server.js +365 -0
  315. package/esm/server/services/authorization-code.d.ts +84 -0
  316. package/esm/server/services/authorization-code.js +35 -0
  317. package/esm/server/services/client.d.ts +35 -0
  318. package/esm/server/services/client.js +1 -0
  319. package/esm/server/services/device-authorization.d.ts +134 -0
  320. package/esm/server/services/device-authorization.js +7 -0
  321. package/esm/server/services/token.d.ts +242 -0
  322. package/esm/server/services/token.js +78 -0
  323. package/esm/server/services/user.d.ts +29 -0
  324. package/esm/server/services/user.js +7 -0
  325. package/esm/server/signing-keys.d.ts +201 -0
  326. package/esm/server/signing-keys.js +225 -0
  327. package/esm/server/utils/hash.d.ts +6 -0
  328. package/esm/server/utils/hash.js +11 -0
  329. package/esm/testing/contract/authorization-code.d.ts +37 -0
  330. package/esm/testing/contract/authorization-code.js +93 -0
  331. package/esm/testing/contract/client.d.ts +85 -0
  332. package/esm/testing/contract/client.js +126 -0
  333. package/esm/testing/contract/device-authorization.d.ts +37 -0
  334. package/esm/testing/contract/device-authorization.js +193 -0
  335. package/esm/testing/contract/lockout-store.d.ts +47 -0
  336. package/esm/testing/contract/lockout-store.js +122 -0
  337. package/esm/testing/contract/mfa-store.d.ts +50 -0
  338. package/esm/testing/contract/mfa-store.js +226 -0
  339. package/esm/testing/contract/mod.d.ts +39 -0
  340. package/esm/testing/contract/mod.js +39 -0
  341. package/esm/testing/contract/otp-store.d.ts +48 -0
  342. package/esm/testing/contract/otp-store.js +197 -0
  343. package/esm/testing/contract/rate-limit-store.d.ts +52 -0
  344. package/esm/testing/contract/rate-limit-store.js +105 -0
  345. package/esm/testing/contract/token-flow-store.d.ts +54 -0
  346. package/esm/testing/contract/token-flow-store.js +179 -0
  347. package/esm/testing/contract/token-reader.d.ts +77 -0
  348. package/esm/testing/contract/token-reader.js +78 -0
  349. package/esm/testing/contract/token.d.ts +61 -0
  350. package/esm/testing/contract/token.js +287 -0
  351. package/esm/testing/contract/user.d.ts +63 -0
  352. package/esm/testing/contract/user.js +75 -0
  353. package/esm/testing/mod.d.ts +34 -0
  354. package/esm/testing/mod.js +34 -0
  355. package/esm/testing/server.d.ts +197 -0
  356. package/esm/testing/server.js +193 -0
  357. package/esm/testing/services.d.ts +373 -0
  358. package/esm/testing/services.js +703 -0
  359. package/esm/utils/_buffer.d.ts +10 -0
  360. package/esm/utils/_buffer.js +12 -0
  361. package/esm/utils/_timing-safe.d.ts +13 -0
  362. package/esm/utils/_timing-safe.js +22 -0
  363. package/esm/utils/authentication-context.d.ts +3 -0
  364. package/esm/utils/authentication-context.js +14 -0
  365. package/esm/utils/basic-auth.d.ts +50 -0
  366. package/esm/utils/basic-auth.js +106 -0
  367. package/esm/utils/crypto.d.ts +97 -0
  368. package/esm/utils/crypto.js +162 -0
  369. package/esm/utils/pkce.d.ts +151 -0
  370. package/esm/utils/pkce.js +179 -0
  371. package/esm/utils/text.d.ts +24 -0
  372. package/esm/utils/text.js +28 -0
  373. package/esm/utils/url.d.ts +66 -0
  374. package/esm/utils/url.js +90 -0
  375. package/package.json +92 -0
@@ -0,0 +1,508 @@
1
+ /**
2
+ * Token reader that validates JWT access tokens locally against the
3
+ * issuer's published JWKS, with no per-request network hop.
4
+ *
5
+ * This is the validating half of RFC 9068 (`at+jwt`): the authorization
6
+ * server signs access tokens and publishes its public keys at a `jwks_uri`;
7
+ * the resource server fetches those keys once, caches them, and verifies
8
+ * every subsequent token in-process. Signature verification uses Web Crypto
9
+ * only — the package takes no JOSE dependency.
10
+ *
11
+ * @see https://datatracker.ietf.org/doc/html/rfc9068
12
+ * @see https://datatracker.ietf.org/doc/html/rfc7517
13
+ * @module
14
+ */
15
+ import { ServerError, TemporarilyUnavailableError } from "../errors.js";
16
+ import { BasicScope } from "../models/scope.js";
17
+ import { toArrayBuffer } from "../utils/_buffer.js";
18
+ import { base64urlDecode } from "../utils/crypto.js";
19
+ const ALGORITHMS = {
20
+ ES256: {
21
+ kty: "EC",
22
+ crv: "P-256",
23
+ importParams: { name: "ECDSA", namedCurve: "P-256" },
24
+ verifyParams: { name: "ECDSA", hash: "SHA-256" },
25
+ },
26
+ ES384: {
27
+ kty: "EC",
28
+ crv: "P-384",
29
+ importParams: { name: "ECDSA", namedCurve: "P-384" },
30
+ verifyParams: { name: "ECDSA", hash: "SHA-384" },
31
+ },
32
+ ES512: {
33
+ kty: "EC",
34
+ crv: "P-521",
35
+ importParams: { name: "ECDSA", namedCurve: "P-521" },
36
+ verifyParams: { name: "ECDSA", hash: "SHA-512" },
37
+ },
38
+ RS256: {
39
+ kty: "RSA",
40
+ importParams: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
41
+ verifyParams: { name: "RSASSA-PKCS1-v1_5" },
42
+ },
43
+ RS384: {
44
+ kty: "RSA",
45
+ importParams: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-384" },
46
+ verifyParams: { name: "RSASSA-PKCS1-v1_5" },
47
+ },
48
+ RS512: {
49
+ kty: "RSA",
50
+ importParams: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-512" },
51
+ verifyParams: { name: "RSASSA-PKCS1-v1_5" },
52
+ },
53
+ PS256: {
54
+ kty: "RSA",
55
+ importParams: { name: "RSA-PSS", hash: "SHA-256" },
56
+ verifyParams: { name: "RSA-PSS", saltLength: 32 },
57
+ },
58
+ PS384: {
59
+ kty: "RSA",
60
+ importParams: { name: "RSA-PSS", hash: "SHA-384" },
61
+ verifyParams: { name: "RSA-PSS", saltLength: 48 },
62
+ },
63
+ PS512: {
64
+ kty: "RSA",
65
+ importParams: { name: "RSA-PSS", hash: "SHA-512" },
66
+ verifyParams: { name: "RSA-PSS", saltLength: 64 },
67
+ },
68
+ };
69
+ const encoder = new TextEncoder();
70
+ const decoder = new TextDecoder();
71
+ function parseJws(jwt) {
72
+ const parts = jwt.split(".");
73
+ if (parts.length !== 3)
74
+ return undefined;
75
+ const [headerPart, payloadPart, signaturePart] = parts;
76
+ try {
77
+ const header = JSON.parse(decoder.decode(base64urlDecode(headerPart)));
78
+ const payload = JSON.parse(decoder.decode(base64urlDecode(payloadPart)));
79
+ if (!isRecord(header) || !isRecord(payload))
80
+ return undefined;
81
+ return {
82
+ header,
83
+ payload,
84
+ signingInput: toArrayBuffer(encoder.encode(`${headerPart}.${payloadPart}`)),
85
+ signature: toArrayBuffer(base64urlDecode(signaturePart)),
86
+ };
87
+ }
88
+ catch {
89
+ return undefined;
90
+ }
91
+ }
92
+ function isRecord(value) {
93
+ return typeof value === "object" && value !== null && !Array.isArray(value);
94
+ }
95
+ const MEDIA_TYPE_PREFIX = "application/";
96
+ function normalizeType(value) {
97
+ const lowered = value.toLowerCase();
98
+ return lowered.startsWith(MEDIA_TYPE_PREFIX)
99
+ ? lowered.slice(MEDIA_TYPE_PREFIX.length)
100
+ : lowered;
101
+ }
102
+ function verifyJwkOf(jwk) {
103
+ return jwk.kty === "EC"
104
+ ? { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y, ext: true }
105
+ : { kty: jwk.kty, n: jwk.n, e: jwk.e, ext: true };
106
+ }
107
+ function usableForVerification(jwk) {
108
+ if (jwk.kty !== "EC" && jwk.kty !== "RSA")
109
+ return false;
110
+ if (jwk.use !== undefined && jwk.use !== "sig")
111
+ return false;
112
+ if (jwk.key_ops !== undefined) {
113
+ if (!Array.isArray(jwk.key_ops) || !jwk.key_ops.includes("verify")) {
114
+ return false;
115
+ }
116
+ }
117
+ if (jwk.alg !== undefined) {
118
+ if (typeof jwk.alg !== "string" || !(jwk.alg in ALGORITHMS))
119
+ return false;
120
+ }
121
+ return true;
122
+ }
123
+ const ID_TOKEN_ONLY_CLAIMS = ["nonce", "at_hash", "c_hash", "s_hash"];
124
+ function metadataUrlsFor(issuer) {
125
+ let url;
126
+ try {
127
+ url = new URL(issuer);
128
+ }
129
+ catch {
130
+ throw new TypeError("`issuer` must be an absolute URL");
131
+ }
132
+ const path = url.pathname.replace(/\/$/, "");
133
+ return [
134
+ ...new Set([
135
+ `${url.origin}/.well-known/oauth-authorization-server${path}`,
136
+ `${url.origin}/.well-known/openid-configuration${path}`,
137
+ `${url.origin}${path}/.well-known/openid-configuration`,
138
+ ]),
139
+ ];
140
+ }
141
+ function scopeTextOf(claims) {
142
+ if (typeof claims.scope === "string" && claims.scope)
143
+ return claims.scope;
144
+ if (Array.isArray(claims.scp))
145
+ return claims.scp.join(" ") || undefined;
146
+ if (typeof claims.scp === "string" && claims.scp)
147
+ return claims.scp;
148
+ return undefined;
149
+ }
150
+ /**
151
+ * Validates JWT access tokens (RFC 9068) against the issuer's remote JWKS.
152
+ *
153
+ * Use this with {@linkcode ResourceServer} when the authorization server
154
+ * issues **signed** access tokens: keys are fetched once and cached on the
155
+ * instance, so validation costs no network round-trip per request — the
156
+ * trade-off against {@linkcode IntrospectionTokenReader}, which sees
157
+ * revocation immediately but calls the authorization server every time. A
158
+ * revoked JWT stays valid here until it expires, so keep access-token
159
+ * lifetimes short, or introspect on the endpoints where revocation latency
160
+ * matters.
161
+ *
162
+ * A token is accepted only when its signature verifies against a published
163
+ * key whose algorithm the header matches, and its `typ`, `iss`, `aud`, `exp`
164
+ * and `nbf` all satisfy the configuration. Anything else is `undefined` —
165
+ * the same `invalid_token` surface as an unknown opaque token. Unreachable
166
+ * key material throws instead, so a down issuer is never reported as a bad
167
+ * token.
168
+ *
169
+ * **Token substitution.** An access token must never be confused with
170
+ * another JWT the same issuer signs. Three checks enforce that
171
+ * independently: `typ` must be `at+jwt`
172
+ * ({@linkcode JwksTokenReaderOptions.types}), the client-id claim must be
173
+ * present ({@linkcode JwksTokenReaderOptions.clientIdClaim}, REQUIRED by
174
+ * RFC 9068 §2.2 and absent from an `id_token`), and `id_token`-only claims
175
+ * (`nonce`, `at_hash`, `c_hash`, `s_hash`) are rejected outright.
176
+ * `auth_time`, `acr` and `amr` are **not** in that list — RFC 9068 §2.2.1
177
+ * permits them on an access token. A `crit` header is rejected per RFC 7515
178
+ * §4.1.11, since this reader understands no JWS extensions.
179
+ *
180
+ * The cache lives on the instance: construct one reader and reuse it.
181
+ *
182
+ * @example
183
+ * ```ts
184
+ * import { JwksTokenReader, ResourceServer } from "@udibo/oauth2/server/resource";
185
+ *
186
+ * interface MyClient { id: string }
187
+ * interface MyUser { id: string }
188
+ *
189
+ * const tokenReader = new JwksTokenReader<MyClient, MyUser>({
190
+ * issuer: "https://auth.example.com",
191
+ * audience: "https://api.example.com",
192
+ * getClient: (claims) => ({ id: String(claims.client_id) }),
193
+ * getUser: (claims) => claims.sub ? { id: claims.sub } : undefined,
194
+ * });
195
+ *
196
+ * const resourceServer = new ResourceServer<MyClient, MyUser>({
197
+ * resolve: () => ({ services: { tokenService: tokenReader } }),
198
+ * });
199
+ * ```
200
+ */
201
+ export class JwksTokenReader {
202
+ #issuer;
203
+ #audience;
204
+ #algorithms;
205
+ #types;
206
+ #clientIdClaim;
207
+ #clockSkewSeconds;
208
+ #cacheMaxAgeMs;
209
+ #minFetchIntervalMs;
210
+ #fetchTimeoutMs;
211
+ #metadataUrls;
212
+ #Scope;
213
+ #getClient;
214
+ #getUser;
215
+ #customFetch;
216
+ #jwksUri;
217
+ #entries = [];
218
+ #fetchedAt = 0;
219
+ #lastAttemptAt = 0;
220
+ #inFlight;
221
+ /**
222
+ * Defaults: every Web Crypto asymmetric algorithm accepted, `at+jwt`
223
+ * required as `typ`, `client_id` as the required client-id claim, 30
224
+ * seconds of clock skew, a 10-minute cache with a 30-second minimum
225
+ * between fetches, a 5-second request deadline, {@linkcode BasicScope},
226
+ * and the global `fetch`.
227
+ *
228
+ * @throws {TypeError} If `issuer` is not an absolute URL, `audience` is
229
+ * empty, or `algorithms` names an algorithm this package cannot verify
230
+ * (a silently ignored entry would read as a policy that isn't enforced).
231
+ */
232
+ constructor(options) {
233
+ this.#issuer = options.issuer;
234
+ this.#metadataUrls = metadataUrlsFor(options.issuer);
235
+ this.#audience = Array.isArray(options.audience)
236
+ ? [...options.audience]
237
+ : [options.audience];
238
+ if (this.#audience.length === 0) {
239
+ throw new TypeError("`audience` must name at least one value");
240
+ }
241
+ this.#algorithms = options.algorithms ?? Object.keys(ALGORITHMS);
242
+ for (const algorithm of this.#algorithms) {
243
+ if (!(algorithm in ALGORITHMS)) {
244
+ throw new TypeError(`unsupported algorithm: ${algorithm}`);
245
+ }
246
+ }
247
+ this.#types = (options.types ?? ["at+jwt"]).map(normalizeType);
248
+ this.#clientIdClaim = options.clientIdClaim ?? "client_id";
249
+ this.#clockSkewSeconds = options.clockSkewSeconds ?? 30;
250
+ this.#cacheMaxAgeMs = options.cacheMaxAgeMs ?? 600_000;
251
+ this.#minFetchIntervalMs = options.minFetchIntervalMs ?? 30_000;
252
+ this.#fetchTimeoutMs = options.fetchTimeoutMs ?? 5_000;
253
+ this.#Scope = options.Scope ??
254
+ BasicScope;
255
+ this.#getClient = options.getClient;
256
+ this.#getUser = options.getUser;
257
+ this.#customFetch = options.fetch;
258
+ this.#jwksUri = options.jwksUri;
259
+ }
260
+ /**
261
+ * Validates a JWT access token against the cached JWKS.
262
+ *
263
+ * Refreshes the keys when no published key verifies the signature — at
264
+ * most one fetch per {@linkcode
265
+ * JwksTokenReaderOptions.minFetchIntervalMs}, shared by concurrent
266
+ * callers. A token whose `kid` matched a cached key and still failed
267
+ * verification is a forgery, not a rotation, and provokes no fetch. A
268
+ * stale cache refreshes in the background: requests are served from the
269
+ * cached keys rather than blocked on the issuer.
270
+ *
271
+ * @returns The token with client/user/scope info, or `undefined` when the
272
+ * token is malformed, signed by an unknown or unaccepted key, or fails
273
+ * any claim check.
274
+ * @throws {TemporarilyUnavailableError} If the JWKS (or discovery
275
+ * document) is unreachable or returns a 5xx **and** no cached keys are
276
+ * available — a down issuer must be distinguishable from a genuinely
277
+ * invalid token, not collapsed into it. Once keys are cached, a failed
278
+ * refresh is absorbed and the cached keys keep serving.
279
+ * @throws {ServerError} If the JWKS endpoint returns a 4xx or a body that
280
+ * is not a JWKS, or discovery reports no `jwks_uri` — a
281
+ * misconfiguration, not a verdict on the caller's token.
282
+ */
283
+ async getToken(accessToken) {
284
+ const parsed = parseJws(accessToken);
285
+ if (!parsed)
286
+ return undefined;
287
+ const { alg, kid, typ, crit } = parsed.header;
288
+ if (crit !== undefined)
289
+ return undefined;
290
+ if (typeof alg !== "string" || !this.#algorithms.includes(alg)) {
291
+ return undefined;
292
+ }
293
+ if (!this.#acceptsType(typ))
294
+ return undefined;
295
+ const verified = await this.#verified(parsed, alg, typeof kid === "string" ? kid : undefined);
296
+ if (!verified)
297
+ return undefined;
298
+ const claims = parsed.payload;
299
+ if (!this.#validClaims(claims))
300
+ return undefined;
301
+ const [client, user] = await Promise.all([
302
+ this.#getClient(claims),
303
+ this.#getUser?.(claims),
304
+ ]);
305
+ const scopeText = scopeTextOf(claims);
306
+ return {
307
+ accessToken,
308
+ accessTokenExpiresAt: new Date(claims.exp * 1000),
309
+ client,
310
+ user,
311
+ scope: scopeText ? new this.#Scope(scopeText) : undefined,
312
+ claims: claims,
313
+ };
314
+ }
315
+ #acceptsType(typ) {
316
+ if (this.#types.length === 0)
317
+ return true;
318
+ if (typeof typ !== "string")
319
+ return false;
320
+ return this.#types.includes(normalizeType(typ));
321
+ }
322
+ #validClaims(claims) {
323
+ if (claims.iss !== this.#issuer)
324
+ return false;
325
+ const clientId = claims[this.#clientIdClaim];
326
+ if (typeof clientId !== "string" || !clientId)
327
+ return false;
328
+ for (const claim of ID_TOKEN_ONLY_CLAIMS) {
329
+ if (claims[claim] !== undefined)
330
+ return false;
331
+ }
332
+ const audience = Array.isArray(claims.aud)
333
+ ? claims.aud
334
+ : typeof claims.aud === "string"
335
+ ? [claims.aud]
336
+ : [];
337
+ if (!audience.some((value) => this.#audience.includes(value)))
338
+ return false;
339
+ const now = Math.floor(Date.now() / 1000);
340
+ if (typeof claims.exp !== "number" || !Number.isFinite(claims.exp)) {
341
+ return false;
342
+ }
343
+ if (now >= claims.exp + this.#clockSkewSeconds)
344
+ return false;
345
+ if (claims.nbf !== undefined) {
346
+ if (typeof claims.nbf !== "number" || !Number.isFinite(claims.nbf)) {
347
+ return false;
348
+ }
349
+ if (claims.nbf - this.#clockSkewSeconds > now)
350
+ return false;
351
+ }
352
+ return true;
353
+ }
354
+ async #verifySignature(candidates, alg, parsed) {
355
+ const { verifyParams } = ALGORITHMS[alg];
356
+ for (const entry of candidates) {
357
+ const key = await this.#importKey(entry, alg);
358
+ if (!key)
359
+ continue;
360
+ const valid = await crypto.subtle.verify(verifyParams, key, parsed.signature, parsed.signingInput);
361
+ if (valid)
362
+ return true;
363
+ }
364
+ return false;
365
+ }
366
+ async #importKey(entry, alg) {
367
+ const cached = entry.imported.get(alg);
368
+ if (cached)
369
+ return cached;
370
+ try {
371
+ const key = await crypto.subtle.importKey("jwk", verifyJwkOf(entry.jwk), ALGORITHMS[alg].importParams, false, ["verify"]);
372
+ entry.imported.set(alg, key);
373
+ return key;
374
+ }
375
+ catch {
376
+ return undefined;
377
+ }
378
+ }
379
+ #match(kid, alg) {
380
+ const spec = ALGORITHMS[alg];
381
+ return this.#entries.filter((entry) => {
382
+ if (kid !== undefined && entry.kid !== kid)
383
+ return false;
384
+ if (entry.alg !== undefined && entry.alg !== alg)
385
+ return false;
386
+ if (entry.jwk.kty !== spec.kty)
387
+ return false;
388
+ if (spec.crv !== undefined && entry.jwk.crv !== spec.crv)
389
+ return false;
390
+ return true;
391
+ });
392
+ }
393
+ async #verified(parsed, alg, kid) {
394
+ await this.#ensureKeys();
395
+ const candidates = this.#match(kid, alg);
396
+ if (await this.#verifySignature(candidates, alg, parsed))
397
+ return true;
398
+ if (kid !== undefined && candidates.length > 0)
399
+ return false;
400
+ await this.#refreshQuietly();
401
+ return await this.#verifySignature(this.#match(kid, alg), alg, parsed);
402
+ }
403
+ async #ensureKeys() {
404
+ if (this.#entries.length === 0) {
405
+ await this.#refresh();
406
+ return;
407
+ }
408
+ if (Date.now() - this.#fetchedAt > this.#cacheMaxAgeMs) {
409
+ void this.#refreshQuietly();
410
+ }
411
+ }
412
+ async #refreshQuietly() {
413
+ await this.#refresh().catch(() => { });
414
+ }
415
+ async #refresh() {
416
+ if (this.#inFlight)
417
+ return await this.#inFlight;
418
+ if (Date.now() - this.#lastAttemptAt < this.#minFetchIntervalMs) {
419
+ if (this.#entries.length === 0) {
420
+ throw new TemporarilyUnavailableError("jwks is unavailable");
421
+ }
422
+ return;
423
+ }
424
+ const promise = this.#load();
425
+ this.#inFlight = promise;
426
+ try {
427
+ await promise;
428
+ }
429
+ finally {
430
+ this.#inFlight = undefined;
431
+ this.#lastAttemptAt = Date.now();
432
+ }
433
+ }
434
+ async #load() {
435
+ const jwksUri = this.#jwksUri ?? await this.#discoverJwksUri();
436
+ const body = await this.#fetchJson(jwksUri, "jwks");
437
+ if (!isRecord(body) || !Array.isArray(body.keys)) {
438
+ throw new ServerError("jwks response has no `keys` array");
439
+ }
440
+ this.#entries = body.keys
441
+ .filter((jwk) => isRecord(jwk))
442
+ .filter(usableForVerification)
443
+ .map((jwk) => ({
444
+ jwk,
445
+ kid: typeof jwk.kid === "string" ? jwk.kid : undefined,
446
+ alg: typeof jwk.alg === "string" ? jwk.alg : undefined,
447
+ imported: new Map(),
448
+ }));
449
+ this.#fetchedAt = Date.now();
450
+ }
451
+ async #discoverJwksUri() {
452
+ let transientError;
453
+ let lastError;
454
+ for (const url of this.#metadataUrls) {
455
+ try {
456
+ const metadata = await this.#fetchJson(url, "discovery");
457
+ const jwksUri = isRecord(metadata) ? metadata.jwks_uri : undefined;
458
+ if (typeof jwksUri !== "string") {
459
+ throw new ServerError("discovery metadata has no `jwks_uri`");
460
+ }
461
+ this.#jwksUri = jwksUri;
462
+ return jwksUri;
463
+ }
464
+ catch (error) {
465
+ if (error instanceof TemporarilyUnavailableError &&
466
+ transientError === undefined) {
467
+ transientError = error;
468
+ }
469
+ lastError = error;
470
+ }
471
+ }
472
+ throw transientError ?? lastError ?? new ServerError("discovery failed");
473
+ }
474
+ async #fetchJson(url, label) {
475
+ const fetchImpl = this.#customFetch ?? globalThis.fetch;
476
+ const controller = new AbortController();
477
+ const deadline = setTimeout(() => controller.abort(), this.#fetchTimeoutMs);
478
+ try {
479
+ let response;
480
+ try {
481
+ response = await fetchImpl(url, {
482
+ headers: { "Accept": "application/json" },
483
+ signal: controller.signal,
484
+ });
485
+ }
486
+ catch (cause) {
487
+ throw new TemporarilyUnavailableError(`${label} request failed`, {
488
+ cause,
489
+ });
490
+ }
491
+ if (!response.ok) {
492
+ await response.body?.cancel();
493
+ throw response.status >= 500
494
+ ? new TemporarilyUnavailableError(`${label} request failed (HTTP ${response.status})`)
495
+ : new ServerError(`${label} request failed (HTTP ${response.status})`);
496
+ }
497
+ try {
498
+ return await response.json();
499
+ }
500
+ catch (cause) {
501
+ throw new ServerError(`${label} response was not JSON`, { cause });
502
+ }
503
+ }
504
+ finally {
505
+ clearTimeout(deadline);
506
+ }
507
+ }
508
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Shared types for OAuth2 servers (both resource and authorization servers).
3
+ *
4
+ * This module exports errors, models, service interfaces, and utilities
5
+ * common to both server types. Import server-specific classes from:
6
+ * - `@udibo/oauth2/server/resource` for ResourceServer
7
+ * - `@udibo/oauth2/server/authorization` for AuthorizationServer
8
+ *
9
+ * @module
10
+ */
11
+ import "../_dnt.polyfills.js";
12
+ export type { ClientCredentials, ClientInterface } from "../models/client.js";
13
+ export type { AuthenticationContext } from "../models/authentication.js";
14
+ export type { IntrospectionResponse, RefreshToken, Token, TokenResponse, } from "../models/token.js";
15
+ export { AbstractScope, BasicScope } from "../models/scope.js";
16
+ export type { ScopeConstructor } from "../models/scope.js";
17
+ export { Authorization, authorizationFromClaims, } from "../models/authorization.js";
18
+ export type { AuthorizationFailure, AuthorizationInit, OrganizationContext, RequireConditions, } from "../models/authorization.js";
19
+ export { AccessDeniedError, AuthorizationPendingError, ExpiredTokenError, InsufficientPermissionsError, InsufficientScopeError, InvalidClientError, InvalidGrantError, InvalidRequestError, InvalidScopeError, InvalidTokenError, isOAuth2Error, OAuth2Error, ServerError, SlowDownError, TemporarilyUnavailableError, toOAuth2Error, UnauthorizedClientError, UnsupportedGrantTypeError, UnsupportedResponseTypeError, UnsupportedTokenTypeError, } from "../errors.js";
20
+ export type { OAuth2ErrorClass, OAuth2ProblemDetailsExtensions, } from "../errors.js";
21
+ export type { TokenReaderInterface } from "./services/token.js";
22
+ export { checkRedirectUriPattern, isRedirectUriPattern, matchRedirectUri, } from "./redirect-uri.js";
23
+ export type { IsPublicSuffix, RedirectUriPatternRule, RedirectUriPatternViolation, } from "./redirect-uri.js";
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Shared types for OAuth2 servers (both resource and authorization servers).
3
+ *
4
+ * This module exports errors, models, service interfaces, and utilities
5
+ * common to both server types. Import server-specific classes from:
6
+ * - `@udibo/oauth2/server/resource` for ResourceServer
7
+ * - `@udibo/oauth2/server/authorization` for AuthorizationServer
8
+ *
9
+ * @module
10
+ */
11
+ import "../_dnt.polyfills.js";
12
+ export { AbstractScope, BasicScope } from "../models/scope.js";
13
+ export { Authorization, authorizationFromClaims, } from "../models/authorization.js";
14
+ export { AccessDeniedError, AuthorizationPendingError, ExpiredTokenError, InsufficientPermissionsError, InsufficientScopeError, InvalidClientError, InvalidGrantError, InvalidRequestError, InvalidScopeError, InvalidTokenError, isOAuth2Error, OAuth2Error, ServerError, SlowDownError, TemporarilyUnavailableError, toOAuth2Error, UnauthorizedClientError, UnsupportedGrantTypeError, UnsupportedResponseTypeError, UnsupportedTokenTypeError, } from "../errors.js";
15
+ export { checkRedirectUriPattern, isRedirectUriPattern, matchRedirectUri, } from "./redirect-uri.js";
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The bundled Public Suffix List, as an {@link isPublicSuffix} implementation.
3
+ *
4
+ * A *public suffix* is a domain you can only register names **under**, never
5
+ * **at** — `com`, `co.uk`, `deno.net`, `s3.amazonaws.com`. The authorization
6
+ * server needs the distinction to bound a wildcard redirect URI: everything a
7
+ * wildcard covers must belong to one registrant, which is only true when the
8
+ * domain beneath it is a registrable name rather than a shared suffix.
9
+ *
10
+ * This entrypoint is separate from `@udibo/oauth2/server` on purpose. The list
11
+ * is roughly 150 kB of generated source, and a server that never accepts
12
+ * wildcard registrations should not carry it — so
13
+ * `checkRedirectUriPattern` takes the check as an injected seam and
14
+ * refuses every pattern when none is supplied. Wire it once, where you build
15
+ * the authorization server:
16
+ *
17
+ * ```ts
18
+ * import { AuthorizationServer } from "@udibo/oauth2/server/authorization";
19
+ * import { isPublicSuffix } from "@udibo/oauth2/server/public-suffix";
20
+ *
21
+ * const server = new AuthorizationServer({ isPublicSuffix, ...options });
22
+ * ```
23
+ *
24
+ * The snapshot covers both the ICANN and the private sections. The private
25
+ * section is the security-relevant half here: every shared hosting platform a
26
+ * wildcard must not straddle (`github.io`, `vercel.app`, `blob.core.windows.net`)
27
+ * is listed there and nowhere else.
28
+ *
29
+ * Regenerate it with `deno task psl:update`; `deno task psl:check` fails when
30
+ * the snapshot has drifted from publicsuffix.org and runs on a schedule in CI.
31
+ *
32
+ * @module
33
+ */
34
+ import "../../_dnt.polyfills.js";
35
+ import { publicSuffixListInfo } from "./rules.js";
36
+ export { publicSuffixListInfo };
37
+ /**
38
+ * Whether a domain is a public suffix — a name others register *under* rather
39
+ * than a registrable domain someone owns.
40
+ *
41
+ * Implements the publicsuffix.org algorithm against the bundled snapshot,
42
+ * including wildcard rules (`*.ck`), exception rules (`!www.ck`), and the
43
+ * implicit `*` rule that makes any unlisted top-level domain a public suffix.
44
+ * The argument may be Unicode or punycode, upper or lower case, with or
45
+ * without a trailing dot; a host that cannot be normalized (empty, or with an
46
+ * empty label) is reported as a public suffix so a caller bounding a wildcard
47
+ * fails closed.
48
+ *
49
+ * @param domain The hostname to classify.
50
+ * @returns `true` when the whole domain is a public suffix.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * import { isPublicSuffix } from "@udibo/oauth2/server/public-suffix";
55
+ *
56
+ * isPublicSuffix("co.uk"); // true
57
+ * isPublicSuffix("deno.net"); // true — anyone can take a subdomain
58
+ * isPublicSuffix("myorg.deno.net"); // false — one organization's namespace
59
+ * isPublicSuffix("example.com"); // false
60
+ * ```
61
+ */
62
+ export declare function isPublicSuffix(domain: string): boolean;