@udibo/oauth2 0.14.0 → 0.15.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 (411) hide show
  1. package/README.md +45 -24
  2. package/{esm → dist}/adapters/hono/_common.d.ts +5 -5
  3. package/{esm → dist}/adapters/hono/_common.js +1 -1
  4. package/{esm → dist}/adapters/hono/authorization-server.d.ts +6 -7
  5. package/{esm → dist}/adapters/hono/authorization-server.js +0 -1
  6. package/{esm → dist}/adapters/hono/bff/auth-request-store.d.ts +2 -2
  7. package/{esm → dist}/adapters/hono/bff/auth-request-store.js +2 -2
  8. package/{esm → dist}/adapters/hono/bff/bff.d.ts +22 -12
  9. package/{esm → dist}/adapters/hono/bff/bff.js +35 -29
  10. package/{esm → dist}/adapters/hono/bff/cookie-prefix.js +1 -2
  11. package/{esm → dist}/adapters/hono/bff/mod.d.ts +5 -6
  12. package/{esm → dist}/adapters/hono/bff/mod.js +1 -2
  13. package/{esm → dist}/adapters/hono/bff/proxy.js +2 -1
  14. package/{esm → dist}/adapters/hono/bff/session-store.d.ts +2 -2
  15. package/{esm → dist}/adapters/hono/bff/session-store.js +7 -6
  16. package/{esm → dist}/adapters/hono/bff/testing.d.ts +7 -8
  17. package/{esm → dist}/adapters/hono/bff/testing.js +19 -22
  18. package/{esm → dist}/adapters/hono/identity.d.ts +1 -2
  19. package/{esm → dist}/adapters/hono/identity.js +10 -10
  20. package/{esm → dist}/adapters/hono/log.d.ts +0 -1
  21. package/{esm → dist}/adapters/hono/log.js +0 -6
  22. package/{esm → dist}/adapters/hono/resource-server.d.ts +5 -6
  23. package/{esm → dist}/adapters/hono/resource-server.js +0 -1
  24. package/dist/cli/bin.d.ts +2 -0
  25. package/dist/cli/bin.js +3 -0
  26. package/dist/cli/idp/config.d.ts +110 -0
  27. package/dist/cli/idp/config.js +269 -0
  28. package/dist/cli/idp/mod.d.ts +20 -0
  29. package/dist/cli/idp/mod.js +175 -0
  30. package/dist/cli/idp/pages.d.ts +56 -0
  31. package/dist/cli/idp/pages.js +190 -0
  32. package/dist/cli/idp/server.d.ts +93 -0
  33. package/dist/cli/idp/server.js +559 -0
  34. package/dist/cli/keygen.d.ts +13 -0
  35. package/dist/cli/keygen.js +30 -0
  36. package/dist/cli/mod.d.ts +34 -0
  37. package/dist/cli/mod.js +94 -0
  38. package/{esm → dist}/client/_http.d.ts +1 -1
  39. package/{esm → dist}/client/base.d.ts +1 -1
  40. package/{esm → dist}/client/bff-client.d.ts +1 -1
  41. package/{esm → dist}/client/bff-client.js +7 -6
  42. package/{esm → dist}/client/browser-storage.d.ts +1 -1
  43. package/{esm → dist}/client/check.js +1 -1
  44. package/{esm → dist}/client/direct-client.d.ts +6 -6
  45. package/{esm → dist}/client/direct-client.js +11 -13
  46. package/{esm → dist}/client/discovery-cache.d.ts +1 -1
  47. package/{esm → dist}/client/discovery-cache.js +2 -2
  48. package/{esm → dist}/client/events.d.ts +1 -1
  49. package/{esm → dist}/client/mod.d.ts +11 -12
  50. package/{esm → dist}/client/mod.js +1 -1
  51. package/{esm → dist}/errors.d.ts +1 -1
  52. package/{esm → dist}/errors.js +1 -1
  53. package/{esm → dist}/identity/events.d.ts +1 -1
  54. package/{esm → dist}/identity/external/_shared.d.ts +1 -1
  55. package/{esm → dist}/identity/external/_shared.js +1 -2
  56. package/{esm → dist}/identity/external/apple-client-secret.d.ts +1 -1
  57. package/{esm → dist}/identity/external/apple-client-secret.js +6 -7
  58. package/{esm → dist}/identity/external/apple.d.ts +5 -5
  59. package/{esm → dist}/identity/external/apple.js +10 -11
  60. package/{esm → dist}/identity/external/discord.d.ts +3 -3
  61. package/{esm → dist}/identity/external/discord.js +2 -2
  62. package/{esm → dist}/identity/external/flow.d.ts +1 -1
  63. package/{esm → dist}/identity/external/flow.js +2 -2
  64. package/{esm → dist}/identity/external/github.d.ts +3 -3
  65. package/{esm → dist}/identity/external/github.js +12 -17
  66. package/{esm → dist}/identity/external/google.d.ts +5 -5
  67. package/{esm → dist}/identity/external/google.js +2 -2
  68. package/{esm → dist}/identity/external/mod.d.ts +12 -13
  69. package/{esm → dist}/identity/external/mod.js +0 -1
  70. package/{esm → dist}/identity/external/oauth2.d.ts +1 -1
  71. package/{esm → dist}/identity/external/oauth2.js +8 -8
  72. package/{esm → dist}/identity/external/oidc.d.ts +4 -4
  73. package/{esm → dist}/identity/external/oidc.js +9 -8
  74. package/{esm → dist}/identity/hibp.d.ts +1 -1
  75. package/{esm → dist}/identity/hibp.js +1 -1
  76. package/{esm → dist}/identity/lockout.js +1 -2
  77. package/{esm → dist}/identity/mfa/mod.d.ts +4 -5
  78. package/{esm → dist}/identity/mfa/mod.js +1 -2
  79. package/{esm → dist}/identity/mfa/service.d.ts +3 -3
  80. package/{esm → dist}/identity/mfa/service.js +4 -3
  81. package/{esm → dist}/identity/mfa/totp.d.ts +1 -1
  82. package/{esm → dist}/identity/mfa/totp.js +2 -2
  83. package/{esm → dist}/identity/migration.d.ts +2 -3
  84. package/{esm → dist}/identity/migration.js +3 -4
  85. package/{esm → dist}/identity/mod.d.ts +14 -15
  86. package/{esm → dist}/identity/mod.js +0 -1
  87. package/{esm → dist}/identity/otp.d.ts +1 -1
  88. package/{esm → dist}/identity/otp.js +4 -2
  89. package/{esm → dist}/identity/password.js +8 -5
  90. package/{esm → dist}/identity/rate-limit.d.ts +1 -1
  91. package/{esm → dist}/identity/service.d.ts +10 -10
  92. package/{esm → dist}/identity/service.js +17 -18
  93. package/{esm → dist}/identity/session.js +2 -2
  94. package/{esm → dist}/identity/token-flow.js +3 -2
  95. package/{esm → dist}/models/authorization-code.d.ts +3 -3
  96. package/{esm → dist}/models/authorization.d.ts +1 -1
  97. package/{esm → dist}/models/authorization.js +1 -2
  98. package/{esm → dist}/models/device-authorization.d.ts +2 -2
  99. package/{esm → dist}/models/token.d.ts +3 -3
  100. package/{esm → dist}/react/callback.d.ts +1 -1
  101. package/{esm → dist}/react/callback.js +0 -1
  102. package/{esm → dist}/react/components/class-names.d.ts +1 -1
  103. package/{esm → dist}/react/components/class-names.js +3 -2
  104. package/{esm → dist}/react/components/internal.d.ts +2 -2
  105. package/{esm → dist}/react/components/internal.js +5 -11
  106. package/{esm → dist}/react/components/mfa-challenge-form.d.ts +2 -2
  107. package/{esm → dist}/react/components/mfa-challenge-form.js +4 -6
  108. package/{esm → dist}/react/components/mfa-enrollment-form.d.ts +2 -2
  109. package/{esm → dist}/react/components/mfa-enrollment-form.js +2 -6
  110. package/{esm → dist}/react/components/mod.d.ts +20 -21
  111. package/{esm → dist}/react/components/mod.js +1 -2
  112. package/{esm → dist}/react/components/request-password-reset-form.d.ts +2 -2
  113. package/{esm → dist}/react/components/request-password-reset-form.js +1 -3
  114. package/{esm → dist}/react/components/reset-password-form.d.ts +2 -2
  115. package/{esm → dist}/react/components/reset-password-form.js +2 -2
  116. package/{esm → dist}/react/components/sign-in-form.d.ts +2 -2
  117. package/{esm → dist}/react/components/sign-in-form.js +1 -5
  118. package/{esm → dist}/react/components/sign-up-form.d.ts +2 -2
  119. package/{esm → dist}/react/components/sign-up-form.js +4 -10
  120. package/{esm → dist}/react/components/types.d.ts +2 -2
  121. package/{esm → dist}/react/components/use-auth-form.d.ts +3 -3
  122. package/{esm → dist}/react/components/use-auth-form.js +4 -7
  123. package/{esm → dist}/react/components/user-menu.d.ts +2 -2
  124. package/{esm → dist}/react/components/user-menu.js +9 -14
  125. package/{esm → dist}/react/context.d.ts +1 -1
  126. package/{esm → dist}/react/mod.d.ts +6 -7
  127. package/{esm → dist}/react/mod.js +0 -1
  128. package/{esm → dist}/react/provider.d.ts +2 -2
  129. package/{esm → dist}/react/require-auth.js +1 -3
  130. package/{esm → dist}/react/testing.d.ts +2 -3
  131. package/{esm → dist}/react/testing.js +1 -2
  132. package/{esm → dist}/react/use-authorization.d.ts +1 -1
  133. package/{esm → dist}/react/use-oauth2.d.ts +8 -1
  134. package/{esm → dist}/react/use-oauth2.js +0 -1
  135. package/{esm → dist}/server/_clock-skew.js +2 -1
  136. package/{esm → dist}/server/authorization-server.d.ts +40 -41
  137. package/{esm → dist}/server/authorization-server.js +32 -42
  138. package/{esm → dist}/server/client-authentication.d.ts +2 -2
  139. package/{esm → dist}/server/grants/authorization-code.d.ts +9 -9
  140. package/{esm → dist}/server/grants/authorization-code.js +5 -6
  141. package/{esm → dist}/server/grants/client-credentials.d.ts +4 -4
  142. package/{esm → dist}/server/grants/device-authorization.d.ts +6 -6
  143. package/{esm → dist}/server/grants/device-authorization.js +4 -4
  144. package/{esm → dist}/server/grants/grant.d.ts +7 -7
  145. package/{esm → dist}/server/grants/grant.js +7 -7
  146. package/{esm → dist}/server/grants/password.d.ts +5 -5
  147. package/{esm → dist}/server/grants/refresh-token.d.ts +4 -4
  148. package/{esm → dist}/server/grants/refresh-token.js +5 -6
  149. package/{esm → dist}/server/introspection-token-reader.d.ts +5 -5
  150. package/{esm → dist}/server/introspection-token-reader.js +4 -4
  151. package/{esm → dist}/server/jwks-token-reader.d.ts +5 -5
  152. package/{esm → dist}/server/jwks-token-reader.js +4 -4
  153. package/{esm → dist}/server/mod.d.ts +12 -13
  154. package/{esm → dist}/server/mod.js +0 -1
  155. package/{esm → dist}/server/public-suffix/mod.d.ts +2 -3
  156. package/{esm → dist}/server/public-suffix/mod.js +1 -2
  157. package/{esm → dist}/server/public-suffix/rules.d.ts +1 -1
  158. package/{esm → dist}/server/public-suffix/rules.js +1 -1
  159. package/{esm → dist}/server/redirect-uri.js +5 -4
  160. package/{esm → dist}/server/resource-server.d.ts +11 -12
  161. package/{esm → dist}/server/resource-server.js +12 -14
  162. package/{esm → dist}/server/services/authorization-code.d.ts +5 -5
  163. package/{esm → dist}/server/services/client.d.ts +1 -1
  164. package/{esm → dist}/server/services/device-authorization.d.ts +3 -3
  165. package/{esm → dist}/server/services/token.d.ts +6 -6
  166. package/{esm → dist}/server/services/token.js +3 -1
  167. package/{esm → dist}/server/services/user.d.ts +1 -1
  168. package/{esm → dist}/server/signing-keys.d.ts +1 -1
  169. package/{esm → dist}/server/signing-keys.js +8 -2
  170. package/{esm → dist}/server/utils/hash.js +1 -1
  171. package/{esm → dist}/testing/contract/auth-request-storage.d.ts +1 -1
  172. package/{esm → dist}/testing/contract/auth-request-storage.js +24 -29
  173. package/{esm → dist}/testing/contract/authorization-code.d.ts +6 -6
  174. package/{esm → dist}/testing/contract/authorization-code.js +16 -17
  175. package/{esm → dist}/testing/contract/client.d.ts +4 -4
  176. package/{esm → dist}/testing/contract/client.js +14 -15
  177. package/{esm → dist}/testing/contract/device-authorization.d.ts +6 -6
  178. package/{esm → dist}/testing/contract/device-authorization.js +37 -39
  179. package/{esm → dist}/testing/contract/identity-session.d.ts +6 -1
  180. package/{esm → dist}/testing/contract/identity-session.js +44 -36
  181. package/{esm → dist}/testing/contract/identity-user-store.d.ts +8 -2
  182. package/{esm → dist}/testing/contract/identity-user-store.js +48 -46
  183. package/{esm → dist}/testing/contract/lockout-store.d.ts +1 -1
  184. package/{esm → dist}/testing/contract/lockout-store.js +23 -24
  185. package/{esm → dist}/testing/contract/mfa-store.d.ts +1 -1
  186. package/{esm → dist}/testing/contract/mfa-store.js +53 -54
  187. package/{esm → dist}/testing/contract/mod.d.ts +15 -16
  188. package/{esm → dist}/testing/contract/mod.js +0 -1
  189. package/{esm → dist}/testing/contract/otp-store.d.ts +1 -1
  190. package/{esm → dist}/testing/contract/otp-store.js +33 -34
  191. package/{esm → dist}/testing/contract/rate-limit-store.d.ts +1 -1
  192. package/{esm → dist}/testing/contract/rate-limit-store.js +15 -16
  193. package/{esm → dist}/testing/contract/tenant.js +361 -330
  194. package/{esm → dist}/testing/contract/token-flow-store.d.ts +1 -1
  195. package/{esm → dist}/testing/contract/token-flow-store.js +27 -32
  196. package/{esm → dist}/testing/contract/token-reader.d.ts +3 -3
  197. package/{esm → dist}/testing/contract/token-reader.js +6 -7
  198. package/{esm → dist}/testing/contract/token.d.ts +7 -7
  199. package/{esm → dist}/testing/contract/token.js +48 -53
  200. package/{esm → dist}/testing/contract/user.d.ts +2 -2
  201. package/{esm → dist}/testing/contract/user.js +8 -9
  202. package/{esm → dist}/testing/mod.d.ts +5 -6
  203. package/{esm → dist}/testing/mod.js +2 -3
  204. package/{esm → dist}/testing/server.d.ts +7 -6
  205. package/{esm → dist}/testing/server.js +2 -1
  206. package/{esm → dist}/testing/services.d.ts +11 -11
  207. package/{esm → dist}/testing/services.js +8 -8
  208. package/{esm → dist}/testing/tenant.d.ts +11 -7
  209. package/{esm → dist}/testing/tenant.js +109 -94
  210. package/dist/utils/_constant-time.d.ts +12 -0
  211. package/dist/utils/_constant-time.js +19 -0
  212. package/{esm → dist}/utils/_default-fetch.js +4 -1
  213. package/dist/utils/_delay.d.ts +13 -0
  214. package/dist/utils/_delay.js +28 -0
  215. package/dist/utils/_encoding.d.ts +39 -0
  216. package/dist/utils/_encoding.js +126 -0
  217. package/{esm → dist}/utils/authentication-context.d.ts +1 -1
  218. package/{esm → dist}/utils/crypto.d.ts +2 -3
  219. package/{esm → dist}/utils/crypto.js +3 -4
  220. package/{esm → dist}/utils/pkce.js +1 -1
  221. package/{esm → dist}/utils/text.js +1 -1
  222. package/{esm → dist}/utils/url.d.ts +0 -1
  223. package/{esm → dist}/utils/url.js +0 -1
  224. package/package.json +156 -33
  225. package/esm/_dnt.polyfills.d.ts +0 -31
  226. package/esm/_dnt.polyfills.js +0 -26
  227. package/esm/deps/jsr.io/@std/assert/1.0.19/almost_equals.d.ts +0 -29
  228. package/esm/deps/jsr.io/@std/assert/1.0.19/almost_equals.js +0 -47
  229. package/esm/deps/jsr.io/@std/assert/1.0.19/array_includes.d.ts +0 -28
  230. package/esm/deps/jsr.io/@std/assert/1.0.19/array_includes.js +0 -65
  231. package/esm/deps/jsr.io/@std/assert/1.0.19/assert.d.ts +0 -16
  232. package/esm/deps/jsr.io/@std/assert/1.0.19/assert.js +0 -23
  233. package/esm/deps/jsr.io/@std/assert/1.0.19/assertion_error.d.ts +0 -25
  234. package/esm/deps/jsr.io/@std/assert/1.0.19/assertion_error.js +0 -30
  235. package/esm/deps/jsr.io/@std/assert/1.0.19/equal.d.ts +0 -24
  236. package/esm/deps/jsr.io/@std/assert/1.0.19/equal.js +0 -193
  237. package/esm/deps/jsr.io/@std/assert/1.0.19/equals.d.ts +0 -36
  238. package/esm/deps/jsr.io/@std/assert/1.0.19/equals.js +0 -61
  239. package/esm/deps/jsr.io/@std/assert/1.0.19/exists.d.ts +0 -17
  240. package/esm/deps/jsr.io/@std/assert/1.0.19/exists.js +0 -27
  241. package/esm/deps/jsr.io/@std/assert/1.0.19/fail.d.ts +0 -14
  242. package/esm/deps/jsr.io/@std/assert/1.0.19/fail.js +0 -20
  243. package/esm/deps/jsr.io/@std/assert/1.0.19/false.d.ts +0 -18
  244. package/esm/deps/jsr.io/@std/assert/1.0.19/false.js +0 -23
  245. package/esm/deps/jsr.io/@std/assert/1.0.19/greater.d.ts +0 -19
  246. package/esm/deps/jsr.io/@std/assert/1.0.19/greater.js +0 -29
  247. package/esm/deps/jsr.io/@std/assert/1.0.19/greater_or_equal.d.ts +0 -19
  248. package/esm/deps/jsr.io/@std/assert/1.0.19/greater_or_equal.js +0 -29
  249. package/esm/deps/jsr.io/@std/assert/1.0.19/instance_of.d.ts +0 -22
  250. package/esm/deps/jsr.io/@std/assert/1.0.19/instance_of.js +0 -52
  251. package/esm/deps/jsr.io/@std/assert/1.0.19/is_error.d.ts +0 -24
  252. package/esm/deps/jsr.io/@std/assert/1.0.19/is_error.js +0 -53
  253. package/esm/deps/jsr.io/@std/assert/1.0.19/less.d.ts +0 -18
  254. package/esm/deps/jsr.io/@std/assert/1.0.19/less.js +0 -28
  255. package/esm/deps/jsr.io/@std/assert/1.0.19/less_or_equal.d.ts +0 -19
  256. package/esm/deps/jsr.io/@std/assert/1.0.19/less_or_equal.js +0 -29
  257. package/esm/deps/jsr.io/@std/assert/1.0.19/match.d.ts +0 -17
  258. package/esm/deps/jsr.io/@std/assert/1.0.19/match.js +0 -26
  259. package/esm/deps/jsr.io/@std/assert/1.0.19/mod.d.ts +0 -43
  260. package/esm/deps/jsr.io/@std/assert/1.0.19/mod.js +0 -45
  261. package/esm/deps/jsr.io/@std/assert/1.0.19/not_equals.d.ts +0 -26
  262. package/esm/deps/jsr.io/@std/assert/1.0.19/not_equals.js +0 -39
  263. package/esm/deps/jsr.io/@std/assert/1.0.19/not_instance_of.d.ts +0 -19
  264. package/esm/deps/jsr.io/@std/assert/1.0.19/not_instance_of.js +0 -29
  265. package/esm/deps/jsr.io/@std/assert/1.0.19/not_match.d.ts +0 -17
  266. package/esm/deps/jsr.io/@std/assert/1.0.19/not_match.js +0 -26
  267. package/esm/deps/jsr.io/@std/assert/1.0.19/not_strict_equals.d.ts +0 -22
  268. package/esm/deps/jsr.io/@std/assert/1.0.19/not_strict_equals.js +0 -32
  269. package/esm/deps/jsr.io/@std/assert/1.0.19/object_match.d.ts +0 -28
  270. package/esm/deps/jsr.io/@std/assert/1.0.19/object_match.js +0 -177
  271. package/esm/deps/jsr.io/@std/assert/1.0.19/rejects.d.ts +0 -41
  272. package/esm/deps/jsr.io/@std/assert/1.0.19/rejects.js +0 -53
  273. package/esm/deps/jsr.io/@std/assert/1.0.19/strict_equals.d.ts +0 -23
  274. package/esm/deps/jsr.io/@std/assert/1.0.19/strict_equals.js +0 -58
  275. package/esm/deps/jsr.io/@std/assert/1.0.19/string_includes.d.ts +0 -17
  276. package/esm/deps/jsr.io/@std/assert/1.0.19/string_includes.js +0 -26
  277. package/esm/deps/jsr.io/@std/assert/1.0.19/throws.d.ts +0 -44
  278. package/esm/deps/jsr.io/@std/assert/1.0.19/throws.js +0 -44
  279. package/esm/deps/jsr.io/@std/assert/1.0.19/unimplemented.d.ts +0 -14
  280. package/esm/deps/jsr.io/@std/assert/1.0.19/unimplemented.js +0 -20
  281. package/esm/deps/jsr.io/@std/assert/1.0.19/unreachable.d.ts +0 -14
  282. package/esm/deps/jsr.io/@std/assert/1.0.19/unreachable.js +0 -20
  283. package/esm/deps/jsr.io/@std/async/1.5.0/delay.d.ts +0 -44
  284. package/esm/deps/jsr.io/@std/async/1.5.0/delay.js +0 -84
  285. package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.d.ts +0 -39
  286. package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.js +0 -61
  287. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common16.d.ts +0 -22
  288. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common16.js +0 -51
  289. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common32.d.ts +0 -34
  290. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common32.js +0 -192
  291. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common64.d.ts +0 -34
  292. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common64.js +0 -113
  293. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common_detach.d.ts +0 -3
  294. package/esm/deps/jsr.io/@std/encoding/1.0.11/_common_detach.js +0 -13
  295. package/esm/deps/jsr.io/@std/encoding/1.0.11/_types.d.ts +0 -8
  296. package/esm/deps/jsr.io/@std/encoding/1.0.11/_types.js +0 -2
  297. package/esm/deps/jsr.io/@std/encoding/1.0.11/_validate_binary_like.d.ts +0 -1
  298. package/esm/deps/jsr.io/@std/encoding/1.0.11/_validate_binary_like.js +0 -26
  299. package/esm/deps/jsr.io/@std/encoding/1.0.11/ascii85.d.ts +0 -60
  300. package/esm/deps/jsr.io/@std/encoding/1.0.11/ascii85.js +0 -152
  301. package/esm/deps/jsr.io/@std/encoding/1.0.11/base32.d.ts +0 -39
  302. package/esm/deps/jsr.io/@std/encoding/1.0.11/base32.js +0 -87
  303. package/esm/deps/jsr.io/@std/encoding/1.0.11/base58.d.ts +0 -39
  304. package/esm/deps/jsr.io/@std/encoding/1.0.11/base58.js +0 -131
  305. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64.d.ts +0 -39
  306. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64.js +0 -82
  307. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64url.d.ts +0 -39
  308. package/esm/deps/jsr.io/@std/encoding/1.0.11/base64url.js +0 -72
  309. package/esm/deps/jsr.io/@std/encoding/1.0.11/hex.d.ts +0 -38
  310. package/esm/deps/jsr.io/@std/encoding/1.0.11/hex.js +0 -87
  311. package/esm/deps/jsr.io/@std/encoding/1.0.11/mod.d.ts +0 -97
  312. package/esm/deps/jsr.io/@std/encoding/1.0.11/mod.js +0 -99
  313. package/esm/deps/jsr.io/@std/encoding/1.0.11/varint.d.ts +0 -119
  314. package/esm/deps/jsr.io/@std/encoding/1.0.11/varint.js +0 -209
  315. package/esm/deps/jsr.io/@std/http/1.1.3/status.d.ts +0 -343
  316. package/esm/deps/jsr.io/@std/http/1.1.3/status.js +0 -343
  317. package/esm/deps/jsr.io/@std/internal/1.0.14/assertion_state.d.ts +0 -159
  318. package/esm/deps/jsr.io/@std/internal/1.0.14/assertion_state.js +0 -223
  319. package/esm/deps/jsr.io/@std/internal/1.0.14/build_message.d.ts +0 -79
  320. package/esm/deps/jsr.io/@std/internal/1.0.14/build_message.js +0 -116
  321. package/esm/deps/jsr.io/@std/internal/1.0.14/diff.d.ts +0 -139
  322. package/esm/deps/jsr.io/@std/internal/1.0.14/diff.js +0 -277
  323. package/esm/deps/jsr.io/@std/internal/1.0.14/diff_str.d.ts +0 -98
  324. package/esm/deps/jsr.io/@std/internal/1.0.14/diff_str.js +0 -181
  325. package/esm/deps/jsr.io/@std/internal/1.0.14/format.d.ts +0 -29
  326. package/esm/deps/jsr.io/@std/internal/1.0.14/format.js +0 -68
  327. package/esm/deps/jsr.io/@std/internal/1.0.14/styles.d.ts +0 -158
  328. package/esm/deps/jsr.io/@std/internal/1.0.14/styles.js +0 -206
  329. package/esm/deps/jsr.io/@std/internal/1.0.14/types.d.ts +0 -24
  330. package/esm/deps/jsr.io/@std/internal/1.0.14/types.js +0 -3
  331. package/esm/deps/jsr.io/@std/testing/1.0.20/_test_suite.d.ts +0 -91
  332. package/esm/deps/jsr.io/@std/testing/1.0.20/_test_suite.js +0 -347
  333. package/esm/deps/jsr.io/@std/testing/1.0.20/bdd.d.ts +0 -382
  334. package/esm/deps/jsr.io/@std/testing/1.0.20/bdd.js +0 -1110
  335. package/esm/deps/jsr.io/@udibo/http-error/0.11.1/mod.d.ts +0 -363
  336. package/esm/deps/jsr.io/@udibo/http-error/0.11.1/mod.js +0 -616
  337. package/esm/package.json +0 -3
  338. /package/{esm → dist}/adapters/hono/bff/cookie-prefix.d.ts +0 -0
  339. /package/{esm → dist}/adapters/hono/bff/proxy.d.ts +0 -0
  340. /package/{esm → dist}/client/_http.js +0 -0
  341. /package/{esm → dist}/client/base.js +0 -0
  342. /package/{esm → dist}/client/browser-storage.js +0 -0
  343. /package/{esm → dist}/client/check.d.ts +0 -0
  344. /package/{esm → dist}/client/events.js +0 -0
  345. /package/{esm → dist}/client/storage.d.ts +0 -0
  346. /package/{esm → dist}/client/storage.js +0 -0
  347. /package/{esm → dist}/identity/captcha.d.ts +0 -0
  348. /package/{esm → dist}/identity/captcha.js +0 -0
  349. /package/{esm → dist}/identity/delivery.d.ts +0 -0
  350. /package/{esm → dist}/identity/delivery.js +0 -0
  351. /package/{esm → dist}/identity/errors.d.ts +0 -0
  352. /package/{esm → dist}/identity/errors.js +0 -0
  353. /package/{esm → dist}/identity/events.js +0 -0
  354. /package/{esm → dist}/identity/external/_token-exchange.d.ts +0 -0
  355. /package/{esm → dist}/identity/external/_token-exchange.js +0 -0
  356. /package/{esm → dist}/identity/external/errors.d.ts +0 -0
  357. /package/{esm → dist}/identity/external/errors.js +0 -0
  358. /package/{esm → dist}/identity/external/provider.d.ts +0 -0
  359. /package/{esm → dist}/identity/external/provider.js +0 -0
  360. /package/{esm → dist}/identity/identifier.d.ts +0 -0
  361. /package/{esm → dist}/identity/identifier.js +0 -0
  362. /package/{esm → dist}/identity/lockout.d.ts +0 -0
  363. /package/{esm → dist}/identity/mfa/recovery-codes.d.ts +0 -0
  364. /package/{esm → dist}/identity/mfa/recovery-codes.js +0 -0
  365. /package/{esm → dist}/identity/password-policy.d.ts +0 -0
  366. /package/{esm → dist}/identity/password-policy.js +0 -0
  367. /package/{esm → dist}/identity/password.d.ts +0 -0
  368. /package/{esm → dist}/identity/rate-limit.js +0 -0
  369. /package/{esm → dist}/identity/session.d.ts +0 -0
  370. /package/{esm → dist}/identity/token-flow.d.ts +0 -0
  371. /package/{esm → dist}/models/authentication.d.ts +0 -0
  372. /package/{esm → dist}/models/authentication.js +0 -0
  373. /package/{esm → dist}/models/authorization-code.js +0 -0
  374. /package/{esm → dist}/models/client.d.ts +0 -0
  375. /package/{esm → dist}/models/client.js +0 -0
  376. /package/{esm → dist}/models/device-authorization.js +0 -0
  377. /package/{esm → dist}/models/responses.d.ts +0 -0
  378. /package/{esm → dist}/models/responses.js +0 -0
  379. /package/{esm → dist}/models/scope.d.ts +0 -0
  380. /package/{esm → dist}/models/scope.js +0 -0
  381. /package/{esm → dist}/models/token.js +0 -0
  382. /package/{esm → dist}/react/components/types.js +0 -0
  383. /package/{esm → dist}/react/context.js +0 -0
  384. /package/{esm → dist}/react/provider.js +0 -0
  385. /package/{esm → dist}/react/require-auth.d.ts +0 -0
  386. /package/{esm → dist}/react/use-authorization.js +0 -0
  387. /package/{esm → dist}/server/_clock-skew.d.ts +0 -0
  388. /package/{esm → dist}/server/client-authentication.js +0 -0
  389. /package/{esm → dist}/server/grants/client-credentials.js +0 -0
  390. /package/{esm → dist}/server/grants/password.js +0 -0
  391. /package/{esm → dist}/server/redirect-uri.d.ts +0 -0
  392. /package/{esm → dist}/server/services/authorization-code.js +0 -0
  393. /package/{esm → dist}/server/services/client.js +0 -0
  394. /package/{esm → dist}/server/services/device-authorization.js +0 -0
  395. /package/{esm → dist}/server/services/user.js +0 -0
  396. /package/{esm → dist}/server/utils/hash.d.ts +0 -0
  397. /package/{esm → dist}/testing/contract/_race.d.ts +0 -0
  398. /package/{esm → dist}/testing/contract/_race.js +0 -0
  399. /package/{esm → dist}/testing/contract/tenant.d.ts +0 -0
  400. /package/{esm → dist}/utils/_body.d.ts +0 -0
  401. /package/{esm → dist}/utils/_body.js +0 -0
  402. /package/{esm → dist}/utils/_buffer.d.ts +0 -0
  403. /package/{esm → dist}/utils/_buffer.js +0 -0
  404. /package/{esm → dist}/utils/_default-fetch.d.ts +0 -0
  405. /package/{esm → dist}/utils/_timing-safe.d.ts +0 -0
  406. /package/{esm → dist}/utils/_timing-safe.js +0 -0
  407. /package/{esm → dist}/utils/authentication-context.js +0 -0
  408. /package/{esm → dist}/utils/basic-auth.d.ts +0 -0
  409. /package/{esm → dist}/utils/basic-auth.js +0 -0
  410. /package/{esm → dist}/utils/pkce.d.ts +0 -0
  411. /package/{esm → dist}/utils/text.d.ts +0 -0
@@ -0,0 +1,175 @@
1
+ /**
2
+ * The `idp dev` command: runs the development identity provider from a config
3
+ * file (or the built-in demo config) and prints what it seeded.
4
+ *
5
+ * @module
6
+ */
7
+ import { generateSigningKey, importSigningKeyJwk, } from "../../server/signing-keys.js";
8
+ import { defaultDevIdpConfig, loadDevIdpConfig, } from "./config.js";
9
+ import { ADMIN_TOKEN_HEADER, isLoopbackHostname, startDevIdentityProvider, } from "./server.js";
10
+ const SIGNING_KEY_VARIABLE = "OIDC_SIGNING_KEY";
11
+ const ADMIN_TOKEN_VARIABLE = "IDP_ADMIN_TOKEN";
12
+ const VALUE_FLAGS = [
13
+ "--config",
14
+ "--port",
15
+ "--hostname",
16
+ "--issuer",
17
+ "--admin-token",
18
+ ];
19
+ const BOOLEAN_FLAGS = ["--unsafe-remote-access"];
20
+ function parseIdpDevArgs(args) {
21
+ const parsed = {};
22
+ for (let index = 0; index < args.length; index++) {
23
+ const argument = args[index];
24
+ const separator = argument.indexOf("=");
25
+ const flag = separator === -1 ? argument : argument.slice(0, separator);
26
+ if (BOOLEAN_FLAGS.includes(flag) && separator === -1) {
27
+ parsed.allowRemoteAccess = true;
28
+ continue;
29
+ }
30
+ if (!VALUE_FLAGS.includes(flag)) {
31
+ throw new Error(`unknown option "${argument}" (expected one of: ${[
32
+ ...VALUE_FLAGS,
33
+ ...BOOLEAN_FLAGS,
34
+ ].join(", ")})`);
35
+ }
36
+ const value = separator === -1 ? args[++index] : argument.slice(separator + 1);
37
+ if (value === undefined || value.length === 0) {
38
+ throw new Error(`${flag} requires a value`);
39
+ }
40
+ if (flag === "--config")
41
+ parsed.configPath = value;
42
+ if (flag === "--hostname")
43
+ parsed.hostname = value;
44
+ if (flag === "--issuer")
45
+ parsed.issuer = value;
46
+ if (flag === "--admin-token")
47
+ parsed.adminToken = value;
48
+ if (flag === "--port") {
49
+ const port = Number(value);
50
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
51
+ throw new Error(`--port must be an integer between 0 and 65535`);
52
+ }
53
+ parsed.port = port;
54
+ }
55
+ }
56
+ return parsed;
57
+ }
58
+ function readVariable(name) {
59
+ return process.env[name] || undefined;
60
+ }
61
+ async function resolveSigningKey(config) {
62
+ const fromEnvironment = readVariable(SIGNING_KEY_VARIABLE);
63
+ if (fromEnvironment) {
64
+ let jwk;
65
+ try {
66
+ jwk = JSON.parse(fromEnvironment);
67
+ }
68
+ catch {
69
+ throw new Error(`${SIGNING_KEY_VARIABLE} is not valid JSON`);
70
+ }
71
+ return {
72
+ key: await importSigningKeyJwk(jwk),
73
+ source: SIGNING_KEY_VARIABLE,
74
+ };
75
+ }
76
+ if (config.signingKey) {
77
+ return {
78
+ key: await importSigningKeyJwk(config.signingKey),
79
+ source: "the config file",
80
+ };
81
+ }
82
+ return { key: await generateSigningKey(), source: "" };
83
+ }
84
+ function describeSeed(config) {
85
+ const lines = ["Users:"];
86
+ if (config.users.length === 0)
87
+ lines.push(" (none)");
88
+ for (const user of config.users) {
89
+ lines.push(` ${user.username} password: ${user.password} sub: ${user.id}`);
90
+ }
91
+ lines.push("", "Clients:");
92
+ if (config.clients.length === 0)
93
+ lines.push(" (none)");
94
+ for (const client of config.clients) {
95
+ lines.push(` ${client.id} ${client.secret ? `secret: ${client.secret}` : "public client"}`, ` grants: ${client.grants.join(", ")}`, ` redirect URIs: ${client.redirectUris.join(", ") || "(none)"}`);
96
+ }
97
+ return lines;
98
+ }
99
+ /**
100
+ * Runs the development identity provider until the process is stopped.
101
+ *
102
+ * Accepts `--config <path>`, `--port <number>`, `--hostname <host>`,
103
+ * `--issuer <url>`, `--admin-token <token>`, and `--unsafe-remote-access`;
104
+ * flags win over the config file, which wins over the built-in demo config.
105
+ * `IDP_ADMIN_TOKEN` supplies the admin token when the flag is absent.
106
+ *
107
+ * Aborting `signal` shuts the server down and resolves the returned promise.
108
+ *
109
+ * @throws {Error} When an option or the config file is invalid, or when the
110
+ * bind address is not loopback and `--unsafe-remote-access` was not passed.
111
+ */
112
+ export async function idpDev(args, signal) {
113
+ const options = parseIdpDevArgs(args);
114
+ const config = options.configPath
115
+ ? await loadDevIdpConfig(options.configPath)
116
+ : defaultDevIdpConfig();
117
+ if (options.port !== undefined)
118
+ config.port = options.port;
119
+ if (options.hostname !== undefined)
120
+ config.hostname = options.hostname;
121
+ if (options.issuer !== undefined)
122
+ config.issuer = options.issuer;
123
+ const { key, source } = await resolveSigningKey(config);
124
+ const idp = await startDevIdentityProvider({
125
+ config,
126
+ signingKey: key,
127
+ adminToken: options.adminToken ?? readVariable(ADMIN_TOKEN_VARIABLE),
128
+ allowRemoteAccess: options.allowRemoteAccess,
129
+ });
130
+ const loopback = isLoopbackHostname(idp.hostname);
131
+ const stop = () => void idp.shutdown();
132
+ if (signal?.aborted)
133
+ stop();
134
+ else
135
+ signal?.addEventListener("abort", stop, { once: true });
136
+ console.log([
137
+ "@udibo/oauth2 development identity provider",
138
+ "",
139
+ " DEVELOPMENT AND CI ONLY. State is in memory and the /__admin/",
140
+ " endpoints mint tokens for any seeded user without their password.",
141
+ " Never expose this server to a network you do not control.",
142
+ "",
143
+ `Listening on ${idp.url}`,
144
+ `Reachable from: ${loopback
145
+ ? "this machine only (loopback)"
146
+ : `ANY HOST THAT CAN REACH ${idp.hostname}:${idp.port} — remote access was enabled explicitly`}`,
147
+ `Issuer: ${idp.issuer}${config.issuer
148
+ ? ""
149
+ : " (derived from the bind address; pin it with --issuer)"}`,
150
+ `Discovery: ${idp.url}/.well-known/openid-configuration`,
151
+ `JWKS: ${idp.url}/jwks`,
152
+ `Signing key: ${source
153
+ ? `loaded from ${source} (kid ${key.kid})`
154
+ : `generated (kid ${key.kid})`}`,
155
+ `Consent: ${config.consent === "prompt" ? "prompted" : "granted automatically"}`,
156
+ "",
157
+ `Admin token: ${idp.adminToken}`,
158
+ ` Send it as the ${ADMIN_TOKEN_HEADER} header on every /__admin/ request.`,
159
+ ` Set ${ADMIN_TOKEN_VARIABLE} or --admin-token to choose it yourself.`,
160
+ "",
161
+ ...describeSeed(config),
162
+ ].join("\n"));
163
+ if (!loopback) {
164
+ console.error(`\nWARNING: bound to ${idp.hostname}, which is not loopback. Anyone who ` +
165
+ `can reach this port and read the admin token can mint tokens for any ` +
166
+ `seeded user. Only do this on a network you control, such as a CI ` +
167
+ `job's private network.`);
168
+ }
169
+ if (!source) {
170
+ console.error(`\nNo ${SIGNING_KEY_VARIABLE} and no "signingKey" in the config: this ` +
171
+ `key exists only for this process, so tokens and JWKS change on ` +
172
+ `every restart. Pin one with "udibo-oauth2 oidc keygen".`);
173
+ }
174
+ await idp.finished;
175
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The development identity provider's HTML: a sign-in page, a consent screen,
3
+ * and the status page served at `/`.
4
+ *
5
+ * Hand-written markup with no client-side JavaScript, so the pages render the
6
+ * same in a browser and in a `fetch`-driven test. Every control a test needs
7
+ * carries a stable `id` and `name`.
8
+ *
9
+ * @module
10
+ */
11
+ import type { DevIdpClientConfig, DevIdpUserConfig } from "./config.ts";
12
+ /** Wraps HTML in a `Response` with the headers a browser and a test expect. */
13
+ export declare function htmlResponse(html: string, status?: number): Response;
14
+ /** Options for {@link loginPage}. */
15
+ export interface LoginPageOptions {
16
+ /** URL to continue to after a successful sign-in, usually the authorize URL. */
17
+ returnTo: string;
18
+ /** Seeded users, offered as one-click sign-in buttons. */
19
+ users: readonly DevIdpUserConfig[];
20
+ /** Message to show above the form after a failed attempt. */
21
+ error?: string;
22
+ }
23
+ /**
24
+ * The sign-in page. Submits to `POST /login` with `username` + `password`, or
25
+ * with `as=<username>` from a one-click button.
26
+ */
27
+ export declare function loginPage(options: LoginPageOptions): string;
28
+ /** Options for {@link consentPage}. */
29
+ export interface ConsentPageOptions {
30
+ /** Client asking for access. */
31
+ clientId: string;
32
+ /** Scope being requested, or `undefined` when the request named none. */
33
+ scope?: string;
34
+ /** Signed-in user's login name. */
35
+ username: string;
36
+ /** Authorize URL to resume once the decision is recorded. */
37
+ returnTo: string;
38
+ }
39
+ /**
40
+ * The consent screen shown when the config sets `"consent": "prompt"`.
41
+ * Submits to `POST /consent` with `decision=approve` or `decision=deny`.
42
+ */
43
+ export declare function consentPage(options: ConsentPageOptions): string;
44
+ /** Options for {@link statusPage}. */
45
+ export interface StatusPageOptions {
46
+ /** Issuer as resolved for this request. */
47
+ issuer: string;
48
+ /** Seeded users. */
49
+ users: readonly DevIdpUserConfig[];
50
+ /** Registered clients. */
51
+ clients: readonly DevIdpClientConfig[];
52
+ }
53
+ /** The page served at `/`: what is seeded and where the endpoints are. */
54
+ export declare function statusPage(options: StatusPageOptions): string;
55
+ /** A terminal page for a flow that ended without a redirect. */
56
+ export declare function messagePage(title: string, message: string): string;
@@ -0,0 +1,190 @@
1
+ /**
2
+ * The development identity provider's HTML: a sign-in page, a consent screen,
3
+ * and the status page served at `/`.
4
+ *
5
+ * Hand-written markup with no client-side JavaScript, so the pages render the
6
+ * same in a browser and in a `fetch`-driven test. Every control a test needs
7
+ * carries a stable `id` and `name`.
8
+ *
9
+ * @module
10
+ */
11
+ const STYLE = `
12
+ :root { color-scheme: light dark; }
13
+ body {
14
+ font: 16px/1.5 system-ui, sans-serif;
15
+ margin: 0 auto; padding: 2rem 1.25rem; max-width: 40rem;
16
+ }
17
+ h1 { font-size: 1.5rem; margin: 0 0 0.25rem; }
18
+ h2 { font-size: 1.05rem; margin: 1.75rem 0 0.5rem; }
19
+ .banner {
20
+ border: 1px solid currentColor; border-radius: 6px;
21
+ padding: 0.5rem 0.75rem; margin-bottom: 1.5rem;
22
+ font-size: 0.85rem; font-weight: 600; letter-spacing: 0.02em;
23
+ }
24
+ label { display: block; margin: 0.75rem 0 0.25rem; font-size: 0.9rem; }
25
+ input {
26
+ width: 100%; padding: 0.5rem; font: inherit;
27
+ border: 1px solid currentColor; border-radius: 4px; background: transparent;
28
+ }
29
+ button {
30
+ font: inherit; padding: 0.5rem 1rem; margin: 1rem 0.5rem 0 0;
31
+ border: 1px solid currentColor; border-radius: 4px;
32
+ background: transparent; cursor: pointer;
33
+ }
34
+ .error { font-weight: 600; margin-top: 1rem; }
35
+ ul { padding-left: 1.25rem; }
36
+ li { margin: 0.25rem 0; }
37
+ code, .mono { font-family: ui-monospace, monospace; font-size: 0.9em; }
38
+ .quick { display: flex; flex-wrap: wrap; gap: 0.5rem; }
39
+ .quick button { margin: 0; }
40
+ footer { margin-top: 2rem; font-size: 0.85rem; opacity: 0.75; }
41
+ `;
42
+ function escapeHtml(value) {
43
+ return value
44
+ .replaceAll("&", "&amp;")
45
+ .replaceAll("<", "&lt;")
46
+ .replaceAll(">", "&gt;")
47
+ .replaceAll('"', "&quot;")
48
+ .replaceAll("'", "&#39;");
49
+ }
50
+ function layout(title, body) {
51
+ return `<!DOCTYPE html>
52
+ <html lang="en">
53
+ <head>
54
+ <meta charset="utf-8">
55
+ <meta name="viewport" content="width=device-width, initial-scale=1">
56
+ <meta name="robots" content="noindex">
57
+ <title>${escapeHtml(title)}</title>
58
+ <style>${STYLE}</style>
59
+ </head>
60
+ <body>
61
+ <p class="banner" id="dev-only-banner">Development identity provider — never
62
+ expose this to a network you do not control.</p>
63
+ ${body}
64
+ <footer>@udibo/oauth2 <code>idp dev</code> · in-memory, no persistence</footer>
65
+ </body>
66
+ </html>
67
+ `;
68
+ }
69
+ /** Wraps HTML in a `Response` with the headers a browser and a test expect. */
70
+ export function htmlResponse(html, status = 200) {
71
+ return new Response(html, {
72
+ status,
73
+ headers: {
74
+ "content-type": "text/html; charset=utf-8",
75
+ "cache-control": "no-store",
76
+ },
77
+ });
78
+ }
79
+ /**
80
+ * The sign-in page. Submits to `POST /login` with `username` + `password`, or
81
+ * with `as=<username>` from a one-click button.
82
+ */
83
+ export function loginPage(options) {
84
+ const { returnTo, users, error } = options;
85
+ const quickSignIn = users.length === 0
86
+ ? ""
87
+ : `
88
+ <h2>Seeded users</h2>
89
+ <div class="quick">
90
+ ${users
91
+ .map((user) => ` <button type="submit" name="as" value="${escapeHtml(user.username)}" form="sign-in-form">Sign in as ${escapeHtml(user.username)}</button>`)
92
+ .join("\n")}
93
+ </div>
94
+ <p class="mono">Passwords are printed in the startup banner.</p>`;
95
+ return layout("Sign in", `
96
+ <h1>Sign in</h1>
97
+ ${error ? `<p class="error" id="sign-in-error">${escapeHtml(error)}</p>` : ""}
98
+ <form method="post" action="/login" id="sign-in-form">
99
+ <input type="hidden" name="return_to" value="${escapeHtml(returnTo)}">
100
+ <label for="username">Username</label>
101
+ <input id="username" name="username" autocomplete="username" autofocus>
102
+ <label for="password">Password</label>
103
+ <input id="password" name="password" type="password"
104
+ autocomplete="current-password">
105
+ <button type="submit" id="sign-in">Sign in</button>
106
+ </form>
107
+ ${quickSignIn}
108
+ `);
109
+ }
110
+ /**
111
+ * The consent screen shown when the config sets `"consent": "prompt"`.
112
+ * Submits to `POST /consent` with `decision=approve` or `decision=deny`.
113
+ */
114
+ export function consentPage(options) {
115
+ const { clientId, scope, username, returnTo } = options;
116
+ return layout("Authorize application", `
117
+ <h1>Authorize application</h1>
118
+ <p><span class="mono">${escapeHtml(clientId)}</span> wants to access your
119
+ account as <span class="mono">${escapeHtml(username)}</span>.</p>
120
+ <h2>Requested scope</h2>
121
+ <p class="mono" id="requested-scope">${scope ? escapeHtml(scope) : "(no scope requested)"}</p>
122
+ <form method="post" action="/consent" id="consent-form">
123
+ <input type="hidden" name="return_to" value="${escapeHtml(returnTo)}">
124
+ <button type="submit" name="decision" value="approve" id="approve">
125
+ Approve
126
+ </button>
127
+ <button type="submit" name="decision" value="deny" id="deny">Deny</button>
128
+ </form>
129
+ `);
130
+ }
131
+ /** The page served at `/`: what is seeded and where the endpoints are. */
132
+ export function statusPage(options) {
133
+ const { issuer, users, clients } = options;
134
+ const userList = users
135
+ .map((user) => ` <li><span class="mono">${escapeHtml(user.username)}</span> · password
136
+ <span class="mono">${escapeHtml(user.password)}</span> · sub
137
+ <span class="mono">${escapeHtml(user.id)}</span></li>`)
138
+ .join("\n");
139
+ const clientList = clients
140
+ .map((client) => ` <li><span class="mono">${escapeHtml(client.id)}</span>${client.secret
141
+ ? ` · secret <span class="mono">${escapeHtml(client.secret)}</span>`
142
+ : " · public client"}<br>redirect URIs: <span class="mono">${client.redirectUris.map(escapeHtml).join(", ") || "(none)"}</span><br>grants: <span class="mono">${client.grants
143
+ .map(escapeHtml)
144
+ .join(", ")}</span></li>`)
145
+ .join("\n");
146
+ return layout("Development identity provider", `
147
+ <h1>Development identity provider</h1>
148
+ <p>Issuer <span class="mono">${escapeHtml(issuer)}</span></p>
149
+ <h2>Endpoints</h2>
150
+ <ul>
151
+ <li><a href="/.well-known/openid-configuration">
152
+ /.well-known/openid-configuration</a></li>
153
+ <li><a href="/jwks">/jwks</a></li>
154
+ <li><span class="mono">/authorize</span>,
155
+ <span class="mono">/token</span>,
156
+ <span class="mono">/userinfo</span>,
157
+ <span class="mono">/revoke</span>,
158
+ <span class="mono">/introspect</span></li>
159
+ <li><span class="mono">/login</span>,
160
+ <span class="mono">/logout</span></li>
161
+ </ul>
162
+ <h2>Users</h2>
163
+ <ul>
164
+ ${userList || " <li>(none seeded)</li>"}
165
+ </ul>
166
+ <h2>Clients</h2>
167
+ <ul>
168
+ ${clientList || " <li>(none registered)</li>"}
169
+ </ul>
170
+ <h2>Test control surface</h2>
171
+ <ul>
172
+ <li><span class="mono">POST /__admin/reset</span> — drop every session,
173
+ code, and token</li>
174
+ <li><span class="mono">POST /__admin/session</span> — sign a user in
175
+ without the form</li>
176
+ <li><span class="mono">POST /__admin/tokens</span> — mint tokens without
177
+ the browser</li>
178
+ <li><span class="mono">GET /__admin/state</span> — what is seeded right
179
+ now</li>
180
+ </ul>
181
+ `);
182
+ }
183
+ /** A terminal page for a flow that ended without a redirect. */
184
+ export function messagePage(title, message) {
185
+ return layout(title, `
186
+ <h1>${escapeHtml(title)}</h1>
187
+ <p id="message">${escapeHtml(message)}</p>
188
+ <p><a href="/">Back to the status page</a></p>
189
+ `);
190
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * The development identity provider itself: a real {@link AuthorizationServer}
3
+ * over the in-memory services, served on a socket with a sign-in page, an
4
+ * optional consent screen, and a test-control surface under `/__admin/`.
5
+ *
6
+ * Everything here is packaging — the protocol behavior is the same code an
7
+ * application runs in production. What makes it a development tool is the
8
+ * storage (memory, dropped on exit) and the admin endpoints, which mint tokens
9
+ * for any seeded user without their password.
10
+ *
11
+ * Three guardrails are enforced rather than documented: the admin endpoints
12
+ * require a startup token in a custom header (so a browser must preflight, and
13
+ * a drive-by page cannot), a non-loopback bind needs an explicit opt-in, and
14
+ * the issuer is pinned at startup instead of read from the request's `Host`.
15
+ *
16
+ * @module
17
+ */
18
+ import { type SigningKey } from "../../server/signing-keys.ts";
19
+ import type { DevIdpConfig } from "./config.ts";
20
+ /** Header the admin endpoints require, carrying the token printed at startup. */
21
+ export declare const ADMIN_TOKEN_HEADER = "x-admin-token";
22
+ /**
23
+ * Whether a bind address only accepts connections from this machine. A
24
+ * non-loopback bind exposes the admin endpoints to the network, so it needs an
25
+ * explicit opt-in.
26
+ */
27
+ export declare function isLoopbackHostname(hostname: string): boolean;
28
+ /** A running development identity provider. */
29
+ export interface DevIdentityProvider {
30
+ /** Base URL the server is reachable at. */
31
+ url: string;
32
+ /** Issuer pinned at startup and stamped into every token and metadata document. */
33
+ issuer: string;
34
+ /** Token the `/__admin/` endpoints require in {@link ADMIN_TOKEN_HEADER}. */
35
+ adminToken: string;
36
+ /** Port the server bound. Resolved when the config asked for port `0`. */
37
+ port: number;
38
+ /** Hostname the server bound. */
39
+ hostname: string;
40
+ /** Resolves once the server has finished shutting down. */
41
+ finished: Promise<void>;
42
+ /** Stops accepting connections and drains in-flight requests. */
43
+ shutdown(): Promise<void>;
44
+ }
45
+ /** Options for {@link startDevIdentityProvider}. */
46
+ export interface StartDevIdentityProviderOptions {
47
+ /** Resolved configuration, as returned by the config parser. */
48
+ config: DevIdpConfig;
49
+ /** Key the server signs id_tokens with and publishes at `/jwks`. */
50
+ signingKey: SigningKey;
51
+ /**
52
+ * Token the admin endpoints require. Generated when omitted; supply one so a
53
+ * CI job can hold it before the server starts.
54
+ */
55
+ adminToken?: string;
56
+ /**
57
+ * Permits binding a non-loopback address, which exposes the admin endpoints
58
+ * to the network. Refused unless this is explicitly set.
59
+ */
60
+ allowRemoteAccess?: boolean;
61
+ }
62
+ /**
63
+ * Starts the development identity provider on a socket and resolves once it is
64
+ * accepting connections.
65
+ *
66
+ * The caller owns the lifetime: keep the returned {@link DevIdentityProvider}
67
+ * and call `shutdown()` (a test's `finally`, a CI teardown step). Nothing is
68
+ * written to disk and no state survives the process.
69
+ *
70
+ * **This server is for development and CI only.** Its `/__admin/` endpoints
71
+ * mint tokens for any seeded user without their password; they are gated by
72
+ * {@link DevIdentityProvider.adminToken}, not by anything stronger.
73
+ *
74
+ * @throws {Error} When the config binds a non-loopback address without
75
+ * `allowRemoteAccess`.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * const idp = await startDevIdentityProvider({
80
+ * config: defaultDevIdpConfig(),
81
+ * signingKey: await generateSigningKey(),
82
+ * });
83
+ * try {
84
+ * const discovery = await fetch(
85
+ * `${idp.url}/.well-known/openid-configuration`,
86
+ * );
87
+ * // ...point the app under test at the discovered endpoints.
88
+ * } finally {
89
+ * await idp.shutdown();
90
+ * }
91
+ * ```
92
+ */
93
+ export declare function startDevIdentityProvider(options: StartDevIdentityProviderOptions): Promise<DevIdentityProvider>;